From 9c4779c0619e011415d491cde7b34c0739af9b02 Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Sun, 8 Feb 2009 09:06:00 -0800 Subject: [PATCH] Notes For V3.8 The makefile now works for Linux and most Unix's. Howevr, for Solaris and MacOS, you must first export the OSTYPE environment variable: > export OSTYPE > make Otherwise, you will get build errors. 1. New Features 1.1 3.8-0 1.1.1 SCP and Libraries - BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and show (respectively) a breakpoint at the current PC. 1.1.2 GRI - Added support for the GRI-99 processor. 1.1.3 HP2100 - Added support for the BACI terminal interface. - Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions. 1.1.4 Nova - Added support for 64KW memory (implemented in third-party CPU's). 1.1.5 PDP-11 - Added support for DC11, RC11, KE11A, KG11A. - Added modem control support for DL11. - Added ASCII character support for all 8b devices. 1.2 3.8-1 1.2.1 SCP and libraries - Added capability to set line connection order for terminal multiplexers. 1.2.2 HP2100 - Added support for 12620A/12936A privileged interrupt fence. - Added support for 12792C eight-channel asynchronous multiplexer. 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h. --- 0readme_38.txt | 19 +- AltairZ80/altairZ80_cpu.c | 563 +++- AltairZ80/altairZ80_defs.h | 25 +- AltairZ80/altairZ80_dsk.c | 154 +- AltairZ80/altairZ80_sio.c | 3125 +++++++++--------- AltairZ80/altairZ80_sys.c | 1665 +++++----- AltairZ80/altairz80_cpu_nommu.c | 125 +- AltairZ80/altairz80_hdsk.c | 178 +- AltairZ80/altairz80_net.c | 110 +- AltairZ80/disasm.c | 72 +- AltairZ80/flashwriter2.c | 65 +- AltairZ80/i8272.c | 520 +-- AltairZ80/i8272.h | 2 +- AltairZ80/i86_decode.c | 74 +- AltairZ80/i86_ops.c | 75 +- AltairZ80/i86_prim_ops.c | 751 +++-- AltairZ80/insns.h | 19 +- AltairZ80/insnsd.c | 3136 +++++++++--------- AltairZ80/mfdc.c | 54 +- AltairZ80/n8vem.c | 72 +- AltairZ80/nasm.h | 666 +--- AltairZ80/s100_64fdc.c | 502 ++- AltairZ80/s100_adcs6.c | 716 +++++ AltairZ80/s100_disk1a.c | 96 +- AltairZ80/s100_disk2.c | 108 +- AltairZ80/s100_disk3.c | 667 ++++ AltairZ80/s100_fif.c | 25 +- AltairZ80/s100_hdc1001.c | 624 ++++ AltairZ80/s100_if3.c | 371 +++ AltairZ80/s100_mdriveh.c | 33 +- AltairZ80/s100_mdsad.c | 155 +- AltairZ80/s100_scp300f.c | 103 +- AltairZ80/s100_selchan.c | 49 +- AltairZ80/s100_ss1.c | 496 ++- AltairZ80/sim_imd.c | 579 +++- AltairZ80/sim_imd.h | 57 +- AltairZ80/vfdhd.c | 91 +- AltairZ80/wd179x.c | 506 ++- GRI/gri_cpu.c | 102 +- GRI/gri_stddev.c | 42 +- GRI/gri_sys.c | 138 +- H316/h316_cpu.c | 424 ++- H316/h316_defs.h | 2 +- H316/h316_dp.c | 176 +- H316/h316_fhd.c | 82 +- H316/h316_lp.c | 60 +- H316/h316_mt.c | 87 +- H316/h316_stddev.c | 125 +- H316/h316_sys.c | 47 +- HP2100/hp2100_baci.c | 401 ++- HP2100/hp2100_bugfixes.txt | 5353 +++++++++++++++++++++++++++++++ HP2100/hp2100_cpu.c | 2595 ++++++++++----- HP2100/hp2100_cpu.h | 173 +- HP2100/hp2100_cpu0.c | 162 +- HP2100/hp2100_cpu1.c | 198 +- HP2100/hp2100_cpu1.h | 55 +- HP2100/hp2100_cpu2.c | 93 +- HP2100/hp2100_cpu3.c | 86 +- HP2100/hp2100_cpu4.c | 18 +- HP2100/hp2100_cpu5.c | 197 +- HP2100/hp2100_cpu6.c | 179 +- HP2100/hp2100_cpu7.c | 72 +- HP2100/hp2100_defs.h | 299 +- HP2100/hp2100_diag.txt | 154 +- HP2100/hp2100_dp.c | 522 ++- HP2100/hp2100_dq.c | 399 ++- HP2100/hp2100_dr.c | 384 ++- HP2100/hp2100_ds.c | 287 +- HP2100/hp2100_fp.c | 22 +- HP2100/hp2100_fp1.c | 9 + HP2100/hp2100_ipl.c | 424 ++- HP2100/hp2100_lps.c | 263 +- HP2100/hp2100_lpt.c | 166 +- HP2100/hp2100_mpx.c | 2693 ++++++++++++++++ HP2100/hp2100_ms.c | 470 ++- HP2100/hp2100_mt.c | 418 ++- HP2100/hp2100_mux.c | 1183 ++++--- HP2100/hp2100_pif.c | 367 +++ HP2100/hp2100_stddev.c | 638 ++-- HP2100/hp2100_sys.c | 99 +- I1401/i1401_cd.c | 68 +- I1401/i1401_cpu.c | 395 ++- I1401/i1401_dat.h | 2 +- I1401/i1401_defs.h | 4 +- I1401/i1401_dp.c | 150 +- I1401/i1401_iq.c | 44 +- I1401/i1401_lp.c | 35 +- I1401/i1401_mt.c | 217 +- I1401/i1401_sys.c | 110 +- I1620/i1620_cd.c | 35 +- I1620/i1620_cpu.c | 379 ++- I1620/i1620_defs.h | 2 +- I1620/i1620_dp.c | 98 +- I1620/i1620_fp.c | 93 +- I1620/i1620_lp.c | 38 +- I1620/i1620_pt.c | 38 +- I1620/i1620_sys.c | 141 +- I1620/i1620_tty.c | 59 +- I7094/i7094_binloader.c | 13 +- I7094/i7094_cd.c | 38 +- I7094/i7094_clk.c | 23 +- I7094/i7094_com.c | 232 +- I7094/i7094_cpu.c | 570 ++-- I7094/i7094_cpu1.c | 154 +- I7094/i7094_dat.h | 2 +- I7094/i7094_defs.h | 2 +- I7094/i7094_drm.c | 32 +- I7094/i7094_dsk.c | 188 +- I7094/i7094_io.c | 327 +- I7094/i7094_lp.c | 32 +- I7094/i7094_mt.c | 131 +- I7094/i7094_sys.c | 65 +- Interdata/id16_cpu.c | 274 +- Interdata/id16_dboot.c | 5 +- Interdata/id16_sys.c | 125 +- Interdata/id32_cpu.c | 356 +- Interdata/id32_dboot.c | 8 +- Interdata/id32_sys.c | 156 +- Interdata/id_dp.c | 99 +- Interdata/id_fd.c | 65 +- Interdata/id_fp.c | 40 +- Interdata/id_idc.c | 72 +- Interdata/id_io.c | 176 +- Interdata/id_lp.c | 48 +- Interdata/id_mt.c | 68 +- Interdata/id_pas.c | 102 +- Interdata/id_pt.c | 53 +- Interdata/id_tt.c | 38 +- Interdata/id_ttp.c | 35 +- Interdata/id_uvc.c | 38 +- LGP/lgp_cpu.c | 109 +- LGP/lgp_defs.h | 2 +- LGP/lgp_stddev.c | 82 +- LGP/lgp_sys.c | 92 +- NOVA/nova_clk.c | 6 +- NOVA/nova_cpu.c | 162 +- NOVA/nova_dkp.c | 34 +- NOVA/nova_dsk.c | 15 +- NOVA/nova_mta.c | 57 +- NOVA/nova_pt.c | 3 +- NOVA/nova_qty.c | 61 +- NOVA/nova_sys.c | 133 +- NOVA/nova_tt1.c | 45 +- PDP1/pdp1_clk.c | 5 +- PDP1/pdp1_cpu.c | 411 ++- PDP1/pdp1_dcs.c | 97 +- PDP1/pdp1_defs.h | 2 +- PDP1/pdp1_drm.c | 29 +- PDP1/pdp1_dt.c | 138 +- PDP1/pdp1_lp.c | 11 +- PDP1/pdp1_stddev.c | 62 +- PDP1/pdp1_sys.c | 112 +- PDP10/pdp10_cpu.c | 282 +- PDP10/pdp10_defs.h | 3 +- PDP10/pdp10_fe.c | 6 +- PDP10/pdp10_ksio.c | 186 +- PDP10/pdp10_lp20.c | 115 +- PDP10/pdp10_mdfp.c | 139 +- PDP10/pdp10_pag.c | 167 +- PDP10/pdp10_rp.c | 115 +- PDP10/pdp10_sys.c | 149 +- PDP10/pdp10_tim.c | 15 +- PDP10/pdp10_tu.c | 189 +- PDP10/pdp10_xtnd.c | 134 +- PDP11/pdp11_cis.c | 180 +- PDP11/pdp11_cpu.c | 506 ++- PDP11/pdp11_cpumod.c | 116 +- PDP11/pdp11_cr.c | 2 +- PDP11/pdp11_dc.c | 87 +- PDP11/pdp11_defs.h | 13 +- PDP11/pdp11_dl.c | 103 +- PDP11/pdp11_dz.c | 143 +- PDP11/pdp11_fp.c | 156 +- PDP11/pdp11_hk.c | 132 +- PDP11/pdp11_io.c | 422 +-- PDP11/pdp11_io_lib.c | 521 +++ PDP11/pdp11_io_lib.h | 44 + PDP11/pdp11_lp.c | 25 +- PDP11/pdp11_mscp.h | 2 +- PDP11/pdp11_pclk.c | 17 +- PDP11/pdp11_pt.c | 35 +- PDP11/pdp11_rf.c | 43 +- PDP11/pdp11_rh.c | 171 +- PDP11/pdp11_rk.c | 78 +- PDP11/pdp11_rl.c | 97 +- PDP11/pdp11_rp.c | 99 +- PDP11/pdp11_rq.c | 252 +- PDP11/pdp11_rx.c | 32 +- PDP11/pdp11_ry.c | 41 +- PDP11/pdp11_stddev.c | 57 +- PDP11/pdp11_sys.c | 76 +- PDP11/pdp11_ta.c | 62 +- PDP11/pdp11_tc.c | 163 +- PDP11/pdp11_tm.c | 103 +- PDP11/pdp11_tq.c | 255 +- PDP11/pdp11_ts.c | 129 +- PDP11/pdp11_tu.c | 153 +- PDP11/pdp11_uqssp.h | 2 +- PDP11/pdp11_vh.c | 57 +- PDP11/pdp11_xq.h | 2 +- PDP11/pdp11_xq_bootrom.h | 2 +- PDP11/pdp11_xu.h | 2 +- PDP18B/pdp18b_cpu.c | 547 ++-- PDP18B/pdp18b_defs.h | 2 +- PDP18B/pdp18b_drm.c | 26 +- PDP18B/pdp18b_dt.c | 213 +- PDP18B/pdp18b_fpp.c | 142 +- PDP18B/pdp18b_lp.c | 101 +- PDP18B/pdp18b_mt.c | 70 +- PDP18B/pdp18b_rb.c | 44 +- PDP18B/pdp18b_rf.c | 49 +- PDP18B/pdp18b_rp.c | 71 +- PDP18B/pdp18b_stddev.c | 92 +- PDP18B/pdp18b_sys.c | 157 +- PDP18B/pdp18b_tt1.c | 121 +- PDP8/pdp8_clk.c | 11 +- PDP8/pdp8_cpu.c | 288 +- PDP8/pdp8_ct.c | 62 +- PDP8/pdp8_defs.h | 2 +- PDP8/pdp8_df.c | 29 +- PDP8/pdp8_dt.c | 133 +- PDP8/pdp8_fpp.c | 28 +- PDP8/pdp8_lp.c | 2 +- PDP8/pdp8_mt.c | 56 +- PDP8/pdp8_pt.c | 11 +- PDP8/pdp8_rf.c | 35 +- PDP8/pdp8_rk.c | 44 +- PDP8/pdp8_rl.c | 77 +- PDP8/pdp8_rx.c | 74 +- PDP8/pdp8_sys.c | 48 +- PDP8/pdp8_td.c | 86 +- PDP8/pdp8_tsc.c | 5 +- PDP8/pdp8_tt.c | 11 +- PDP8/pdp8_ttx.c | 65 +- SDS/sds_cpu.c | 602 ++-- SDS/sds_defs.h | 2 +- SDS/sds_drm.c | 32 +- SDS/sds_dsk.c | 50 +- SDS/sds_io.c | 202 +- SDS/sds_lp.c | 64 +- SDS/sds_mt.c | 71 +- SDS/sds_mux.c | 95 +- SDS/sds_rad.c | 44 +- SDS/sds_stddev.c | 38 +- SDS/sds_sys.c | 112 +- VAX/vax780_defs.h | 14 +- VAX/vax780_fload.c | 24 +- VAX/vax780_mba.c | 137 +- VAX/vax780_mem.c | 8 +- VAX/vax780_sbi.c | 77 +- VAX/vax780_stddev.c | 89 +- VAX/vax780_syslist.c | 17 +- VAX/vax780_uba.c | 439 +-- VAX/vax_cis.c | 168 +- VAX/vax_cmode.c | 599 ++-- VAX/vax_cpu.c | 387 ++- VAX/vax_cpu1.c | 265 +- VAX/vax_defs.h | 2 +- VAX/vax_fpa.c | 344 +- VAX/vax_io.c | 440 +-- VAX/vax_mmu.c | 102 +- VAX/vax_octa.c | 184 +- VAX/vax_stddev.c | 46 +- VAX/vax_sys.c | 275 +- VAX/vax_syscm.c | 78 +- VAX/vax_sysdev.c | 105 +- VAX/vax_syslist.c | 11 +- VAX/vaxmod_defs.h | 11 +- descrip.mms | 10 +- makefile | 17 +- scp.c | 1299 +++++--- scp.h | 2 +- sim_console.c | 260 +- sim_console.h | 2 +- sim_defs.h | 9 +- sim_fio.c | 26 +- sim_fio.h | 2 +- sim_rev.h | 184 +- sim_sock.c | 35 +- sim_sock.h | 2 +- sim_tape.c | 147 +- sim_tape.h | 2 +- sim_timer.c | 93 +- sim_timer.h | 5 +- sim_tmxr.c | 402 ++- sim_tmxr.h | 13 +- 286 files changed, 40587 insertions(+), 19094 deletions(-) create mode 100644 AltairZ80/s100_adcs6.c create mode 100644 AltairZ80/s100_disk3.c create mode 100644 AltairZ80/s100_hdc1001.c create mode 100644 AltairZ80/s100_if3.c create mode 100644 HP2100/hp2100_bugfixes.txt create mode 100644 HP2100/hp2100_mpx.c create mode 100644 HP2100/hp2100_pif.c create mode 100644 PDP11/pdp11_io_lib.c create mode 100644 PDP11/pdp11_io_lib.h diff --git a/0readme_38.txt b/0readme_38.txt index 3ba9383c..ffa2798b 100644 --- a/0readme_38.txt +++ b/0readme_38.txt @@ -19,25 +19,36 @@ Otherwise, you will get build errors. - BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and show (respectively) a breakpoint at the current PC. -1.2 GRI +1.1.2 GRI - Added support for the GRI-99 processor. -1.3 HP2100 +1.1.3 HP2100 - Added support for the BACI terminal interface. - Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions. -1.4 Nova +1.1.4 Nova - Added support for 64KW memory (implemented in third-party CPU's). -1.5 PDP-11 +1.1.5 PDP-11 - Added support for DC11, RC11, KE11A, KG11A. - Added modem control support for DL11. - Added ASCII character support for all 8b devices. +1.2 3.8-1 + +1.2.1 SCP and libraries + +- Added capability to set line connection order for terminal multiplexers. + +1.2.2 HP2100 + +- Added support for 12620A/12936A privileged interrupt fence. +- Added support for 12792C eight-channel asynchronous multiplexer. + 2. Bugs Fixed diff --git a/AltairZ80/altairZ80_cpu.c b/AltairZ80/altairZ80_cpu.c index 7d696cd1..26c54e2c 100644 --- a/AltairZ80/altairZ80_cpu.c +++ b/AltairZ80/altairZ80_cpu.c @@ -31,6 +31,10 @@ #include #define SWITCHCPU_DEFAULT 0xfd +/* Debug flags */ +#define IN_MSG (1 << 0) +#define OUT_MSG (1 << 1) + #if defined (_WIN32) #include #else @@ -139,23 +143,20 @@ 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 void install_ALTAIRbootROM(void); -extern char messageBuffer[]; -extern void printMessage(void); extern void do_SIMH_sleep(void); +extern FILE *sim_deb; + extern t_stat sim_instr_nommu(void); extern uint8 MOPT[MAXBANKSIZE]; extern t_stat sim_instr_8086(void); -extern t_stat sim_instr_8086(void); extern void cpu8086reset(void); /* function prototypes */ -#ifdef CPUSWITCHER static t_stat cpu_set_switcher (UNIT *uptr, int32 value, char *cptr, void *desc); static t_stat cpu_reset_switcher(UNIT *uptr, int32 value, char *cptr, void *desc); static t_stat cpu_show_switcher (FILE *st, UNIT *uptr, int32 val, void *desc); static int32 switchcpu_io (const int32 port, const int32 io, const int32 data); -#endif static t_stat cpu_set_altairrom (UNIT *uptr, int32 value, char *cptr, void *desc); static t_stat cpu_set_noaltairrom (UNIT *uptr, int32 value, char *cptr, void *desc); @@ -184,6 +185,8 @@ t_stat sim_instr(void); t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); uint8 GetBYTEWrapper(const uint32 Addr); void PutBYTEWrapper(const uint32 Addr, const uint32 Value); +uint8 GetByteDMA(const uint32 Addr); +void PutByteDMA(const uint32 Addr, const uint32 Value); int32 getBankSelect(void); void setBankSelect(const int32 b); uint32 getCommon(void); @@ -193,6 +196,7 @@ uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, void PutBYTEExtended(register uint32 Addr, const register uint32 Value); uint32 GetBYTEExtended(register uint32 Addr); +void cpu_raise_interrupt(uint32 irq); /* CPU data structures cpu_dev CPU device descriptor @@ -213,7 +217,8 @@ UNIT cpu_unit = { int32 HL_S; /* HL register */ int32 IX_S; /* IX register */ int32 IY_S; /* IY register */ - int32 PC_S = 0; /* program counter */ + int32 PC_S = 0; /* 8080 / Z80 program counter */ + int32 PCX_S = 0xFFFF0; /* 8086 program counter */ int32 SP_S; /* SP register */ int32 AF1_S; /* alternate AF register */ int32 BC1_S; /* alternate BC register */ @@ -232,7 +237,7 @@ UNIT cpu_unit = { int32 DI_S; /* DI register (8086) */ int32 SI_S; /* SI register (8086) */ int32 BP_S; /* BP register (8086) */ - int32 SP8086_S; /* SP register (8086) */ + int32 SPX_S; /* SP register (8086) */ int32 IP_S; /* IP register (8086) */ int32 FLAGS_S; /* flags register (8086) */ int32 SR = 0; /* switch register */ @@ -243,9 +248,7 @@ static uint32 clockFrequency = 0; /* in kHz, 0 means as fast a 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 uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ static int32 pcq_p = 0; /* PC queue ptr */ static REG *pcq_r = NULL; /* PC queue reg ptr */ @@ -254,10 +257,8 @@ struct idev { int32 (*routine)(const int32, const int32, const int32); }; -#ifdef CPUSWITCHER static int32 switcherPort = SWITCHCPU_DEFAULT; static struct idev oldSwitcherDevice = { NULL }; -#endif REG cpu_reg[] = { { HRDATA (AF, AF_S, 16) }, @@ -266,7 +267,8 @@ REG cpu_reg[] = { { HRDATA (HL, HL_S, 16) }, { HRDATA (IX, IX_S, 16) }, { HRDATA (IY, IY_S, 16) }, - { HRDATA (PC, PC_S, 16 + MAXBANKSLOG2) }, + { HRDATA (PC, PC_S, 16 + MAXBANKSLOG2) }, /* 8080 / Z80 PC [6] */ + { HRDATA (PCX, PCX_S, 16 + MAXBANKSLOG2) }, /* 8086 PC [7] */ { HRDATA (SP, SP_S, 16) }, { HRDATA (AF1, AF1_S, 16) }, { HRDATA (BC1, BC1_S, 16) }, @@ -286,7 +288,7 @@ REG cpu_reg[] = { { HRDATA (DX, DX_S, 16) }, /* 8086 */ { GRDATA (DL, DX_S, 16, 8, 0) }, /* 8086, low 8 bits of DX */ { GRDATA (DH, DX_S, 16, 8, 8) }, /* 8086, high 8 bits of DX */ - { HRDATA (SP86, SP8086_S, 16) }, /* 8086 */ + { HRDATA (SPX, SPX_S, 16) }, /* 8086 */ { HRDATA (BP, BP_S, 16) }, /* 8086, Base Pointer */ { HRDATA (SI, SI_S, 16) }, /* 8086, Source Index */ { HRDATA (DI, DI_S, 16) }, /* 8086, Destination Index */ @@ -300,9 +302,7 @@ REG cpu_reg[] = { { HRDATA (SR, SR, 8) }, { HRDATA (BANK, bankSelect, MAXBANKSLOG2) }, { HRDATA (COMMON, common, 32) }, -#ifdef CPUSWITCHER { HRDATA (SWITCHERPORT, switcherPort, 8), }, -#endif { DRDATA (CLOCK, clockFrequency, 32) }, { DRDATA (SLICE, sliceLength, 16) }, { DRDATA (TSTATES, executedTStates, 32), REG_RO }, @@ -332,10 +332,8 @@ static MTAB cpu_mod[] = { { UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL }, { UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu }, { MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory }, -#ifdef CPUSWITCHER { UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher }, { UNIT_CPU_SWITCHER, 0, "NOSWITCHER", "NOSWITCHER", &cpu_reset_switcher, &cpu_show_switcher }, -#endif { MTAB_XTD | MTAB_VDV, 0, NULL, "AZ80", &cpu_set_ramtype }, { MTAB_XTD | MTAB_VDV, 1, NULL, "HRAM", &cpu_set_ramtype }, { MTAB_XTD | MTAB_VDV, 2, NULL, "VRAM", &cpu_set_ramtype }, @@ -359,13 +357,20 @@ static MTAB cpu_mod[] = { { 0 } }; +/* Debug Flags */ +static DEBTAB cpu_dt[] = { + { "LOG_IN", IN_MSG }, + { "LOG_OUT", OUT_MSG }, + { NULL, 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 + NULL, DEV_DEBUG, 0, + cpu_dt, NULL, NULL }; /* This is the I/O configuration table. There are 255 possible @@ -429,7 +434,7 @@ static struct idev dev_table[256] = { {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D4 */ {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D8 */ {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* DC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */ + {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E0 */ {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E4 */ {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E8 */ {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* EC */ @@ -440,14 +445,38 @@ static struct idev dev_table[256] = { }; static int32 ramtype = 0; +#define MAX_RAM_TYPE 3 + int32 chiptype = CHIP_TYPE_8080; void out(const uint32 Port, const uint32 Value) { + if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) { + fprintf(sim_deb, "CPU: " ADDRESS_FORMAT + " OUT(port=0x%04x [%5d], value=0x%04x [%5d])\n", PCX, Port, Port, Value, Value); + fflush(sim_deb); + } dev_table[Port & 0xff].routine(Port, 1, Value); + if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) { + fprintf(sim_deb, "CPU: " ADDRESS_FORMAT + " OUT(port=0x%04x [%5d], value=0x%04x [%5d]) done\n", PCX, Port, Port, Value, Value); + fflush(sim_deb); + } } uint32 in(const uint32 Port) { - return dev_table[Port & 0xff].routine(Port, 0, 0); + uint32 result; + if ((cpu_dev.dctrl & IN_MSG) && sim_deb) { + fprintf(sim_deb, "CPU: " ADDRESS_FORMAT + " IN(port=0x%04x [%5d])\n", PCX, Port, Port); + fflush(sim_deb); + } + result = dev_table[Port & 0xff].routine(Port, 0, 0); + if ((cpu_dev.dctrl & IN_MSG) && sim_deb) { + fprintf(sim_deb, "CPU: " ADDRESS_FORMAT + " IN(port=0x%04x [%5d]) = 0x%04x [%5d]\n", PCX, Port, Port, result, result); + fflush(sim_deb); + } + return result; } /* the following tables precompute some common subexpressions @@ -1605,15 +1634,15 @@ static void PutBYTE(register uint32 Addr, const register uint32 Value) { Addr |= bankSelect << MAXBANKSIZELOG2; m = mmu_table[Addr >> LOG2PAGESIZE]; - if (m.isRAM) M[Addr] = Value; - else if (m.routine) m.routine(Addr, 1, Value); + if (m.isRAM) + M[Addr] = Value; + else if (m.routine) + m.routine(Addr, 1, Value); else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - if (m.isEmpty) { - MESSAGE_2("Attempt to write to non existing memory " ADDRESS_FORMAT ".", Addr); - } - else { - MESSAGE_2("Attempt to write to ROM " ADDRESS_FORMAT ".", Addr); - } + if (m.isEmpty) + printf("CPU: " ADDRESS_FORMAT " Attempt to write to non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); + else + printf("CPU: " ADDRESS_FORMAT " Attempt to write to ROM " ADDRESS_FORMAT "." NLP, PCX, Addr); } } @@ -1623,15 +1652,15 @@ void PutBYTEExtended(register uint32 Addr, const register uint32 Value) { Addr &= ADDRMASKEXTENDED; m = mmu_table[Addr >> LOG2PAGESIZE]; - if (m.isRAM) M[Addr] = Value; - else if (m.routine) m.routine(Addr, 1, Value); + if (m.isRAM) + M[Addr] = Value; + else if (m.routine) + m.routine(Addr, 1, Value); else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - if (m.isEmpty) { - MESSAGE_2("Attempt to write to non existing memory " ADDRESS_FORMAT ".", Addr); - } - else { - MESSAGE_2("Attempt to write to ROM " ADDRESS_FORMAT ".", Addr); - } + if (m.isEmpty) + printf("CPU: " ADDRESS_FORMAT " Attempt to write to non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); + else + printf("CPU: " ADDRESS_FORMAT " Attempt to write to ROM " ADDRESS_FORMAT "." NLP, PCX, Addr); } } @@ -1648,12 +1677,13 @@ static uint32 GetBYTE(register uint32 Addr) { Addr |= bankSelect << MAXBANKSIZELOG2; m = mmu_table[Addr >> LOG2PAGESIZE]; - if (m.isRAM) return M[Addr]; /* RAM */ - if (m.routine) return m.routine(Addr, 0, 0); /* memory mapped I/O */ + if (m.isRAM) + return M[Addr]; /* RAM */ + if (m.routine) + return m.routine(Addr, 0, 0); /* memory mapped I/O */ if (m.isEmpty) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - MESSAGE_2("Attempt to read from non existing memory " ADDRESS_FORMAT ".", Addr); - } + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("CPU: " ADDRESS_FORMAT " Attempt to read from non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); return 0xff; } return M[Addr]; /* ROM */ @@ -1665,12 +1695,13 @@ uint32 GetBYTEExtended(register uint32 Addr) { Addr &= ADDRMASKEXTENDED; m = mmu_table[Addr >> LOG2PAGESIZE]; - if (m.isRAM) return M[Addr]; - if (m.routine) return m.routine(Addr, 0, 0); + if (m.isRAM) + return M[Addr]; + if (m.routine) + return m.routine(Addr, 0, 0); if (m.isEmpty) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - MESSAGE_2("Attempt to read from non existing memory " ADDRESS_FORMAT ".", Addr); - } + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("CPU: " ADDRESS_FORMAT " Attempt to read from non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); return 0xff; } return M[Addr]; @@ -1708,6 +1739,21 @@ void PutBYTEWrapper(const uint32 Addr, const uint32 Value) { MOPT[Addr & ADDRMASK] = Value & 0xff; } +/* DMA memory access during a simulation, suggested by Tony Nicholson */ +uint8 GetByteDMA(const uint32 Addr) { + if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) + return GetBYTEExtended(Addr); + else + return MOPT[Addr & ADDRMASK]; +} + +void PutByteDMA(const uint32 Addr, const uint32 Value) { + if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) + PutBYTEExtended(Addr, Value); + else + MOPT[Addr & ADDRMASK] = Value & 0xff; +} + #define RAM_PP(Addr) GetBYTE(Addr++) #define RAM_MM(Addr) GetBYTE(Addr--) #define GET_WORD(Addr) (GetBYTE(Addr) | (GetBYTE(Addr + 1) << 8)) @@ -1741,7 +1787,7 @@ static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) { static void prepareMemoryAccessMessage(t_addr loc) { extern char memoryAccessMessage[]; - sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc); + sprintf(memoryAccessMessage, "Memory access breakpoint [%05xh]", loc); } #define PUSH(x) { \ @@ -1812,14 +1858,22 @@ static void prepareMemoryAccessMessage(t_addr loc) { #define INOUTFLAGS_NONZERO(x) \ INOUTFLAGS((HIGH_REGISTER(BC) & 0xa8) | ((HIGH_REGISTER(BC) == 0) << 6), x) +int32 switch_cpu_now = TRUE; /* hharte */ + t_stat sim_instr (void) { uint32 i; t_stat result; - if (chiptype == CHIP_TYPE_8086) return sim_instr_8086(); - if (cpu_unit.flags & UNIT_CPU_MMU) return sim_instr_mmu(); - for (i = 0; i < MAXBANKSIZE; i++) MOPT[i] = M[i]; - result = sim_instr_nommu(); - for (i = 0; i < MAXBANKSIZE; i++) M[i] = MOPT[i]; + if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) + do { + result = (chiptype == CHIP_TYPE_8086) ? sim_instr_8086() : sim_instr_mmu(); + } while (switch_cpu_now == FALSE); + else { + for (i = 0; i < MAXBANKSIZE; i++) + MOPT[i] = M[i]; + result = sim_instr_nommu(); + for (i = 0; i < MAXBANKSIZE; i++) + M[i] = MOPT[i]; + } return result; } @@ -1833,7 +1887,7 @@ static t_stat sim_instr_mmu (void) { extern uint32 sim_os_msec(void); extern const t_bool rtc_avail; extern uint32 sim_brk_summ; - int32 reason = 0; + int32 reason = SCPE_OK; register uint32 specialProcessing; register uint32 AF; register uint32 BC; @@ -1856,6 +1910,8 @@ static t_stat sim_instr_mmu (void) { uint32 startTime, now; int32 br1, br2, tStateModifier = FALSE; + switch_cpu_now = TRUE; /* hharte */ + AF = AF_S; BC = BC_S; DE = DE_S; @@ -1875,14 +1931,15 @@ static t_stat sim_instr_mmu (void) { } /* main instruction fetch/decode loop */ - while (TRUE) { /* loop until halted */ + while (switch_cpu_now == TRUE) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ #if !UNIX_PLATFORM if ((reason = sim_os_poll_kbd()) == SCPE_STOP) { /* poll on platforms without reliable signalling */ break; } #endif - if ( (reason = sim_process_event()) ) break; + if ( (reason = sim_process_event()) ) + break; else specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ; } @@ -2258,14 +2315,16 @@ static t_stat sim_instr_mmu (void) { acu -= 6; acu &= 0xff; } - if (hd) acu -= 0x160; /* adjust high digit */ + if (hd) + acu -= 0x160; /* adjust high digit */ } 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)) acu += 0x60; /* adjust high digit */ + if (cbits || ((acu & 0x1f0) > 0x90)) + acu += 0x60; /* adjust high digit */ } AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | ((acu >> 8) & 1) | cbits; break; @@ -3582,11 +3641,14 @@ static t_stat sim_instr_mmu (void) { break; case 0x40: /* BIT */ - if (tStateModifier) tStates -= 3; + 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); + else + AF = (AF & ~0xfe) | 0x54; + if ((op & 7) != 6) + AF |= (acu & 0x28); temp = acu; break; @@ -4444,8 +4506,10 @@ static t_stat sim_instr_mmu (void) { 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); + else + AF = (AF & ~0xfe) | 0x54; + if ((op & 7) != 6) + AF |= (acu & 0x28); temp = acu; break; @@ -5044,7 +5108,8 @@ static t_stat sim_instr_mmu (void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; /* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. @@ -5105,7 +5170,8 @@ static t_stat sim_instr_mmu (void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; /* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. @@ -5141,7 +5207,8 @@ static t_stat sim_instr_mmu (void) { tStates -= 5; acu = HIGH_REGISTER(AF); BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { tStates += 21; CHECK_BREAK_TWO_BYTES(HL, DE); @@ -5156,7 +5223,8 @@ static t_stat sim_instr_mmu (void) { tStates -= 5; acu = HIGH_REGISTER(AF); BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { tStates += 21; CHECK_BREAK_BYTE(HL); @@ -5169,13 +5237,15 @@ static t_stat sim_instr_mmu (void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; case 0xb2: /* INIR */ tStates -= 5; temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { tStates += 21; CHECK_BREAK_BYTE(HL); @@ -5191,7 +5261,8 @@ static t_stat sim_instr_mmu (void) { case 0xb3: /* OTIR */ tStates -= 5; temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { tStates += 21; CHECK_BREAK_BYTE(HL); @@ -5207,7 +5278,8 @@ static t_stat sim_instr_mmu (void) { case 0xb8: /* LDDR */ tStates -= 5; BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { tStates += 21; CHECK_BREAK_TWO_BYTES(HL, DE); @@ -5222,7 +5294,8 @@ static t_stat sim_instr_mmu (void) { tStates -= 5; acu = HIGH_REGISTER(AF); BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { tStates += 21; CHECK_BREAK_BYTE(HL); @@ -5235,13 +5308,15 @@ static t_stat sim_instr_mmu (void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; case 0xba: /* INDR */ tStates -= 5; temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { tStates += 21; CHECK_BREAK_BYTE(HL); @@ -5257,7 +5332,8 @@ static t_stat sim_instr_mmu (void) { case 0xbb: /* OTDR */ tStates -= 5; temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { tStates += 21; CHECK_BREAK_BYTE(HL); @@ -6060,8 +6136,10 @@ static t_stat sim_instr_mmu (void) { 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); + else + AF = (AF & ~0xfe) | 0x54; + if ((op & 7) != 6) + AF |= (acu & 0x28); temp = acu; break; @@ -6171,6 +6249,14 @@ static t_stat sim_instr_mmu (void) { PC = 0x38; } } + + /* It we stopped processing instructions because of a switch to the other + * CPU, then fixup the reason code. + */ + if (switch_cpu_now == FALSE) { + reason = SCPE_OK; + } + end_decode: /* simulation halted */ @@ -6201,17 +6287,21 @@ static t_stat cpu_reset(DEVICE *dptr) { cpu8086reset(); sim_brk_types = (SWMASK('E') | SWMASK('I') | SWMASK('M')); sim_brk_dflt = SWMASK('E'); - for (i = 0; i < PCQ_SIZE; i++) pcq[i] = 0; + 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; + if (pcq_r) + pcq_r -> qptr = 0; + else + return SCPE_IERR; return SCPE_OK; } t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM) { int32 i; - if (addr & (PAGESIZE - 1)) return SCPE_IERR; + if (addr & (PAGESIZE - 1)) + return SCPE_IERR; for (i = 0; i < size; i++) { if (makeROM && ((i & (PAGESIZE - 1)) == 0)) mmu_table[(i + addr) >> LOG2PAGESIZE] = ROM_PAGE; @@ -6223,7 +6313,8 @@ t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM) { /* memory examine */ static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { int32 oldBankSelect; - if (chiptype == CHIP_TYPE_8086) *vptr = GetBYTEExtended(addr); + if (chiptype == CHIP_TYPE_8086) + *vptr = GetBYTEExtended(addr); else { oldBankSelect = getBankSelect(); setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK); @@ -6236,7 +6327,8 @@ static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { /* memory deposit */ static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) { int32 oldBankSelect; - if (chiptype == CHIP_TYPE_8086) PutBYTEExtended(addr, val); + if (chiptype == CHIP_TYPE_8086) + PutBYTEExtended(addr, val); else { oldBankSelect = getBankSelect(); setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK); @@ -6246,34 +6338,107 @@ static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) { return SCPE_OK; } +struct cpuflag { + int32 mask; /* bit mask within CPU status register */ + char name; /* character to print if flag is set */ +}; +typedef struct cpuflag CPUFLAG; + +static CPUFLAG cpuflags8086[] = { + {1 << 11, 'O'}, + {1 << 10, 'D'}, + {1 << 9, 'I'}, + {1 << 8, 'T'}, + {1 << 7, 'S'}, + {1 << 6, 'Z'}, + {1 << 4, 'A'}, + {1 << 2, 'P'}, + {1 << 0, 'C'}, + {0, 0} /* last mask must be 0 */ +}; + +static CPUFLAG cpuflags8080[] = { + {1 << 7, 'S'}, + {1 << 6, 'Z'}, + {1 << 4, 'A'}, + {1 << 3, 'P'}, + {1 << 1, 'N'}, + {1 << 0, 'C'}, + {0, 0} /* last mask must be 0 */ +}; + +static CPUFLAG cpuflagsZ80[] = { + {1 << 7, 'S'}, + {1 << 6, 'Z'}, + {1 << 4, 'A'}, + {1 << 3, 'V'}, + {1 << 1, 'N'}, + {1 << 0, 'C'}, + {0, 0} /* last mask must be 0 */ +}; + +/* needs to be set for each chiptype <= MAX_CHIP_TYPE */ +static char *chipTypeToString[] = { "8080", "Z80", "8086" }; +static int32 *flagregister[] = { &AF_S, &AF_S, &FLAGS_S }; +static CPUFLAG *cpuflags[] = { cpuflags8080, cpuflagsZ80, cpuflags8086 }; + +/* needs to be set for each ramtype <= MAX_RAM_TYPE */ +static char *ramTypeToString[] = { "AZ80", "HRAM", "VRAM", "CRAM" }; + static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) { fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, "); - if (chiptype == CHIP_TYPE_8080) fprintf(st, "8080"); - else if (chiptype == CHIP_TYPE_Z80) fprintf(st, "Z80"); - else if (chiptype == CHIP_TYPE_8086) fprintf(st, "8086"); + if (chiptype <= MAX_CHIP_TYPE) + fprintf(st, chipTypeToString[chiptype]); fprintf(st, ", "); - if (ramtype == 0) fprintf(st, "AZ80"); - else if (ramtype == 1) fprintf(st, "HRAM"); - else if (ramtype == 2) fprintf(st, "VRAM"); - else if (ramtype == 3) fprintf(st, "CRAM"); + if (ramtype <= MAX_RAM_TYPE) + fprintf(st, ramTypeToString[ramtype]); return SCPE_OK; } static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, void *desc) { - uint32 i, maxBanks; + uint32 i, maxBanks, first = TRUE; MDEV m; maxBanks = ((cpu_unit.flags & UNIT_CPU_BANKED) || (chiptype == CHIP_TYPE_8086)) ? MAXBANKS : 1; fprintf(st, "VERBOSE,\n "); - for (i = 0; i < 4; i++) fprintf(st, "0123456789ABCDEF"); + for (i = 0; i < 4; i++) + fprintf(st, "0123456789ABCDEF"); fprintf(st, " [16k]"); for (i = 0; i < (maxBanks * (MAXBANKSIZE >> LOG2PAGESIZE)); i++) { - if ((i & 0x3f) == 0) fprintf(st, "\n%05X: ", (i << LOG2PAGESIZE)); + if ((i & 0x3f) == 0) + fprintf(st, "\n%05X: ", (i << LOG2PAGESIZE)); m = mmu_table[i]; - if (m.isRAM) fprintf(st, "W"); - else if (m.isEmpty) fprintf(st, "U"); - else if (m.routine) fprintf(st, "M"); - else fprintf(st, "R"); + if (m.isRAM) + fprintf(st, "W"); + else if (m.isEmpty) + fprintf(st, "U"); + else if (m.routine) + fprintf(st, "M"); + else + fprintf(st, "R"); + } + fprintf(st, ",\n0x["); + /* show which ports are assigned */ + for (i = 0; i < 256; i++) + if (dev_table[i].routine != &nulldev) { + if (first) + first = FALSE; + else + fprintf(st, " "); + fprintf(st, "%02X", i); + } + fprintf(st, "]"); + if (chiptype <= MAX_CHIP_TYPE) { + first = TRUE; + /* show verbose CPU flags */ + for (i = 0; cpuflags[chiptype][i].mask; i++) + if (*flagregister[chiptype] & cpuflags[chiptype][i].mask) { + if (first) { + first = FALSE; + fprintf(st, " "); + } + fprintf(st, "%c", cpuflags[chiptype][i].name); + } } return SCPE_OK; } @@ -6281,10 +6446,12 @@ static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, void *desc) { static void cpu_clear(void) { uint32 i; for (i = 0; i < MAXMEMORY; i++) M[i] = 0; - for (i = 0; i < (MAXMEMORY >> LOG2PAGESIZE); i++) mmu_table[i] = RAM_PAGE; + for (i = 0; i < (MAXMEMORY >> LOG2PAGESIZE); i++) + mmu_table[i] = RAM_PAGE; for (i = (MEMORYSIZE >> LOG2PAGESIZE); i < (MAXMEMORY >> LOG2PAGESIZE); i++) mmu_table[i] = EMPTY_PAGE; - if (cpu_unit.flags & UNIT_CPU_ALTAIRROM) install_ALTAIRbootROM(); + if (cpu_unit.flags & UNIT_CPU_ALTAIRROM) + install_ALTAIRbootROM(); } static t_stat cpu_clear_command(UNIT *uptr, int32 value, char *cptr, void *desc) { @@ -6323,7 +6490,8 @@ static t_stat cpu_set_nommu(UNIT *uptr, int32 value, char *cptr, void *desc) { static t_stat cpu_set_banked(UNIT *uptr, int32 value, char *cptr, void *desc) { if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { - if (MEMORYSIZE <= MAXBANKSIZE) previousCapacity = MEMORYSIZE; + if (MEMORYSIZE <= MAXBANKSIZE) + previousCapacity = MEMORYSIZE; MEMORYSIZE = MAXMEMORY; cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2; cpu_clear(); @@ -6345,10 +6513,10 @@ static t_stat cpu_set_nonbanked(UNIT *uptr, int32 value, char *cptr, void *desc) } static int32 bankseldev(const int32 port, const int32 io, const int32 data) { - if(io) { + if (io) { switch(ramtype) { case 1: - if(data & 0x40) { + if (data & 0x40) { printf("HRAM: Parity %s" NLP, data & 1 ? "ON" : "OFF"); } else { printf("HRAM BANKSEL=%02x" NLP, data); @@ -6358,11 +6526,11 @@ static int32 bankseldev(const int32 port, const int32 io, const int32 data) { /* printf("VRAM BANKSEL=%02x" NLP, data);*/ switch(data & 0xFF) { case 0x01: -/* case 0x41: // OASIS uses this for some reason?*/ +/* case 0x41: // OASIS uses this for some reason? */ setBankSelect(0); break; case 0x02: -/* case 0x42: // OASIS uses this for some reason?*/ +/* case 0x42: // OASIS uses this for some reason? */ setBankSelect(1); break; case 0x04: @@ -6389,7 +6557,37 @@ static int32 bankseldev(const int32 port, const int32 io, const int32 data) { } break; case 3: - printf("CRAM BANKSEL=%02x" NLP, data); +/* printf(ADDRESS_FORMAT " CRAM BANKSEL=%02x" NLP, PCX, data); */ + switch(data & 0x7F) { + case 0x01: + setBankSelect(0); + break; + case 0x02: + setBankSelect(1); + break; + case 0x04: + setBankSelect(2); + break; + case 0x08: + setBankSelect(3); + break; + case 0x10: + setBankSelect(4); + break; + case 0x20: + setBankSelect(5); + break; + case 0x40: + setBankSelect(6); + break; +/* case 0x80: */ +/* setBankSelect(7); */ +/* break; */ + default: + printf("Invalid bank select 0x%02x for CRAM" NLP, data); + break; + } + break; case 0: default: @@ -6401,34 +6599,69 @@ static int32 bankseldev(const int32 port, const int32 io, const int32 data) { } } -static t_stat cpu_set_chiptype(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (chiptype == value) return SCPE_OK; /* nothing to do */ +static void cpu_set_chiptype_short(int32 value, uint32 need_cpu_clear) { + extern REG *sim_PC; + if ((chiptype == value) || (chiptype > MAX_CHIP_TYPE)) + return; /* nothing to do */ if ((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80) || (chiptype == CHIP_TYPE_Z80) && (value == CHIP_TYPE_8080)) { chiptype = value; - return SCPE_OK; + return; } chiptype = value; if (chiptype == CHIP_TYPE_8086) { - if (MEMORYSIZE <= MAXBANKSIZE) previousCapacity = MEMORYSIZE; + if (MEMORYSIZE <= MAXBANKSIZE) + previousCapacity = MEMORYSIZE; MEMORYSIZE = MAXMEMORY; cpu_unit.flags &= ~(UNIT_CPU_BANKED | UNIT_CPU_ALTAIRROM); cpu_unit.flags |= UNIT_CPU_MMU; cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2; - cpu_clear(); + if (need_cpu_clear) + cpu_clear(); + sim_PC = &cpu_reg[7]; } else if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { MEMORYSIZE = previousCapacity; cpu_dev.awidth = MAXBANKSIZELOG2; - cpu_clear(); + if (need_cpu_clear) + cpu_clear(); + sim_PC = &cpu_reg[6]; } +} + +static t_stat cpu_set_chiptype(UNIT *uptr, int32 value, char *cptr, void *desc) { + cpu_set_chiptype_short(value, TRUE); return SCPE_OK; } -#ifdef CPUSWITCHER static int32 switchcpu_io(const int32 port, const int32 io, const int32 data) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - MESSAGE_5("SWITCH(port=%02x, io=%i, data=%04x(%i)", port, io, data, data); + int32 new_chiptype = 0; + if (io == 0) { /* Read, switch CPU */ + switch(chiptype) { + case CHIP_TYPE_8080: + case CHIP_TYPE_Z80: + if (cpu_unit.flags & UNIT_CPU_VERBOSE) { + printf("CPU: " ADDRESS_FORMAT " SWITCH(port=%02x) to 8086" NLP, PCX, port); + } + new_chiptype = CHIP_TYPE_8086; + switch_cpu_now = FALSE; /* hharte */ + break; + case CHIP_TYPE_8086: + if (cpu_unit.flags & UNIT_CPU_VERBOSE) { + printf("CPU: " ADDRESS_FORMAT " SWITCH(port=%02x) to 8085/Z80" NLP, PCX, port); + } + new_chiptype = CHIP_TYPE_Z80; + switch_cpu_now = FALSE; /* hharte */ + break; + default: + printf("%s: invalid chiptype: %d\n", __FUNCTION__, chiptype); + break; + } + + cpu_set_chiptype_short(new_chiptype, FALSE); + return(0xFF); /* Return High-Z Data */ + } else { + printf("%s: Set EXT_ADDR=%02x\n", __FUNCTION__, data); } return 0; } @@ -6436,7 +6669,8 @@ static int32 switchcpu_io(const int32 port, const int32 io, const int32 data) { static t_stat cpu_show_switcher(FILE *st, UNIT *uptr, int32 val, void *desc) { if ((cpu_unit.flags & UNIT_CPU_SWITCHER) && (switcherPort >= 0)) fprintf(st, "SWITCHER=0x%02x", switcherPort); - else fprintf(st, "NOSWITCHER"); + else + fprintf(st, "NOSWITCHER"); return SCPE_OK; } @@ -6459,50 +6693,58 @@ static t_stat cpu_reset_switcher(UNIT *uptr, int32 value, char *cptr, void *desc } return SCPE_OK; } -#endif static t_stat cpu_set_ramtype(UNIT *uptr, int32 value, char *cptr, void *desc) { - if(value == ramtype) { - printf("RAM Selection unchanged\n"); + if (value == ramtype) { + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("RAM Selection unchanged\n"); return SCPE_OK; } switch(ramtype) { case 1: - printf("Unmapping NorthStar HRAM\n"); + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("Unmapping NorthStar HRAM\n"); sim_map_resource(0xC0, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE); break; case 2: - printf("Unmapping Vector RAM\n"); + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("Unmapping Vector RAM\n"); sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE); break; case 3: - printf("Unmapping Cromemco RAM\n"); -/* sim_map_resource(0xC0, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE);*/ + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("Unmapping Cromemco RAM\n"); + sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE); break; case 0: default: - printf("Unmapping AltairZ80 RAM\n"); + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("Unmapping AltairZ80 RAM\n"); break; } switch(value) { case 1: - printf("NorthStar HRAM Selected\n"); + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("NorthStar HRAM Selected\n"); sim_map_resource(0xC0, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE); break; case 2: - printf("Vector RAM Selected\n"); + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("Vector RAM Selected\n"); sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE); break; case 3: - printf("Cromemco RAM Selected\n"); -/* sim_map_resource(0xC0, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE);*/ + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("Cromemco RAM Selected\n"); + sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE); break; case 0: default: - printf("AltairZ80 RAM Selected\n"); + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("AltairZ80 RAM Selected\n"); break; } @@ -6515,13 +6757,18 @@ static t_stat set_size(uint32 size) { uint32 maxsize = (((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) && ((cpu_unit.flags & UNIT_CPU_BANKED) == 0)) ? MAXBANKSIZE : MAXMEMORY; size <<= KBLOG2; - if (cpu_unit.flags & UNIT_CPU_BANKED) size &= ~ADDRMASK; + if (cpu_unit.flags & UNIT_CPU_BANKED) + size &= ~ADDRMASK; cpu_unit.flags |= UNIT_CPU_MMU; - if (size < KB) MEMORYSIZE = KB; - else if (size > maxsize) MEMORYSIZE = maxsize; - else MEMORYSIZE = size; + if (size < KB) + MEMORYSIZE = KB; + else if (size > maxsize) + MEMORYSIZE = maxsize; + else + MEMORYSIZE = size; cpu_dev.awidth = MAXBANKSIZELOG2; - if (size > MAXBANKSIZE) cpu_dev.awidth += MAXBANKSLOG2; + if (size > MAXBANKSIZE) + cpu_dev.awidth += MAXBANKSLOG2; cpu_clear(); return SCPE_OK; } @@ -6532,7 +6779,8 @@ static t_stat cpu_set_size(UNIT *uptr, int32 value, char *cptr, void *desc) { static t_stat cpu_set_memory(UNIT *uptr, int32 value, char *cptr, void *desc) { uint32 size, result, i; - if (cptr == NULL) return SCPE_ARG; + if (cptr == NULL) + return SCPE_ARG; result = sscanf(cptr, "%i%n", &size, &i); if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) || (cptr[i + 1] == 'B') && (cptr[i + 2] == 0))) @@ -6557,35 +6805,39 @@ void (*sim_vm_init) (void) = &altairz80_init; #define PLURAL(x) (x), (x) == 1 ? "" : "s" t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) { - uint32 i, addr, cnt = 0, org, pagesModified = 0, makeROM = FALSE; + int32 i; + uint32 addr, cnt = 0, org, pagesModified = 0, makeROM = FALSE; t_addr j, lo, hi; char *result; MDEV m; char gbuf[CBUFSIZE]; if (flag) { - result = (chiptype == CHIP_TYPE_8086) ? - get_range(NULL, cptr, &lo, &hi, 16, ADDRMASK | (BANKMASK << MAXBANKSIZELOG2), 0) : - get_range(NULL, cptr, &lo, &hi, 16, ADDRMASK, 0); - if (result == NULL) return SCPE_ARG; + result = get_range(NULL, cptr, &lo, &hi, 16, ADDRMASKEXTENDED, 0); + if (result == NULL) + return SCPE_ARG; for (j = lo; j <= hi; j++) { - if (putc((chiptype == CHIP_TYPE_8086) ? GetBYTEExtended(j) : GetBYTE(j), fileref) == EOF) return SCPE_IOERR; + if (putc(GetBYTEExtended(j), fileref) == EOF) + return SCPE_IOERR; } printf("%d byte%s dumped [%x - %x].\n", PLURAL(hi + 1 - lo), lo, hi); } else { - if (*cptr == 0) addr = PC_S; + if (*cptr == 0) + addr = (chiptype == CHIP_TYPE_8086) ? PCX_S : PC_S; else { get_glyph(cptr, gbuf, 0); if (strcmp(gbuf, "ROM") == 0) { - addr = PC_S; + addr = (chiptype == CHIP_TYPE_8086) ? PCX_S : PC_S; makeROM = TRUE; } else { - addr = strtotv(cptr, &result, 16); - if (cptr == result) return SCPE_ARG; + addr = strtotv(cptr, &result, 16) & ADDRMASKEXTENDED; + if (cptr == result) + return SCPE_ARG; while (isspace(*result)) result++; get_glyph(result, gbuf, 0); - if (strcmp(gbuf, "ROM") == 0) makeROM = TRUE; + if (strcmp(gbuf, "ROM") == 0) + makeROM = TRUE; } } /* addr is start address to load to, makeROM == TRUE iff memory should become ROM */ @@ -6601,11 +6853,13 @@ t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) { mmu_table[addr >> LOG2PAGESIZE] = ROM_PAGE; m = ROM_PAGE; } - if (!m.isRAM && m.routine) m.routine(addr, 1, i); - else M[addr] = i; + if (!m.isRAM && m.routine) + m.routine(addr, 1, i); + else + M[addr] = i; addr++; cnt++; - } /* end while */ + } /* end while */ printf("%d byte%s [%d page%s] loaded at %x%s.\n", PLURAL(cnt), PLURAL((cnt + 0xff) >> 8), org, makeROM ? " [ROM]" : ""); if (pagesModified) @@ -6613,3 +6867,14 @@ t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) { } return SCPE_OK; } + +void cpu_raise_interrupt(uint32 irq) { + extern void cpu8086_intr(uint8 intrnum); + + if (chiptype == CHIP_TYPE_8086) { + cpu8086_intr(irq); + } else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { + printf("Interrupts not fully supported for chiptype: %s\n", + (chiptype <= MAX_CHIP_TYPE) ? chipTypeToString[chiptype] : "????"); + } +} diff --git a/AltairZ80/altairZ80_defs.h b/AltairZ80/altairZ80_defs.h index 5e4050d5..2059407d 100644 --- a/AltairZ80/altairZ80_defs.h +++ b/AltairZ80/altairZ80_defs.h @@ -51,6 +51,7 @@ #define CHIP_TYPE_8080 0 #define CHIP_TYPE_Z80 1 #define CHIP_TYPE_8086 2 +#define MAX_CHIP_TYPE CHIP_TYPE_8086 /* simulator stop codes */ #define STOP_HALT 0 /* HALT */ @@ -70,31 +71,13 @@ #define UNIT_CPU_MMU (1 << UNIT_CPU_V_MMU) #define UNIT_CPU_V_STOPONHALT (UNIT_V_UF+5) /* stop simulation on HALT */ #define UNIT_CPU_STOPONHALT (1 << UNIT_CPU_V_STOPONHALT) - -#ifdef CPUSWITCHER #define UNIT_CPU_V_SWITCHER (UNIT_V_UF+6) /* switcher 8086 <--> 8080/Z80 enabled */ #define UNIT_CPU_SWITCHER (1 << UNIT_CPU_V_SWITCHER) -#endif #define UNIX_PLATFORM (defined (__linux) || defined(__NetBSD__) \ || defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__)) -#define ADDRESS_FORMAT "[0x%05x]" -#define PC_FORMAT "\n" ADDRESS_FORMAT " " -#define MESSAGE_1(p1) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX); printMessage() -#define MESSAGE_2(p1,p2) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX,p2); printMessage() -#define MESSAGE_3(p1,p2,p3) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3); printMessage() -#define MESSAGE_4(p1,p2,p3,p4) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4); printMessage() -#define MESSAGE_5(p1,p2,p3,p4,p5) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4,p5); printMessage() -#define MESSAGE_6(p1,p2,p3,p4,p5,p6) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4,p5,p6); printMessage() -#define MESSAGE_7(p1,p2,p3,p4,p5,p6,p7) \ - sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4,p5,p6,p7); printMessage() +#define ADDRESS_FORMAT "[0x%05x]" /* use NLP for new line printing while the simulation is running */ #if UNIX_PLATFORM @@ -103,10 +86,6 @@ #define NLP "\n" #endif -#define TRACE_PRINT(level, args) if(trace_level & level) { \ - printf args; \ - } - #if defined (__MWERKS__) && defined (macintosh) #define __FUNCTION__ __FILE__ #endif diff --git a/AltairZ80/altairZ80_dsk.c b/AltairZ80/altairZ80_dsk.c index bebfe2b0..6944fd96 100644 --- a/AltairZ80/altairZ80_dsk.c +++ b/AltairZ80/altairZ80_dsk.c @@ -111,20 +111,23 @@ #include "altairz80_defs.h" #include +/* Debug flags */ +#define IN_MSG (1 << 0) +#define OUT_MSG (1 << 1) +#define READ_MSG (1 << 2) +#define WRITE_MSG (1 << 3) +#define SECTOR_STUCK_MSG (1 << 4) +#define TRACK_STUCK_MSG (1 << 5) +#define VERBOSE_MSG (1 << 6) + #define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK) -#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 BOOTROM_SIZE_DSK 256 /* size of boot rom */ @@ -134,15 +137,14 @@ int32 dsk11(const int32 port, const int32 io, const int32 data); int32 dsk12(const int32 port, const int32 io, const int32 data); static t_stat dsk_boot(int32 unitno, DEVICE *dptr); static t_stat dsk_reset(DEVICE *dptr); -static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc); extern REG *sim_PC; extern UNIT cpu_unit; -extern char messageBuffer[]; extern uint32 PCX; -extern void printMessage(void); extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); void install_ALTAIRbootROM(void); /* global data on status */ @@ -156,7 +158,6 @@ 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_level = 0; static int32 in9_count = 0; static int32 in9_message = FALSE; static int32 dirty = FALSE; /* TRUE when buffer has unwritten data in it */ @@ -224,7 +225,6 @@ static REG dsk_reg[] = { { 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 }, - { HRDATA (TRACELEVEL, trace_level, 16) }, { DRDATA (IN9COUNT, in9_count, 4), REG_RO }, { DRDATA (IN9MESSAGE, in9_message, 4), REG_RO }, { DRDATA (DIRTY, dirty, 4), REG_RO }, @@ -241,46 +241,34 @@ static REG dsk_reg[] = { static MTAB dsk_mod[] = { { UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL }, { UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", 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 } }; +#define TRACE_PRINT(level, args) if (dsk_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB dsk_dt[] = { + { "IN", IN_MSG }, + { "OUT", OUT_MSG }, + { "READ", READ_MSG }, + { "WRITE", WRITE_MSG }, + { "SECTOR_STUCK", SECTOR_STUCK_MSG }, + { "TRACK_STUCK", TRACK_STUCK_MSG }, + { "VERBOSE", VERBOSE_MSG }, + { NULL, 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, (DEV_DISABLE), 0, - NULL, NULL, NULL + NULL, (DEV_DISABLE | DEV_DEBUG), 0, + dsk_dt, NULL, "Altair Floppy Disk DSK" }; -static void resetDSKWarningFlags(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - warnLock[i] = 0; - warnAttached[i] = 0; - } - warnDSK10 = 0; - warnDSK11 = 0; - warnDSK12 = 0; -} - -static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetDSKWarningFlags(); - return SCPE_OK; -} - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hasVerbose(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) - if (((dsk_dev.units + i) -> flags) & UNIT_DSK_VERBOSE) return TRUE; - return FALSE; -} - static char* selectInOut(const int32 io) { return io == 0 ? "IN" : "OUT"; } @@ -289,11 +277,20 @@ static char* selectInOut(const int32 io) { /* reset routine */ static t_stat dsk_reset(DEVICE *dptr) { - resetDSKWarningFlags(); + int32 i; + for (i = 0; i < NUM_OF_DSK; i++) { + warnLock[i] = 0; + warnAttached[i] = 0; + } + warnDSK10 = 0; + warnDSK11 = 0; + warnDSK12 = 0; current_disk = NUM_OF_DSK; - trace_level = 0; in9_count = 0; in9_message = FALSE; + sim_map_resource(0x08, 1, RESOURCE_TYPE_IO, &dsk10, dptr->flags & DEV_DIS); + sim_map_resource(0x09, 1, RESOURCE_TYPE_IO, &dsk11, dptr->flags & DEV_DIS); + sim_map_resource(0x0A, 1, RESOURCE_TYPE_IO, &dsk12, dptr->flags & DEV_DIS); return SCPE_OK; } @@ -335,21 +332,23 @@ static void writebuf(void) { dskbuf[i++] = 0; uptr = dsk_dev.units + current_disk; if (((uptr -> flags) & UNIT_DSK_WLK) == 0) { /* write enabled */ - if (trace_level & TRACE_READ_WRITE) { - MESSAGE_4("OUT 0x0a (WRITE) D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]); - } + TRACE_PRINT(WRITE_MSG, ("DSK%i: " ADDRESS_FORMAT " OUT 0x0a (WRITE) D%d T%d S%d" NLP, current_disk, PCX, + current_disk, current_track[current_disk], current_sector[current_disk])); if (dskseek(uptr)) { - MESSAGE_4("fseek failed D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]); + printf("DSK%i: " ADDRESS_FORMAT " fseek failed D%d T%d S%d" NLP, current_disk, + PCX, current_disk, current_track[current_disk], current_sector[current_disk]); } rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref); if (rtn != 1) { - MESSAGE_4("fwrite failed T%d S%d Return=%d", current_track[current_disk], current_sector[current_disk], rtn); + printf("DSK%i: " ADDRESS_FORMAT " fwrite failed T%d S%d Return=%d" NLP, current_disk, + PCX, current_track[current_disk], current_sector[current_disk], rtn); } } - else if ( ((uptr -> flags) & UNIT_DSK_VERBOSE) && (warnLock[current_disk] < warnLevelDSK) ) { + else if ( (dsk_dev.dctrl & VERBOSE_MSG) && (warnLock[current_disk] < warnLevelDSK) ) { /* write locked - print warning message if required */ warnLock[current_disk]++; -/*05*/ MESSAGE_2("Attempt to write to locked DSK%d - ignored.", current_disk); +/*05*/ printf("DSK%i: " ADDRESS_FORMAT " Attempt to write to locked DSK%d - ignored." NLP, + current_disk, PCX, current_disk); } current_flag[current_disk] &= 0xfe; /* ENWD off */ current_byte[current_disk] = 0xff; @@ -380,9 +379,10 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) { in9_count = 0; if (io == 0) { /* IN: return flags */ if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK10 < warnLevelDSK)) { + if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK10 < warnLevelDSK)) { warnDSK10++; -/*01*/ MESSAGE_1("Attempt of IN 0x08 on unattached disk - ignored."); +/*01*/ printf("DSK%i: " ADDRESS_FORMAT " Attempt of IN 0x08 on unattached disk - ignored." NLP, + current_disk, PCX); } return 0xff; /* no drive selected - can do nothing */ } @@ -392,15 +392,14 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) { /* OUT: Controller set/reset/enable/disable */ if (dirty) /* implies that current_disk < NUM_OF_DSK */ writebuf(); - if (trace_level & TRACE_IN_OUT) { - MESSAGE_2("OUT 0x08: %x", data); - } + TRACE_PRINT(OUT_MSG, ("DSK%i: " ADDRESS_FORMAT " OUT 0x08: %x" NLP, current_disk, PCX, 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) ) { + if ( (dsk_dev.dctrl & VERBOSE_MSG) && (warnAttached[current_disk] < warnLevelDSK) ) { warnAttached[current_disk]++; -/*02*/ MESSAGE_2("Attempt to select unattached DSK%d - ignored.", current_disk); +/*02*/ printf("DSK%i: " ADDRESS_FORMAT " Attempt to select unattached DSK%d - ignored." NLP, + current_disk, PCX, current_disk); } current_disk = NUM_OF_DSK; } @@ -418,9 +417,10 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) { int32 dsk11(const int32 port, const int32 io, const int32 data) { if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK11 < warnLevelDSK)) { + if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK11 < warnLevelDSK)) { warnDSK11++; -/*03*/ MESSAGE_2("Attempt of %s 0x09 on unattached disk - ignored.", selectInOut(io)); +/*03*/ printf("DSK%i: " ADDRESS_FORMAT " Attempt of %s 0x09 on unattached disk - ignored." NLP, + current_disk, PCX, selectInOut(io)); } return 0; /* no drive selected - can do nothing */ } @@ -428,13 +428,12 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) { /* now current_disk < NUM_OF_DSK */ if (io == 0) { /* read sector position */ in9_count++; - if ((trace_level & TRACE_SECTOR_STUCK) && (in9_count > 2 * DSK_SECT) && (!in9_message)) { + if ((dsk_dev.dctrl & SECTOR_STUCK_MSG) && (in9_count > 2 * DSK_SECT) && (!in9_message)) { in9_message = TRUE; - MESSAGE_2("Looping on sector find %d.", current_disk); - } - if (trace_level & TRACE_IN_OUT) { - MESSAGE_1("IN 0x09"); + printf("DSK%i: " ADDRESS_FORMAT " Looping on sector find." NLP, + current_disk, PCX); } + TRACE_PRINT(IN_MSG, ("DSK%i: " ADDRESS_FORMAT " IN 0x09" NLP, current_disk, PCX)); if (dirty) /* implies that current_disk < NUM_OF_DSK */ writebuf(); if (current_flag[current_disk] & 0x04) { /* head loaded? */ @@ -444,18 +443,18 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) { 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 */ + } else + return 0; /* head not loaded - return 0 */ } in9_count = 0; /* drive functions */ - if (trace_level & TRACE_IN_OUT) { - MESSAGE_2("OUT 0x09: %x", data); - } + TRACE_PRINT(OUT_MSG, ("DSK%i: " ADDRESS_FORMAT " OUT 0x09: %x" NLP, current_disk, PCX, data)); if (data & 0x01) { /* step head in */ - if ((trace_level & TRACE_TRACK_STUCK) && (current_track[current_disk] == (tracks[current_disk] - 1))) { - MESSAGE_2("Unnecessary step in for disk %d", current_disk); + if ((dsk_dev.dctrl & TRACK_STUCK_MSG) && (current_track[current_disk] == (tracks[current_disk] - 1))) { + printf("DSK%i: " ADDRESS_FORMAT " Unnecessary step in." NLP, + current_disk, PCX); } current_track[current_disk]++; if (current_track[current_disk] > (tracks[current_disk] - 1)) @@ -467,8 +466,8 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) { } if (data & 0x02) { /* step head out */ - if ((trace_level & TRACE_TRACK_STUCK) && (current_track[current_disk] == 0)) { - MESSAGE_2("Unnecessary step out for disk %d", current_disk); + if ((dsk_dev.dctrl & TRACK_STUCK_MSG) && (current_track[current_disk] == 0)) { + printf("DSK%i: " ADDRESS_FORMAT " Unnecessary step out." NLP, current_disk, PCX); } current_track[current_disk]--; if (current_track[current_disk] < 0) { @@ -512,9 +511,10 @@ int32 dsk12(const int32 port, const int32 io, const int32 data) { UNIT *uptr; if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK12 < warnLevelDSK)) { + if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) { warnDSK12++; -/*04*/ MESSAGE_2("Attempt of %s 0x0a on unattached disk - ignored.", selectInOut(io)); +/*04*/ printf("DSK%i: " ADDRESS_FORMAT " Attempt of %s 0x0a on unattached disk - ignored." NLP, + current_disk, PCX, selectInOut(io)); } return 0; } @@ -525,9 +525,9 @@ int32 dsk12(const int32 port, const int32 io, const int32 data) { if (io == 0) { if (current_byte[current_disk] >= DSK_SECTSIZE) { /* physically read the sector */ - if (trace_level & TRACE_READ_WRITE) { - MESSAGE_4("IN 0x0a (READ) D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]); - } + TRACE_PRINT(READ_MSG, + ("DSK%i: " ADDRESS_FORMAT " IN 0x0a (READ) D%d T%d S%d" NLP, current_disk, + PCX, current_disk, current_track[current_disk], current_sector[current_disk])); for (i = 0; i < DSK_SECTSIZE; i++) dskbuf[i] = 0; dskseek(uptr); diff --git a/AltairZ80/altairZ80_sio.c b/AltairZ80/altairZ80_sio.c index 201dddd0..20c956fe 100644 --- a/AltairZ80/altairZ80_sio.c +++ b/AltairZ80/altairZ80_sio.c @@ -1,1475 +1,1650 @@ -/* altairz80_sio.c: MITS Altair serial I/O card - - Copyright (c) 2002-2008, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - These functions support a simulated MITS 2SIO interface card. - The card had two physical I/O ports which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. Each device has a status port - and a data port. A write to the status port can select - some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | X | X | X | X | X | X | O | I | - +---+---+---+---+---+---+---+---+ - - I - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - O - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include - -#include "altairz80_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include -#include -#if UNIX_PLATFORM -#include -#elif defined (_WIN32) -#include -#endif - -#define UNIT_V_SIO_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */ -#define UNIT_SIO_ANSI (1 << UNIT_V_SIO_ANSI) -#define UNIT_V_SIO_UPPER (UNIT_V_UF + 1) /* upper case mode */ -#define UNIT_SIO_UPPER (1 << UNIT_V_SIO_UPPER) -#define UNIT_V_SIO_BS (UNIT_V_UF + 2) /* map delete to backspace */ -#define UNIT_SIO_BS (1 << UNIT_V_SIO_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_SIO_MAP (UNIT_V_UF + 4) /* mapping mode on */ -#define UNIT_SIO_MAP (1 << UNIT_V_SIO_MAP) -#define UNIT_V_SIO_BELL (UNIT_V_UF + 5) /* ^G (bell character) rings bell */ -#define UNIT_SIO_BELL (1 << UNIT_V_SIO_BELL) -#define UNIT_V_SIO_INTERRUPT (UNIT_V_UF + 6) /* create keyboard interrupts */ -#define UNIT_SIO_INTERRUPT (1 << UNIT_V_SIO_INTERRUPT) -#define UNIT_V_SIO_SLEEP (UNIT_V_UF + 7) /* sleep after keyboard status check */ -#define UNIT_SIO_SLEEP (1 << UNIT_V_SIO_SLEEP) - -#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_TIMERON) - -#define TERMINALS 4 /* lines per mux */ -#define SIO_CAN_READ 0x01 /* bit 0 is set iff character available */ -#define SIO_CAN_WRITE 0x02 /* bit 1 is set iff character can be sent */ -#define SIO_RESET 0x03 /* Command to reset SIO */ -#define VGSIO_CAN_READ 0x02 /* bit 1 is set iff character available */ -#define VGSIO_CAN_WRITE 0x01 /* bit 0 is set iff character can be sent */ -#define KBD_HAS_CHAR 0x40 /* bit 6 is set iff character available */ -#define KBD_HAS_NO_CHAR 0x01 /* bit 0 is set iff no character is available */ - -#define BACKSPACE_CHAR 0x08 /* backspace character */ -#define DELETE_CHAR 0x7f /* delete character */ -#define CONTROLC_CHAR 0x03 /* control C character */ -#define CONTROLG_CHAR 0x07 /* control G char., rings bell when displayed */ -#define CONTROLZ_CHAR 0x1a /* control Z character */ - -#define PORT_TABLE_SIZE 256 /* size of port mapping table */ -#define SLEEP_ALLOWED_START_DEFAULT 100 /* default initial value for sleepAllowedCounter*/ - -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_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); -static t_stat toBool(char tf, int *result); -static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_dev_show_port(FILE *st, UNIT *uptr, int32 val, void *desc); -static t_stat sio_dev_set_interrupton(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_svc(UNIT *uptr); -static t_stat simh_dev_reset(DEVICE *dptr); -static t_stat simh_svc(UNIT *uptr); -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); -void printMessage(void); -void do_SIMH_sleep(void); -static void pollConnection(void); -static int32 mapCharacter(int32 ch); -static void checkSleep(void); -static void voidSleep(void); - -extern int32 getBankSelect(void); -extern void setBankSelect(const int32 b); -extern uint32 getCommon(void); -extern uint8 GetBYTEWrapper(const uint32 Addr); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -extern int32 chiptype; -extern const t_bool rtc_avail; -extern FILE *sim_log; -extern uint32 PCX; -extern int32 sim_switches; -extern const char *scp_error_messages[]; -extern int32 SR; -extern UNIT cpu_unit; -extern volatile int32 stop_cpu; -extern int32 sim_interval; - -/* SIMH pseudo device status registers */ -/* ZSDOS clock definitions */ -static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ -static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */ -static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */ - -/* CPM3 clock definitions */ -static time_t ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ -static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */ -static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */ -static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */ - -/* interrupt related */ -static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */ - int32 timerInterrupt = FALSE; /* timer interrupt pending */ - int32 timerInterruptHandler = 0x0fc00; /* default address of interrupt handling routine */ -static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */ -static int32 timerDelta = 100; /* interrupt every 100 ms */ -static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */ - -/* stop watch and timer related */ -static uint32 stopWatchDelta = 0; /* stores elapsed time of stop watch */ -static int32 getStopWatchDeltaPos = 0; /* determines the state for receiving stopWatchDelta */ -static uint32 stopWatchNow = 0; /* stores starting time of stop watch */ -static int32 markTimeSP = 0; /* stack pointer for timer stack */ - - /* default time in microseconds to sleep for SIMHSleepCmd */ -#if defined (_WIN32) -static uint32 SIMHSleep = 1000; /* Sleep uses milliseconds */ -#elif defined (__MWERKS__) && defined (macintosh) -static uint32 SIMHSleep = 0; /* no sleep on Macintosh OS9 */ -#else -static uint32 SIMHSleep = 100; /* on other platforms 100 micro seconds is good enough */ -#endif -static uint32 sleepAllowedCounter = 0; /* only sleep on no character available when == 0 */ -static uint32 sleepAllowedStart = SLEEP_ALLOWED_START_DEFAULT; /* default start for above counter */ - -/* 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 */ - -/* support for wild card expansion */ -#if UNIX_PLATFORM -static glob_t globS; -static uint32 globPosNameList = 0; -static int32 globPosName = 0; -static int32 globValid = FALSE; -static int32 globError = 0; -#elif defined (_WIN32) -static WIN32_FIND_DATA FindFileData; -static HANDLE hFind = INVALID_HANDLE_VALUE; -static int32 globFinished = FALSE; -static int32 globValid = FALSE; -static int32 globPosName = 0; -#endif - -/* 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 */ - - int32 keyboardInterrupt = FALSE; /* keyboard interrupt pending */ - uint32 keyboardInterruptHandler = 0x0038;/* address of keyboard interrupt handler */ - -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_SIO_MAP | UNIT_SIO_SLEEP, 0), - 100000, /* wait */ - FALSE, /* u3 = FALSE, no character available in buffer */ - FALSE, /* u4 = FALSE, terminal input is not attached to a file */ - FALSE, /* u5 = FALSE, terminal input has not yet reached EOF */ - 0 /* u6 = 0, not used */ -}; - -static REG sio_reg[] = { - { DRDATA (SIOWLEV, warnLevelSIO, 32) }, - { DRDATA (WRNUPTP, warnUnattachedPTP, 32) }, - { DRDATA (WRNUPTR, warnUnattachedPTR, 32) }, - { DRDATA (WRNPTRE, warnPTREOF, 32) }, - { DRDATA (WRUPORT, warnUnassignedPort, 32) }, - { HRDATA (FILEATT, sio_unit.u4, 8), REG_RO }, /* TRUE iff terminal input is attached to a file */ - { HRDATA (FILEEOF, sio_unit.u5, 8), REG_RO }, /* TRUE iff terminal input file has reached EOF */ - { HRDATA (TSTATUS, sio_unit.u3, 8) }, /* TRUE iff a character available in sio_unit.buf */ - { DRDATA (TBUFFER, sio_unit.buf, 8) }, /* input buffer for one character */ - { DRDATA (KEYBDI, keyboardInterrupt, 3), REG_RO }, - { HRDATA (KEYBDH, keyboardInterruptHandler, 16) }, - { NULL } -}; - -static MTAB sio_mod[] = { - { UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */ - { UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */ - { UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */ - { UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */ - { UNIT_SIO_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */ - { UNIT_SIO_BS, UNIT_SIO_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_SIO_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */ - { UNIT_SIO_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */ - { UNIT_SIO_BELL, 0, "BELL", "BELL", NULL }, /* enable bell character */ - { UNIT_SIO_BELL, UNIT_SIO_BELL, "NOBELL", "NOBELL", NULL }, /* suppress ringing the bell */ - { UNIT_SIO_SLEEP, 0, "NOSLEEP", "NOSLEEP", NULL }, /* no sleep after keyboard status check */ - { UNIT_SIO_SLEEP, UNIT_SIO_SLEEP, "SLEEP", "SLEEP", NULL }, /* sleep after keyboard status check */ - /* no keyboard interrupts */ - { UNIT_SIO_INTERRUPT, 0, "NOINTERRUPT","NOINTERRUPT",&sio_dev_set_interruptoff }, - /* create keyboard interrupts */ - { UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT","INTERRUPT",&sio_dev_set_interrupton }, - { MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "PORT", "PORT", &sio_dev_set_port, &sio_dev_show_port }, - { 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 }; - -static UNIT ptr_unit = { - UDATA (NULL, UNIT_SEQ | UNIT_ATTABLE | UNIT_ROABLE, 0) -}; - -static REG ptr_reg[] = { - { HRDATA (STAT, ptr_unit.u3, 8) }, - { 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 -}; - -static UNIT ptp_unit = { - UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0) -}; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, NULL, 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 -}; - -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 (SLEEP, SIMHSleep, 32) }, - { DRDATA (VOSLP, sleepAllowedStart, 32) }, - - { DRDATA (STPDT, stopWatchDelta, 32), REG_RO }, - { DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO }, - { DRDATA (STPNW, stopWatchNow, 32), REG_RO }, - { DRDATA (MTSP, markTimeSP, 8), REG_RO }, - - { DRDATA (VPOS, versionPos, 8), REG_RO }, - { DRDATA (LCPMS, lastCPMStatus, 8), REG_RO }, - { DRDATA (LCMD, lastCommand, 8), REG_RO }, - { DRDATA (CPOS, getCommonPos, 8), REG_RO }, - { NULL } -}; - -static MTAB simh_mod[] = { - /* quiet, no warning messages */ - { UNIT_SIMH_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, display warning messages */ - { UNIT_SIMH_VERBOSE, UNIT_SIMH_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - /* timer generated interrupts are off */ - { UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff }, - /* timer generated interrupts are on */ - { UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron }, - { 0 } -}; - -DEVICE simh_device = { - "SIMH", &simh_unit, simh_reg, simh_mod, - 1, 10, 31, 1, 16, 4, - NULL, NULL, &simh_dev_reset, - NULL, NULL, NULL, - NULL, 0, 0, - NULL, NULL, NULL -}; - -char messageBuffer[256] = { 0 }; - -void printMessage(void) { - printf(messageBuffer); - printf(NLP); - if (sim_log) { - fprintf(sim_log, messageBuffer); - fprintf(sim_log,"\n"); - } -} - -static void resetSIOWarningFlags(void) { - warnUnattachedPTP = warnUnattachedPTR = warnPTREOF = warnUnassignedPort = 0; -} - -static t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetSIOWarningFlags(); - return SCPE_OK; -} - -static t_stat sio_attach(UNIT *uptr, char *cptr) { - t_stat r = SCPE_IERR; - sio_unit.u3 = FALSE; /* no character in terminal input buffer */ - get_uint(cptr, 10, 65535, &r); /* attempt to get port, discard result */ - if (r == SCPE_OK) { /* string can be interpreted as port number */ - sio_unit.u4 = FALSE; /* terminal input is not attached to a file */ - return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */ - } - sio_unit.u4 = TRUE; /* terminal input is attached to a file */ - sio_unit.u5 = FALSE; /* EOF not yet reached */ - return attach_unit(uptr, cptr); -} - -static t_stat sio_detach(UNIT *uptr) { - sio_unit.u3 = FALSE; /* no character in terminal input buffer */ - if (sio_unit.u4) { /* is terminal input attached to a file? */ - sio_unit.u4 = FALSE; /* not anymore, detach */ - return detach_unit(uptr); - } - return tmxr_detach(&altairTMXR, uptr); -} - -static void pollConnection(void) { - if (sio_unit.flags & UNIT_ATT) { - int32 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 */ - } -} - -/* reset routines */ -static t_stat sio_reset(DEVICE *dptr) { - int32 i; - sio_unit.u3 = FALSE; /* no character in terminal input buffer */ - resetSIOWarningFlags(); - if (sio_unit.u4) { /* is terminal input attached to a file? */ - rewind(sio_unit.fileref); /* yes, rewind input */ - sio_unit.u5 = FALSE; /* EOF not yet reached */ - } - else if (sio_unit.flags & UNIT_ATT) - for (i = 0; i < TERMINALS; i++) - if (TerminalLines[i].conn) - tmxr_reset_ln(&TerminalLines[i]); - return SCPE_OK; -} - -static t_stat ptr_reset(DEVICE *dptr) { - resetSIOWarningFlags(); - ptr_unit.u3 = FALSE; /* End Of File not yet reached */ - if (ptr_unit.flags & UNIT_ATT) /* attached? */ - rewind(ptr_unit.fileref); - return SCPE_OK; -} - -static t_stat ptp_reset(DEVICE *dptr) { - resetSIOWarningFlags(); - return SCPE_OK; -} - -static int32 mapCharacter(int32 ch) { - ch &= 0xff; - if (sio_unit.flags & UNIT_SIO_MAP) { - if (sio_unit.flags & UNIT_SIO_BS) { - if (ch == BACKSPACE_CHAR) - return DELETE_CHAR; - } - else if (ch == DELETE_CHAR) - return BACKSPACE_CHAR; - if (sio_unit.flags & UNIT_SIO_UPPER) - return toupper(ch); - } - return ch; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. - - Port 1 controls console I/O. We distinguish three cases: - 1) SIO attached to a file (i.e. input taken from a file ) - 2) SIO attached to a port (i.e. Telnet console I/O ) - 3) SIO not attached to a port (i.e. "regular" console I/O ) -*/ - -typedef struct { - int32 port; /* this information belongs to port number 'port' */ - int32 terminalLine; /* map to this 'terminalLine' */ - int32 sio_can_read; /* bit mask to indicate that one can read from this port */ - int32 sio_cannot_read; /* bit mask to indicate that one cannot read from this port */ - int32 sio_can_write; /* bit mask to indicate that one can write to this port */ - int32 hasReset; /* TRUE iff SIO has reset command */ - int32 sio_reset; /* reset command */ - int32 hasOUT; /* TRUE iff port supports OUT command */ - int32 isBuiltin; /* TRUE iff mapping is built in */ -} SIO_PORT_INFO; - -static SIO_PORT_INFO port_table[PORT_TABLE_SIZE] = { - {0x00, 0, KBD_HAS_CHAR, KBD_HAS_NO_CHAR, SIO_CAN_WRITE, FALSE, 0, FALSE, TRUE }, - {0x01, 0, 0, 0, 0, FALSE, 0, FALSE, TRUE }, - {0x02, 0, VGSIO_CAN_READ, 0, VGSIO_CAN_WRITE, FALSE, 0, TRUE, TRUE }, - {0x03, 0, VGSIO_CAN_READ, 0, VGSIO_CAN_WRITE, FALSE, 0, FALSE, TRUE }, - {0x10, 0, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x14, 1, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x16, 2, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x18, 3, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x11, 0, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {0x15, 1, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {0x17, 2, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {0x19, 3, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {-1, 0, 0, 0, 0, 0, 0, 0, 0} /* must be last */ -}; - -static SIO_PORT_INFO lookupPortInfo(const int32 port, int32 *position) { - int32 i = 0; - while ((port_table[i].port != -1) && (port_table[i].port != port)) i++; - *position = i; - return port_table[i]; -} - -/* keyboard idle detection: sleep when feature enabled, no character available - (duty of caller) and operation not voided (e.g. when output is available) */ -static void checkSleep(void) { - if (sio_unit.flags & UNIT_SIO_SLEEP) { - if (sleepAllowedCounter) sleepAllowedCounter--; - else do_SIMH_sleep(); - } -} - -/* void sleep for next 'sleepAllowedStart' tests */ -static void voidSleep(void) { - sleepAllowedCounter = sleepAllowedStart; -} - -/* generic status port for keyboard input / terminal output */ -int32 sio0s(const int32 port, const int32 io, const int32 data) { - int32 ch, result; - SIO_PORT_INFO spi = lookupPortInfo(port, &ch); - assert(spi.port == port); - pollConnection(); - if (io == 0) { /* IN */ - if (sio_unit.u4) /* attached to a file? */ - if (sio_unit.u5) /* EOF reached? */ - sio_detach(&sio_unit); /* detach file and switch to keyboard input */ - else return spi.sio_can_read | spi.sio_can_write; - if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */ - if (tmxr_rqln(&TerminalLines[spi.terminalLine])) - result = spi.sio_can_read; - else { - result = spi.sio_cannot_read; - checkSleep(); - } - return result | /* read possible if character available */ - (TerminalLines[spi.terminalLine].conn && TerminalLines[spi.terminalLine].xmte ? spi.sio_can_write : 0x00); - /* write possible if connected and transmit - enabled */ - } - if (sio_unit.u3) /* character available? */ - return spi.sio_can_read | spi.sio_can_write; - ch = sim_poll_kbd(); /* no, try to get a character */ - if (ch) { /* character available? */ - if (ch == SCPE_STOP) { /* stop CPU in case ^E (default) was typed */ - stop_cpu = TRUE; - sim_interval = 0; /* detect stop condition as soon as possible*/ - return spi.sio_can_write | spi.sio_cannot_read; /* do not consume stop character */ - } - sio_unit.u3 = TRUE; /* indicate character available */ - sio_unit.buf = ch; /* store character in buffer */ - return spi.sio_can_read | spi.sio_can_write; - } - checkSleep(); - return spi.sio_can_write | spi.sio_cannot_read; - } /* OUT follows, no fall-through from IN */ - if (spi.hasReset && (data == spi.sio_reset)) /* reset command */ - sio_unit.u3 = FALSE; /* indicate that no character is available */ - return 0x00; /* ignored since OUT */ -} - -/* generic data port for keyboard input / terminal output */ -int32 sio0d(const int32 port, const int32 io, const int32 data) { - int32 ch; - SIO_PORT_INFO spi = lookupPortInfo(port, &ch); - assert(spi.port == port); - pollConnection(); - if (io == 0) { /* IN */ - if (sio_unit.u4) { /* attached to a file? */ - if (sio_unit.u5) { /* EOF reached? */ - sio_detach(&sio_unit); /* detach file and switch to keyboard input */ - return CONTROLC_CHAR; /* this time return ^C after all */ - } - if ((ch = getc(sio_unit.fileref)) == EOF) { /* end of file? */ - sio_unit.u5 = TRUE; /* terminal input file has reached EOF */ - return CONTROLC_CHAR; /* result is ^C (= CP/M interrupt) */ - } - return mapCharacter(ch); /* return mapped character */ - } - if (sio_unit.flags & UNIT_ATT) - return mapCharacter(tmxr_getc_ln(&TerminalLines[spi.terminalLine])); - sio_unit.u3 = FALSE; /* no character is available any more */ - return mapCharacter(sio_unit.buf); /* return previous character */ - } /* OUT follows, no fall-through from IN */ - if (spi.hasOUT) { - ch = sio_unit.flags & UNIT_SIO_ANSI ? data & 0x7f : data; /* clear highest bit in ANSI mode */ - if ((ch != CONTROLG_CHAR) || !(sio_unit.flags & UNIT_SIO_BELL)) { - voidSleep(); - if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4)) /* attached to a port and not to a file */ - tmxr_putc_ln(&TerminalLines[spi.terminalLine], ch); /* status ignored */ - else - sim_putchar(ch); - } - } - return 0x00; /* ignored since OUT */ -} - -/* PTR/PTP status port */ -int32 sio1s(const int32 port, const int32 io, const int32 data) { - if (io == 0) { /* IN */ - /* 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) { /* PTR is not attached */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*06*/ MESSAGE_2("Attempt to test status of unattached PTR[0x%02x]. 0x02 returned.", port); - } - return SIO_CAN_WRITE; - } - /* if EOF then SIO_CAN_WRITE else - (SIO_CAN_WRITE and SIO_CAN_READ) */ - return ptr_unit.u3 ? SIO_CAN_WRITE : (SIO_CAN_READ | SIO_CAN_WRITE); - } /* OUT follows */ - if (data == SIO_RESET) - ptr_unit.u3 = FALSE; /* reset EOF indicator */ - return 0x00; /* ignored since OUT */ -} - -/* PTR/PTP data port */ -int32 sio1d(const int32 port, const int32 io, const int32 data) { - int32 ch; - if (io == 0) { /* IN */ - if (ptr_unit.u3) { /* EOF reached, no more data available */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnPTREOF < warnLevelSIO)) { - warnPTREOF++; -/*07*/ MESSAGE_2("PTR[0x%02x] attempted to read past EOF. 0x00 returned.", port); - } - return 0x00; - } - if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*08*/ MESSAGE_2("Attempt to read from unattached PTR[0x%02x]. 0x00 returned.", port); - } - return 0x00; - } - if ((ch = getc(ptr_unit.fileref)) == EOF) { /* end of file? */ - ptr_unit.u3 = TRUE; /* remember EOF reached */ - return CONTROLZ_CHAR; /* ^Z denotes end of text file in CP/M */ - } - return ch & 0xff; - } /* OUT follows */ - if (ptp_unit.flags & UNIT_ATT) /* unit must be attached */ - putc(data, ptp_unit.fileref); - /* else ignore data */ - else if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTP < warnLevelSIO)) { - warnUnattachedPTP++; -/*09*/ MESSAGE_3("Attempt to output '0x%02x' to unattached PTP[0x%02x] - ignored.", data, port); - } - return 0x00; /* ignored since OUT */ -} - -static t_stat toBool(char tf, int *result) { - if (tf == 'T') { - *result = TRUE; - return SCPE_OK; - } - if (tf == 'F') { - *result = FALSE; - return SCPE_OK; - } - return SCPE_ARG; -} - -static void show_sio_port_info(FILE *st, SIO_PORT_INFO sip) { - if (sio_unit.flags & UNIT_SIO_VERBOSE) - fprintf(st, "(Port=%02x/Terminal=%1i/Read=0x%02x/NotRead=0x%02x/" - "Write=0x%02x/Reset?=%s/Reset=0x%02x/Data?=%s)", - sip.port, sip.terminalLine, sip.sio_can_read, sip.sio_cannot_read, - sip.sio_can_write, sip.hasReset ? "True" : "False", sip.sio_reset, - sip.hasOUT ? "True" : "False"); - else - fprintf(st, "(%02x/%1i/%02x/%02x/%02x/%s/%02x/%s)", - sip.port, sip.terminalLine, sip.sio_can_read, sip.sio_cannot_read, - sip.sio_can_write, sip.hasReset ? "T" : "F", sip.sio_reset, - sip.hasOUT ? "T" : "F"); -} - -static uint32 equalSIP(SIO_PORT_INFO x, SIO_PORT_INFO y) { - /* isBuiltin is not relevant for equality, only for display */ - return (x.port == y.port) && (x.terminalLine == y.terminalLine) && - (x.sio_can_read == y.sio_can_read) && (x.sio_cannot_read == y.sio_cannot_read) && - (x.sio_can_write == y.sio_can_write) && (x.hasReset == y.hasReset) && - (x.sio_reset == y.sio_reset) && (x.hasOUT == y.hasOUT); -} - -static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc) { - int32 result, n, position; - SIO_PORT_INFO sip = { 0 }, old; - char hasReset, hasOUT; - if (cptr == NULL) return SCPE_ARG; - result = sscanf(cptr, "%x%n", &sip.port, &n); - if ((result == 1) && (cptr[n] == 0)) { - old = lookupPortInfo(sip.port, &position); - if (old.port == -1) { - printf("No mapping for port 0x%02x exists - cannot remove.\n", sip.port); - return SCPE_ARG; - } - do { - port_table[position] = port_table[position + 1]; - position++; - } - while (port_table[position].port != -1); - sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, &nulldev, FALSE); - if (sio_unit.flags & UNIT_SIO_VERBOSE) { - printf("Removing mapping for port 0x%02x.\n\t", sip.port); - show_sio_port_info(stdout, old); - } - return SCPE_OK; - } - result = sscanf(cptr, "%x/%d/%x/%x/%x/%1c/%x/%1c%n", &sip.port, - &sip.terminalLine, &sip.sio_can_read, &sip.sio_cannot_read, - &sip.sio_can_write, &hasReset, &sip.sio_reset, &hasOUT, &n); - if ((result != 8) || (result == EOF) || (cptr[n] != 0)) return SCPE_ARG; - result = toBool(hasReset, &sip.hasReset); - if (result != SCPE_OK) return result; - result = toBool(hasOUT, &sip.hasOUT); - if (result != SCPE_OK) return result; - if (sip.port != (sip.port & 0xff)) { - printf("Truncating port 0x%x to 0x%02x.\n", sip.port, sip.port & 0xff); - sip.port &= 0xff; - } - old = lookupPortInfo(sip.port, &position); - if (old.port == sip.port) { - if (sio_unit.flags & UNIT_SIO_VERBOSE) { - printf("Replacing mapping for port 0x%02x.\n\t", sip.port); - show_sio_port_info(stdout, old); - printf("-> "); - show_sio_port_info(stdout, sip); - if (equalSIP(sip, old)) printf("[identical]"); - } - } - else { - port_table[position + 1] = old; - if (sio_unit.flags & UNIT_SIO_VERBOSE) { - printf("Adding mapping for port 0x%02x.\n\t", sip.port); - show_sio_port_info(stdout, sip); - } - } - if (sio_unit.flags & UNIT_SIO_VERBOSE) printf("\n"); - port_table[position] = sip; - sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, (sip.hasOUT || - (sip.sio_can_read == 0) && (sip.sio_cannot_read == 0) && - (sip.sio_can_write == 0)) ? &sio0d : &sio0s, FALSE); - return SCPE_OK; -} - -static t_stat sio_dev_show_port(FILE *st, UNIT *uptr, int32 val, void *desc) { - int32 i, first = TRUE; - for (i = 0; port_table[i].port != -1; i++) - if (!port_table[i].isBuiltin) { - if (first) first = FALSE; - else fprintf(st, " "); - show_sio_port_info(st, port_table[i]); - } - if (first) fprintf(st, "no extra port"); - return SCPE_OK; -} - -static t_stat sio_dev_set_interrupton(UNIT *uptr, int32 value, char *cptr, void *desc) { - keyboardInterrupt = FALSE; - return sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ -} - -static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void *desc) { - keyboardInterrupt = FALSE; - sim_cancel(&sio_unit); - return SCPE_OK; -} - -static t_stat sio_svc(UNIT *uptr) { - if (sio0s(0, 0, 0) & KBD_HAS_CHAR) { - keyboardInterrupt = TRUE; - } - if (sio_unit.flags & UNIT_SIO_INTERRUPT) - sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; -} - -int32 nulldev(const int32 port, const int32 io, const int32 data) { - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) { - warnUnassignedPort++; - if (io == 0) { - MESSAGE_2("Attempt to input from unassigned port 0x%04x - ignored.", port); - } - else { - MESSAGE_3("Attempt to output 0x%02x to unassigned port 0x%04x - ignored.", data, port); - } - } - return io == 0 ? 0xff : 0; -} - -int32 sr_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? SR : 0; -} - -static int32 toBCD(const int32 x) { - return (x / 10) * 16 + (x % 10); -} - -static int32 fromBCD(const int32 x) { - return 10 * ((0xf0 & x) >> 4) + (0x0f & x); -} - -/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe. - The following principles apply: - - 1) For commands that do not require parameters and do not return results - ld a, - out (0feh),a - Special case is the reset command which needs to be send 128 times to make - sure that the internal state is properly reset. - - 2) For commands that require parameters and do not return results - ld a, - out (0feh),a - ld a, - out (0feh),a - ld a, - out (0feh),a - ... - Note: The calling program must send all parameter bytes. Otherwise - the pseudo device is left in an undefined 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 undefined state. - - 4) Commands requiring parameters and returning results do not exist currently. - -*/ - -enum simhPseudoDeviceCommands { /* do not change order or remove commands, add only at the end */ - printTimeCmd, /* 0 print the current time in milliseconds */ - startTimerCmd, /* 1 start a new timer on the top of the timer stack */ - stopTimerCmd, /* 2 stop timer on top of timer stack and show time difference */ - resetPTRCmd, /* 3 reset the PTR device */ - attachPTRCmd, /* 4 attach the PTR device */ - detachPTRCmd, /* 5 detach the PTR device */ - getSIMHVersionCmd, /* 6 get the current version of the SIMH pseudo device */ - getClockZSDOSCmd, /* 7 get the current time in ZSDOS format */ - setClockZSDOSCmd, /* 8 set the current time in ZSDOS format */ - getClockCPM3Cmd, /* 9 get the current time in CP/M 3 format */ - setClockCPM3Cmd, /* 10 set the current time in CP/M 3 format */ - getBankSelectCmd, /* 11 get the selected bank */ - setBankSelectCmd, /* 12 set the selected bank */ - getCommonCmd, /* 13 get the base address of the common memory segment */ - resetSIMHInterfaceCmd, /* 14 reset the SIMH pseudo device */ - showTimerCmd, /* 15 show time difference to timer on top of stack */ - attachPTPCmd, /* 16 attach PTP to the file with name at beginning of CP/M command line*/ - detachPTPCmd, /* 17 detach PTP */ - hasBankedMemoryCmd, /* 18 determines whether machine has banked memory */ - setZ80CPUCmd, /* 19 set the CPU to a Z80 */ - set8080CPUCmd, /* 20 set the CPU to an 8080 */ - startTimerInterruptsCmd, /* 21 start timer interrupts */ - stopTimerInterruptsCmd, /* 22 stop timer interrupts */ - setTimerDeltaCmd, /* 23 set the timer interval in which interrupts occur */ - setTimerInterruptAdrCmd, /* 24 set the address to call by timer interrupts */ - resetStopWatchCmd, /* 25 reset the millisecond stop watch */ - readStopWatchCmd, /* 26 read the millisecond stop watch */ - SIMHSleepCmd, /* 27 let SIMH sleep for SIMHSleep microseconds */ - getHostOSPathSeparator, /* 28 obtain the file path separator of the OS under which SIMH runs */ - getHostFilenames /* 29 perform wildcard expansion and obtain list of file names */ -}; - -#define CPM_COMMAND_LINE_LENGTH 128 -#define TIMER_STACK_LIMIT 10 /* stack depth of timer stack */ -static uint32 markTime[TIMER_STACK_LIMIT]; /* timer stack */ -static struct tm currentTime; -static int32 currentTimeValid = FALSE; -static char version[] = "SIMH003"; - -static t_stat simh_dev_reset(DEVICE *dptr) { - currentTimeValid = FALSE; - ClockZSDOSDelta = 0; - setClockZSDOSPos = 0; - getClockZSDOSPos = 0; - ClockCPM3Delta = 0; - setClockCPM3Pos = 0; - getClockCPM3Pos = 0; - getStopWatchDeltaPos = 0; - getCommonPos = 0; - setTimerDeltaPos = 0; - setTimerInterruptAdrPos = 0; - markTimeSP = 0; - versionPos = 0; - lastCommand = 0; - lastCPMStatus = SCPE_OK; - timerInterrupt = FALSE; - if (simh_unit.flags & UNIT_SIMH_TIMERON) - simh_dev_set_timeron(NULL, 0, NULL, NULL); - return SCPE_OK; -} - -static void warnNoRealTimeClock(void) { - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - MESSAGE_1("Sorry - no real time clock available."); - } -} - -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 */ - } - warnNoRealTimeClock(); - return SCPE_ARG; -} - -static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) { - timerInterrupt = FALSE; - sim_cancel(&simh_unit); - return SCPE_OK; -} - -static t_stat simh_svc(UNIT *uptr) { - uint32 n = sim_os_msec(); - if (n >= timeOfNextInterrupt) { - timerInterrupt = TRUE; - timeOfNextInterrupt += timerDelta; - if (n >= timeOfNextInterrupt) /* time of next interrupt is not in the future */ - timeOfNextInterrupt = n + timerDelta; /* make sure it is in the future! */ - } - if (simh_unit.flags & UNIT_SIMH_TIMERON) - sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - return SCPE_OK; -} - -static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH]; -static void createCPMCommandLine(void) { - int32 i, len = (GetBYTEWrapper(0x80) & 0x7f); /* 0x80 contains length of command line, discard first char */ - for (i = 0; i < len - 1; i++) - cpmCommandLine[i] = (char)GetBYTEWrapper(0x82 + i); /* the first char, typically ' ', is discarded */ - cpmCommandLine[i] = 0; /* make C string */ -} - -/* 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) { - createCPMCommandLine(); - if (uptr == &ptr_unit) - sim_switches = SWMASK('R'); - else if (uptr == &ptp_unit) - sim_switches = SWMASK('W') | SWMASK('C'); /* 'C' option makes sure that file is properly truncated - if it had existed before */ - lastCPMStatus = attach_unit(uptr, cpmCommandLine); - if ((lastCPMStatus != SCPE_OK) && (simh_unit.flags & UNIT_SIMH_VERBOSE)) { - MESSAGE_3("Cannot open '%s' (%s).", cpmCommandLine, scp_error_messages[lastCPMStatus - SCPE_BASE]); - /* must keep curly braces as MESSAGE_N is a macro with two statements */ - } -} - -/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */ -static void setClockZSDOS(void) { - struct tm newTime; - int32 year = fromBCD(GetBYTEWrapper(setClockZSDOSAdr)); - newTime.tm_year = year < 50 ? year + 100 : year; - newTime.tm_mon = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 1)) - 1; - newTime.tm_mday = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 2)); - newTime.tm_hour = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 3)); - newTime.tm_min = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 4)); - newTime.tm_sec = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 5)); - ClockZSDOSDelta = mktime(&newTime) - time(NULL); -} - -#define SECONDS_PER_MINUTE 60 -#define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE) -#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) -static time_t mkCPM3Origin(void) { - struct tm date; - date.tm_year = 77; - date.tm_mon = 11; - date.tm_mday = 31; - date.tm_hour = 0; - date.tm_min = 0; - date.tm_sec = 0; - return mktime(&date); -} - -/* setClockCPM3Adr points to 5 byte block in M: - 0 - 1 int16: days since 31 Dec 77 - 2 BCD byte: HH - 3 BCD byte: MM - 4 BCD byte: SS */ -static void setClockCPM3(void) { - ClockCPM3Delta = mkCPM3Origin() + - (GetBYTEWrapper(setClockCPM3Adr) + GetBYTEWrapper(setClockCPM3Adr + 1) * 256) * SECONDS_PER_DAY + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 2)) * SECONDS_PER_HOUR + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 3)) * SECONDS_PER_MINUTE + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 4)) - time(NULL); -} - -static int32 simh_in(const int32 port) { - int32 result = 0; - switch(lastCommand) { - - case getHostFilenames: -#if UNIX_PLATFORM - if (globValid) - if (globPosNameList < globS.gl_pathc) { - if (!(result = globS.gl_pathv[globPosNameList][globPosName++])) { - globPosNameList++; - globPosName = 0; - } - } - else { - globValid = FALSE; - lastCommand = 0; - globfree(&globS); - } -#elif defined (_WIN32) - if (globValid) - if (globFinished) - globValid = FALSE; - else if (!(result = FindFileData.cFileName[globPosName++])) { - globPosName = 0; - if (!FindNextFile(hFind, &FindFileData)) { - globFinished = TRUE; - FindClose(hFind); - hFind = INVALID_HANDLE_VALUE; - } - } -#else - lastCommand = 0; -#endif - break; - - 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_CPU_BANKED) - result = getBankSelect(); - else { - result = 0; - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - MESSAGE_1("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_CPU_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; - - case getHostOSPathSeparator: -#if defined (__MWERKS__) && defined (macintosh) - result = ':'; /* colon on Macintosh OS 9 */ -#elif defined (_WIN32) - result = '\\'; /* back slash in Windows */ -#else - result = '/'; /* slash in UNIX */ -#endif - break; - - default: - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - MESSAGE_2("Undefined IN from SIMH pseudo device on port %03xh ignored.", - port); - } - result = lastCommand = 0; - } - return result; -} - -void do_SIMH_sleep(void) { -#if defined (_WIN32) - if ((SIMHSleep / 1000) && !sio_unit.u4) /* time to sleep and SIO not attached to a file */ - Sleep(SIMHSleep / 1000); -#else - if (SIMHSleep && !sio_unit.u4) /* time to sleep and SIO not attached to a file */ - usleep(SIMHSleep); -#endif -} - -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_CPU_BANKED) - setBankSelect(data & BANKMASK); - else if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - MESSAGE_2("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 getHostFilenames: -#if UNIX_PLATFORM - if (!globValid) { - globValid = TRUE; - globPosNameList = globPosName = 0; - createCPMCommandLine(); - globError = glob(cpmCommandLine, GLOB_ERR, NULL, &globS); - if (globError) { - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - MESSAGE_3("Cannot expand '%s'. Error is %i.", cpmCommandLine, globError); - } - globfree(&globS); - globValid = FALSE; - } - } -#elif defined (_WIN32) - if (!globValid) { - globValid = TRUE; - globPosName = 0; - globFinished = FALSE; - createCPMCommandLine(); - hFind = FindFirstFile(cpmCommandLine, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) { - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - MESSAGE_3("Cannot expand '%s'. Error is %lu.", cpmCommandLine, GetLastError()); - } - globValid = FALSE; - } - } -#endif - break; - - case SIMHSleepCmd: - do_SIMH_sleep(); - break; - - case printTimeCmd: /* print time */ - if (rtc_avail) { - MESSAGE_2("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 < TIMER_STACK_LIMIT) - markTime[markTimeSP++] = sim_os_msec(); - else { - MESSAGE_1("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]; - MESSAGE_2("Timer stopped. Elapsed time in milliseconds = %d.", delta); - } - else { - MESSAGE_1("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 = (int32) ((now - mkCPM3Origin()) / SECONDS_PER_DAY); - getClockCPM3Pos = 0; - break; - - case setClockCPM3Cmd: - setClockCPM3Pos = 0; - break; - - case getBankSelectCmd: - case setBankSelectCmd: - case getCommonCmd: - case hasBankedMemoryCmd: - case getHostOSPathSeparator: - break; - - case resetSIMHInterfaceCmd: - markTimeSP = 0; - lastCommand = 0; -#if UNIX_PLATFORM - if (globValid) { - globValid = FALSE; - globfree(&globS); - } -#elif defined (_WIN32) - if (globValid) { - globValid = FALSE; - if (hFind != INVALID_HANDLE_VALUE) { - FindClose(hFind); - } - } -#endif - 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]; - MESSAGE_2("Timer running. Elapsed in milliseconds = %d.", delta); - } - else { - MESSAGE_1("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: - chiptype = CHIP_TYPE_Z80; - break; - - case set8080CPUCmd: - chiptype = CHIP_TYPE_8080; - 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) { - MESSAGE_3("Unknown command (%i) to SIMH pseudo device on port %03xh ignored.", - data, port); - } - } - } - return 0x00; /* 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); -} +/* altairz80_sio.c: MITS Altair serial I/O card + + Copyright (c) 2002-2008, Peter Schorn + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Peter Schorn shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Peter Schorn. + + Based on work by Charles E Owen (c) 1997 + + These functions support a simulated MITS 2SIO interface card. + The card had two physical I/O ports which could be connected + to any serial I/O device that would connect to a current loop, + RS232, or TTY interface. Available baud rates were jumper + selectable for each port from 110 to 9600. + + All I/O is via programmed I/O. Each device has a status port + and a data port. A write to the status port can select + some options for the device (0x03 will reset the port). + A read of the status port gets the port status: + + +---+---+---+---+---+---+---+---+ + | X | X | X | X | X | X | O | I | + +---+---+---+---+---+---+---+---+ + + I - A 1 in this bit position means a character has been received + on the data port and is ready to be read. + O - A 1 in this bit means the port is ready to receive a character + on the data port and transmit it out over the serial line. + + A read to the data port gets the buffered character, a write + to the data port writes the character to the device. +*/ + +#include + +#include "altairz80_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" +#include +#include +#if UNIX_PLATFORM +#include +#elif defined (_WIN32) +#include +#endif + +/* Debug flags */ +#define IN_MSG (1 << 0) +#define OUT_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define VERBOSE_MSG (1 << 3) + +#define UNIT_V_SIO_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */ +#define UNIT_SIO_ANSI (1 << UNIT_V_SIO_ANSI) +#define UNIT_V_SIO_UPPER (UNIT_V_UF + 1) /* upper case mode */ +#define UNIT_SIO_UPPER (1 << UNIT_V_SIO_UPPER) +#define UNIT_V_SIO_BS (UNIT_V_UF + 2) /* map delete to backspace */ +#define UNIT_SIO_BS (1 << UNIT_V_SIO_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_SIO_MAP (UNIT_V_UF + 4) /* mapping mode on */ +#define UNIT_SIO_MAP (1 << UNIT_V_SIO_MAP) +#define UNIT_V_SIO_BELL (UNIT_V_UF + 5) /* ^G (bell character) rings bell */ +#define UNIT_SIO_BELL (1 << UNIT_V_SIO_BELL) +#define UNIT_V_SIO_INTERRUPT (UNIT_V_UF + 6) /* create keyboard interrupts */ +#define UNIT_SIO_INTERRUPT (1 << UNIT_V_SIO_INTERRUPT) +#define UNIT_V_SIO_SLEEP (UNIT_V_UF + 7) /* sleep after keyboard status check */ +#define UNIT_SIO_SLEEP (1 << UNIT_V_SIO_SLEEP) + +#define UNIT_V_SIMH_TIMERON (UNIT_V_UF + 1) /* SIMH pseudo device timer generate interrupts */ +#define UNIT_SIMH_TIMERON (1 << UNIT_V_SIMH_TIMERON) + +#define TERMINALS 33 /* lines per mux (increased to 33 for IF3 board)*/ +#define SIO_CAN_READ 0x01 /* bit 0 is set iff character available */ +#define SIO_CAN_WRITE 0x02 /* bit 1 is set iff character can be sent */ +#define SIO_RESET 0x03 /* Command to reset SIO */ +#define VGSIO_CAN_READ 0x02 /* bit 1 is set iff character available */ +#define VGSIO_CAN_WRITE 0x01 /* bit 0 is set iff character can be sent */ +#define KBD_HAS_CHAR 0x40 /* bit 6 is set iff character available */ +#define KBD_HAS_NO_CHAR 0x01 /* bit 0 is set iff no character is available */ + +#define BACKSPACE_CHAR 0x08 /* backspace character */ +#define DELETE_CHAR 0x7f /* delete character */ +#define CONTROLC_CHAR 0x03 /* control C character */ +#define CONTROLG_CHAR 0x07 /* control G char., rings bell when displayed */ +#define CONTROLZ_CHAR 0x1a /* control Z character */ + +#define PORT_TABLE_SIZE 256 /* size of port mapping table */ +#define SLEEP_ALLOWED_START_DEFAULT 100 /* default initial value for sleepAllowedCounter*/ + +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_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); +static t_stat toBool(char tf, int *result); +static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc); +static t_stat sio_dev_show_port(FILE *st, UNIT *uptr, int32 val, void *desc); +static t_stat sio_dev_set_interrupton(UNIT *uptr, int32 value, char *cptr, void *desc); +static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void *desc); +static t_stat sio_svc(UNIT *uptr); +static t_stat simh_dev_reset(DEVICE *dptr); +static t_stat simh_svc(UNIT *uptr); +static void mapAltairPorts(void); +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); +void do_SIMH_sleep(void); +static void pollConnection(void); +static int32 mapCharacter(int32 ch); +static void checkSleep(void); +static void voidSleep(void); + +extern int32 getBankSelect(void); +extern void setBankSelect(const int32 b); +extern uint32 getCommon(void); +extern uint8 GetBYTEWrapper(const uint32 Addr); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); + +extern int32 chiptype; +extern const t_bool rtc_avail; +extern uint32 PCX; +extern int32 sim_switches; +extern int32 sim_quiet; +extern const char *scp_error_messages[]; +extern int32 SR; +extern UNIT cpu_unit; +extern volatile int32 stop_cpu; +extern int32 sim_interval; + +/* SIMH pseudo device status registers */ +/* ZSDOS clock definitions */ +static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ +static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */ +static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */ +static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */ + +/* CPM3 clock definitions */ +static time_t ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ +static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */ +static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */ +static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */ +static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */ + +/* interrupt related */ +static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */ + int32 timerInterrupt = FALSE; /* timer interrupt pending */ + int32 timerInterruptHandler = 0x0fc00; /* default address of interrupt handling routine */ +static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */ +static int32 timerDelta = 100; /* interrupt every 100 ms */ +static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */ + +/* stop watch and timer related */ +static uint32 stopWatchDelta = 0; /* stores elapsed time of stop watch */ +static int32 getStopWatchDeltaPos = 0; /* determines the state for receiving stopWatchDelta */ +static uint32 stopWatchNow = 0; /* stores starting time of stop watch */ +static int32 markTimeSP = 0; /* stack pointer for timer stack */ + + /* default time in microseconds to sleep for SIMHSleepCmd */ +#if defined (_WIN32) +static uint32 SIMHSleep = 1000; /* Sleep uses milliseconds */ +#elif defined (__MWERKS__) && defined (macintosh) +static uint32 SIMHSleep = 0; /* no sleep on Macintosh OS9 */ +#else +static uint32 SIMHSleep = 100; /* on other platforms 100 micro seconds is good enough */ +#endif +static uint32 sleepAllowedCounter = 0; /* only sleep on no character available when == 0 */ +static uint32 sleepAllowedStart = SLEEP_ALLOWED_START_DEFAULT; /* default start for above counter */ + +/* 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 */ + +/* support for wild card expansion */ +#if UNIX_PLATFORM +static glob_t globS; +static uint32 globPosNameList = 0; +static int32 globPosName = 0; +static int32 globValid = FALSE; +static int32 globError = 0; +#elif defined (_WIN32) +static WIN32_FIND_DATA FindFileData; +static HANDLE hFind = INVALID_HANDLE_VALUE; +static int32 globFinished = FALSE; +static int32 globValid = FALSE; +static int32 globPosName = 0; +static int32 lastPathSeparator = 0; +static int32 firstPathCharacter = 0; +#endif + +/* 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 */ + + int32 keyboardInterrupt = FALSE; /* keyboard interrupt pending */ + uint32 keyboardInterruptHandler = 0x0038;/* address of keyboard interrupt handler */ + +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_SIO_MAP | UNIT_SIO_SLEEP, 0), + 100000, /* wait */ + FALSE, /* u3 = FALSE, no character available in buffer */ + FALSE, /* u4 = FALSE, terminal input is not attached to a file */ + FALSE, /* u5 = FALSE, terminal input has not yet reached EOF */ + 0 /* u6 = 0, not used */ +}; + +static REG sio_reg[] = { + { DRDATA (SIOWLEV, warnLevelSIO, 32) }, + { DRDATA (WRNUPTP, warnUnattachedPTP, 32) }, + { DRDATA (WRNUPTR, warnUnattachedPTR, 32) }, + { DRDATA (WRNPTRE, warnPTREOF, 32) }, + { DRDATA (WRUPORT, warnUnassignedPort, 32) }, + { HRDATA (FILEATT, sio_unit.u4, 8), REG_RO }, /* TRUE iff terminal input is attached to a file */ + { HRDATA (FILEEOF, sio_unit.u5, 8), REG_RO }, /* TRUE iff terminal input file has reached EOF */ + { HRDATA (TSTATUS, sio_unit.u3, 8) }, /* TRUE iff a character available in sio_unit.buf */ + { DRDATA (TBUFFER, sio_unit.buf, 8) }, /* input buffer for one character */ + { DRDATA (KEYBDI, keyboardInterrupt, 3), REG_RO }, + { HRDATA (KEYBDH, keyboardInterruptHandler, 16) }, + { NULL } +}; + +static MTAB sio_mod[] = { + { UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */ + { UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */ + { UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */ + { UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */ + { UNIT_SIO_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */ + { UNIT_SIO_BS, UNIT_SIO_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_SIO_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */ + { UNIT_SIO_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */ + { UNIT_SIO_BELL, 0, "BELL", "BELL", NULL }, /* enable bell character */ + { UNIT_SIO_BELL, UNIT_SIO_BELL, "NOBELL", "NOBELL", NULL }, /* suppress ringing the bell */ + { UNIT_SIO_SLEEP, 0, "NOSLEEP", "NOSLEEP", NULL }, /* no sleep after keyboard status check */ + { UNIT_SIO_SLEEP, UNIT_SIO_SLEEP, "SLEEP", "SLEEP", NULL }, /* sleep after keyboard status check */ + /* no keyboard interrupts */ + { UNIT_SIO_INTERRUPT, 0, "NOINTERRUPT","NOINTERRUPT",&sio_dev_set_interruptoff }, + /* create keyboard interrupts */ + { UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT","INTERRUPT",&sio_dev_set_interrupton }, + { MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", &sio_dev_set_port, &sio_dev_show_port }, + { 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, "Serial Input Output SIO" +}; + +static UNIT ptr_unit = { + UDATA (NULL, UNIT_SEQ | UNIT_ATTABLE | UNIT_ROABLE, 0) +}; + +static REG ptr_reg[] = { + { HRDATA (STAT, ptr_unit.u3, 8) }, + { NULL } +}; + +DEVICE ptr_dev = { + "PTR", &ptr_unit, ptr_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE, 0, + NULL, NULL, "Paper Tape Reader PTR" +}; + +static UNIT ptp_unit = { + UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0) +}; + +DEVICE ptp_dev = { + "PTP", &ptp_unit, NULL, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptp_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE, 0, + NULL, NULL, "Paper Tape Puncher PTP" +}; + +/* 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 (SLEEP, SIMHSleep, 32) }, + { DRDATA (VOSLP, sleepAllowedStart, 32) }, + + { 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[] = { + /* 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 } +}; + +#define TRACE_PRINT(level, args) if (simh_device.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB simh_dt[] = { + { "IN", IN_MSG }, + { "OUT", OUT_MSG }, + { "CMD", CMD_MSG }, + { "VERBOSE", VERBOSE_MSG }, + { NULL, 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, (DEV_DISABLE | DEV_DEBUG), 0, + simh_dt, NULL, "Pseudo Device SIMH" +}; + +static void resetSIOWarningFlags(void) { + warnUnattachedPTP = warnUnattachedPTR = warnPTREOF = warnUnassignedPort = 0; +} + +static t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { + resetSIOWarningFlags(); + return SCPE_OK; +} + +static t_stat sio_attach(UNIT *uptr, char *cptr) { + t_stat r = SCPE_IERR; + sio_unit.u3 = FALSE; /* no character in terminal input buffer */ + get_uint(cptr, 10, 65535, &r); /* attempt to get port, discard result */ + if (r == SCPE_OK) { /* string can be interpreted as port number */ + sio_unit.u4 = FALSE; /* terminal input is not attached to a file */ + return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */ + } + sio_unit.u4 = TRUE; /* terminal input is attached to a file */ + sio_unit.u5 = FALSE; /* EOF not yet reached */ + return attach_unit(uptr, cptr); +} + +static t_stat sio_detach(UNIT *uptr) { + sio_unit.u3 = FALSE; /* no character in terminal input buffer */ + if (sio_unit.u4) { /* is terminal input attached to a file? */ + sio_unit.u4 = FALSE; /* not anymore, detach */ + return detach_unit(uptr); + } + return tmxr_detach(&altairTMXR, uptr); +} + +static void pollConnection(void) { + if (sio_unit.flags & UNIT_ATT) { + int32 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 */ + } +} + +/* reset routines */ +static t_stat sio_reset(DEVICE *dptr) { + int32 i; + sio_unit.u3 = FALSE; /* no character in terminal input buffer */ + resetSIOWarningFlags(); + if (sio_unit.u4) { /* is terminal input attached to a file? */ + rewind(sio_unit.fileref); /* yes, rewind input */ + sio_unit.u5 = FALSE; /* EOF not yet reached */ + } + else if (sio_unit.flags & UNIT_ATT) + for (i = 0; i < TERMINALS; i++) + if (TerminalLines[i].conn) + tmxr_reset_ln(&TerminalLines[i]); + mapAltairPorts(); + return SCPE_OK; +} + +static t_stat ptr_reset(DEVICE *dptr) { + resetSIOWarningFlags(); + ptr_unit.u3 = FALSE; /* End Of File not yet reached */ + if (ptr_unit.flags & UNIT_ATT) /* attached? */ + rewind(ptr_unit.fileref); + sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS); + sim_map_resource(0x13, 1, RESOURCE_TYPE_IO, &sio1d, dptr->flags & DEV_DIS); + return SCPE_OK; +} + +static t_stat ptp_reset(DEVICE *dptr) { + resetSIOWarningFlags(); + sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS); + sim_map_resource(0x13, 1, RESOURCE_TYPE_IO, &sio1d, dptr->flags & DEV_DIS); + return SCPE_OK; +} + +static int32 mapCharacter(int32 ch) { + ch &= 0xff; + if (sio_unit.flags & UNIT_SIO_MAP) { + if (sio_unit.flags & UNIT_SIO_BS) { + if (ch == BACKSPACE_CHAR) + return DELETE_CHAR; + } + else if (ch == DELETE_CHAR) + return BACKSPACE_CHAR; + if (sio_unit.flags & UNIT_SIO_UPPER) + return toupper(ch); + } + return ch; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. + + Each function is passed an 'io' flag, where 0 means a read from + the port, and 1 means a write to the port. On input, the actual + input is passed as the return value, on output, 'data' is written + to the device. + + Port 1 controls console I/O. We distinguish three cases: + 1) SIO attached to a file (i.e. input taken from a file ) + 2) SIO attached to a port (i.e. Telnet console I/O ) + 3) SIO not attached to a port (i.e. "regular" console I/O ) +*/ + +typedef struct { + int32 port; /* this information belongs to port number 'port' */ + int32 terminalLine; /* map to this 'terminalLine' */ + int32 sio_can_read; /* bit mask to indicate that one can read from this port */ + int32 sio_cannot_read; /* bit mask to indicate that one cannot read from this port */ + int32 sio_can_write; /* bit mask to indicate that one can write to this port */ + int32 hasReset; /* TRUE iff SIO has reset command */ + int32 sio_reset; /* reset command */ + int32 hasOUT; /* TRUE iff port supports OUT command */ + int32 isBuiltin; /* TRUE iff mapping is built in */ +} SIO_PORT_INFO; + +static SIO_PORT_INFO port_table[PORT_TABLE_SIZE] = { + {0x00, 0, KBD_HAS_CHAR, KBD_HAS_NO_CHAR, SIO_CAN_WRITE, FALSE, 0, FALSE, TRUE }, + {0x01, 0, 0, 0, 0, FALSE, 0, FALSE, TRUE }, + {0x02, 0, VGSIO_CAN_READ, 0, VGSIO_CAN_WRITE, FALSE, 0, TRUE, TRUE }, + {0x03, 0, VGSIO_CAN_READ, 0, VGSIO_CAN_WRITE, FALSE, 0, FALSE, TRUE }, + {0x10, 0, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, + {0x11, 0, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, + {0x14, 1, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, + {0x15, 1, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, + {0x16, 2, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, + {0x17, 2, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, + {0x18, 3, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, + {0x19, 3, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, + + /* CompuPro System Support 1 Board */ + {0x5c, 0, 0x0, 0, 0, FALSE,0, TRUE, TRUE }, + {0x5d, 0, 0xC2, 0, 0xC5, FALSE,0, FALSE, TRUE }, + + /* CompuPro Interfacer 3 (IF3) Board 0 */ + {0x300, 1, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x301, 1, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x302, 2, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x303, 2, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x304, 3, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x305, 3, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x306, 4, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x307, 4, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x308, 5, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x309, 5, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x30a, 6, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x30b, 6, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x30c, 7, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x30d, 7, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x30e, 8, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x30f, 8, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + /* CompuPro Interfacer 3 (IF3) Board 1 */ + {0x310, 9, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x311, 9, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x312, 10, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x313, 10, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x314, 11, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x315, 11, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x316, 12, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x317, 12, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x318, 13, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x319, 13, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x31a, 14, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x31b, 14, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x31c, 15, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x31d, 15, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x31e, 16, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x31f, 16, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + /* CompuPro Interfacer 3 (IF3) Board 2 */ + {0x320, 17, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x321, 17, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x322, 18, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x323, 18, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x324, 19, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x325, 19, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x326, 20, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x327, 20, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x328, 21, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x329, 21, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x32a, 22, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x32b, 22, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x32c, 23, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x32d, 23, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x32e, 24, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x32f, 24, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + /* CompuPro Interfacer 3 (IF3) Board 3 */ + {0x330, 25, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x331, 25, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x332, 26, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x333, 26, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x334, 27, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x335, 27, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x336, 28, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x337, 28, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x338, 29, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x339, 29, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x33a, 30, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x33b, 30, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x33c, 31, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x33d, 31, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {0x33e, 32, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, + {0x33f, 32, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, + {-1, 0, 0, 0, 0, 0, 0, 0, 0} /* must be last */ +}; + +static SIO_PORT_INFO lookupPortInfo(const int32 port, int32 *position) { + int32 i = 0; + while ((port_table[i].port != -1) && (port_table[i].port != port)) + i++; + *position = i; + return port_table[i]; +} + +/* keyboard idle detection: sleep when feature enabled, no character available + (duty of caller) and operation not voided (e.g. when output is available) */ +static void checkSleep(void) { + if (sio_unit.flags & UNIT_SIO_SLEEP) { + if (sleepAllowedCounter) + sleepAllowedCounter--; + else + do_SIMH_sleep(); + } +} + +/* void sleep for next 'sleepAllowedStart' tests */ +static void voidSleep(void) { + sleepAllowedCounter = sleepAllowedStart; +} + +/* generic status port for keyboard input / terminal output */ +int32 sio0s(const int32 port, const int32 io, const int32 data) { + int32 ch, result; + SIO_PORT_INFO spi = lookupPortInfo(port, &ch); + assert(spi.port == port); + pollConnection(); + if (io == 0) { /* IN */ + if (sio_unit.u4) /* attached to a file? */ + if (sio_unit.u5) /* EOF reached? */ + sio_detach(&sio_unit); /* detach file and switch to keyboard input */ + else + return spi.sio_can_read | spi.sio_can_write; + if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */ + if (tmxr_rqln(&TerminalLines[spi.terminalLine])) + result = spi.sio_can_read; + else { + result = spi.sio_cannot_read; + checkSleep(); + } + return result | /* read possible if character available */ + (TerminalLines[spi.terminalLine].conn && TerminalLines[spi.terminalLine].xmte ? spi.sio_can_write : 0x00); + /* write possible if connected and transmit + enabled */ + } + if (sio_unit.u3) /* character available? */ + return spi.sio_can_read | spi.sio_can_write; + ch = sim_poll_kbd(); /* no, try to get a character */ + if (ch) { /* character available? */ + if (ch == SCPE_STOP) { /* stop CPU in case ^E (default) was typed */ + stop_cpu = TRUE; + sim_interval = 0; /* detect stop condition as soon as possible*/ + return spi.sio_can_write | spi.sio_cannot_read; /* do not consume stop character */ + } + sio_unit.u3 = TRUE; /* indicate character available */ + sio_unit.buf = ch; /* store character in buffer */ + return spi.sio_can_read | spi.sio_can_write; + } + checkSleep(); + return spi.sio_can_write | spi.sio_cannot_read; + } /* OUT follows, no fall-through from IN */ + if (spi.hasReset && (data == spi.sio_reset)) /* reset command */ + sio_unit.u3 = FALSE; /* indicate that no character is available */ + return 0x00; /* ignored since OUT */ +} + +/* generic data port for keyboard input / terminal output */ +int32 sio0d(const int32 port, const int32 io, const int32 data) { + int32 ch; + SIO_PORT_INFO spi = lookupPortInfo(port, &ch); + assert(spi.port == port); + pollConnection(); + if (io == 0) { /* IN */ + if (sio_unit.u4) { /* attached to a file? */ + if (sio_unit.u5) { /* EOF reached? */ + sio_detach(&sio_unit); /* detach file and switch to keyboard input */ + return CONTROLC_CHAR; /* this time return ^C after all */ + } + if ((ch = getc(sio_unit.fileref)) == EOF) { /* end of file? */ + sio_unit.u5 = TRUE; /* terminal input file has reached EOF */ + return CONTROLC_CHAR; /* result is ^C (= CP/M interrupt) */ + } + return mapCharacter(ch); /* return mapped character */ + } + if (sio_unit.flags & UNIT_ATT) + return mapCharacter(tmxr_getc_ln(&TerminalLines[spi.terminalLine])); + sio_unit.u3 = FALSE; /* no character is available any more */ + return mapCharacter(sio_unit.buf); /* return previous character */ + } /* OUT follows, no fall-through from IN */ + if (spi.hasOUT) { + ch = sio_unit.flags & UNIT_SIO_ANSI ? data & 0x7f : data; /* clear highest bit in ANSI mode */ + if ((ch != CONTROLG_CHAR) || !(sio_unit.flags & UNIT_SIO_BELL)) { + voidSleep(); + if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4)) /* attached to a port and not to a file */ + tmxr_putc_ln(&TerminalLines[spi.terminalLine], ch); /* status ignored */ + else + sim_putchar(ch); + } + } + return 0x00; /* ignored since OUT */ +} + +/* PTR/PTP status port */ +int32 sio1s(const int32 port, const int32 io, const int32 data) { + if (io == 0) { /* IN */ + /* 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) { /* PTR is not attached */ + if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { + warnUnattachedPTR++; +/*06*/ printf("PTR: " ADDRESS_FORMAT " Attempt to test status of unattached PTR[0x%02x]. 0x02 returned." NLP, PCX, port); + } + return SIO_CAN_WRITE; + } + /* if EOF then SIO_CAN_WRITE else + (SIO_CAN_WRITE and SIO_CAN_READ) */ + return ptr_unit.u3 ? SIO_CAN_WRITE : (SIO_CAN_READ | SIO_CAN_WRITE); + } /* OUT follows */ + if (data == SIO_RESET) + ptr_unit.u3 = FALSE; /* reset EOF indicator */ + return 0x00; /* ignored since OUT */ +} + +/* PTR/PTP data port */ +int32 sio1d(const int32 port, const int32 io, const int32 data) { + int32 ch; + if (io == 0) { /* IN */ + if (ptr_unit.u3) { /* EOF reached, no more data available */ + if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnPTREOF < warnLevelSIO)) { + warnPTREOF++; +/*07*/ printf("PTR: " ADDRESS_FORMAT " PTR[0x%02x] attempted to read past EOF. 0x00 returned." NLP, PCX, port); + } + return 0x00; + } + if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */ + if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { + warnUnattachedPTR++; +/*08*/ printf("PTR: " ADDRESS_FORMAT " Attempt to read from unattached PTR[0x%02x]. 0x00 returned." NLP, PCX, port); + } + return 0x00; + } + if ((ch = getc(ptr_unit.fileref)) == EOF) { /* end of file? */ + ptr_unit.u3 = TRUE; /* remember EOF reached */ + return CONTROLZ_CHAR; /* ^Z denotes end of text file in CP/M */ + } + return ch & 0xff; + } /* OUT follows */ + if (ptp_unit.flags & UNIT_ATT) /* unit must be attached */ + putc(data, ptp_unit.fileref); + /* else ignore data */ + else if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTP < warnLevelSIO)) { + warnUnattachedPTP++; +/*09*/ printf("PTP: " ADDRESS_FORMAT " Attempt to output '0x%02x' to unattached PTP[0x%02x] - ignored." NLP, PCX, data, port); + } + return 0x00; /* ignored since OUT */ +} + +static t_stat toBool(char tf, int *result) { + if (tf == 'T') { + *result = TRUE; + return SCPE_OK; + } + if (tf == 'F') { + *result = FALSE; + return SCPE_OK; + } + return SCPE_ARG; +} + +static void show_sio_port_info(FILE *st, SIO_PORT_INFO sip) { + if (sio_unit.flags & UNIT_SIO_VERBOSE) + fprintf(st, "(Port=%02x/Terminal=%1i/Read=0x%02x/NotRead=0x%02x/" + "Write=0x%02x/Reset?=%s/Reset=0x%02x/Data?=%s)", + sip.port, sip.terminalLine, sip.sio_can_read, sip.sio_cannot_read, + sip.sio_can_write, sip.hasReset ? "True" : "False", sip.sio_reset, + sip.hasOUT ? "True" : "False"); + else + fprintf(st, "(%02x/%1i/%02x/%02x/%02x/%s/%02x/%s)", + sip.port, sip.terminalLine, sip.sio_can_read, sip.sio_cannot_read, + sip.sio_can_write, sip.hasReset ? "T" : "F", sip.sio_reset, + sip.hasOUT ? "T" : "F"); +} + +static uint32 equalSIP(SIO_PORT_INFO x, SIO_PORT_INFO y) { + /* isBuiltin is not relevant for equality, only for display */ + return (x.port == y.port) && (x.terminalLine == y.terminalLine) && + (x.sio_can_read == y.sio_can_read) && (x.sio_cannot_read == y.sio_cannot_read) && + (x.sio_can_write == y.sio_can_write) && (x.hasReset == y.hasReset) && + (x.sio_reset == y.sio_reset) && (x.hasOUT == y.hasOUT); +} + +static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc) { + int32 result, n, position; + SIO_PORT_INFO sip = { 0 }, old; + char hasReset, hasOUT; + if (cptr == NULL) + return SCPE_ARG; + result = sscanf(cptr, "%x%n", &sip.port, &n); + if ((result == 1) && (cptr[n] == 0)) { + old = lookupPortInfo(sip.port, &position); + if (old.port == -1) { + printf("No mapping for port 0x%02x exists - cannot remove.\n", sip.port); + return SCPE_ARG; + } + do { + port_table[position] = port_table[position + 1]; + position++; + } while (port_table[position].port != -1); + sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, &nulldev, FALSE); + if (sio_unit.flags & UNIT_SIO_VERBOSE) { + printf("Removing mapping for port 0x%02x.\n\t", sip.port); + show_sio_port_info(stdout, old); + } + return SCPE_OK; + } + result = sscanf(cptr, "%x/%d/%x/%x/%x/%1c/%x/%1c%n", &sip.port, + &sip.terminalLine, &sip.sio_can_read, &sip.sio_cannot_read, + &sip.sio_can_write, &hasReset, &sip.sio_reset, &hasOUT, &n); + if ((result != 8) || (result == EOF) || (cptr[n] != 0)) + return SCPE_ARG; + result = toBool(hasReset, &sip.hasReset); + if (result != SCPE_OK) + return result; + result = toBool(hasOUT, &sip.hasOUT); + if (result != SCPE_OK) + return result; + if (sip.port != (sip.port & 0xff)) { + printf("Truncating port 0x%x to 0x%02x.\n", sip.port, sip.port & 0xff); + sip.port &= 0xff; + } + old = lookupPortInfo(sip.port, &position); + if (old.port == sip.port) { + if (sio_unit.flags & UNIT_SIO_VERBOSE) { + printf("Replacing mapping for port 0x%02x.\n\t", sip.port); + show_sio_port_info(stdout, old); + printf("-> "); + show_sio_port_info(stdout, sip); + if (equalSIP(sip, old)) + printf("[identical]"); + } + } + else { + port_table[position + 1] = old; + if (sio_unit.flags & UNIT_SIO_VERBOSE) { + printf("Adding mapping for port 0x%02x.\n\t", sip.port); + show_sio_port_info(stdout, sip); + } + } + if (sio_unit.flags & UNIT_SIO_VERBOSE) + printf("\n"); + port_table[position] = sip; + sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, (sip.hasOUT || + (sip.sio_can_read == 0) && (sip.sio_cannot_read == 0) && + (sip.sio_can_write == 0)) ? &sio0d : &sio0s, FALSE); + return SCPE_OK; +} + +static t_stat sio_dev_show_port(FILE *st, UNIT *uptr, int32 val, void *desc) { + int32 i, first = TRUE; + for (i = 0; port_table[i].port != -1; i++) + if (!port_table[i].isBuiltin) { + if (first) + first = FALSE; + else + fprintf(st, " "); + show_sio_port_info(st, port_table[i]); + } + if (first) + fprintf(st, "no extra port"); + return SCPE_OK; +} + +static t_stat sio_dev_set_interrupton(UNIT *uptr, int32 value, char *cptr, void *desc) { + keyboardInterrupt = FALSE; + return sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ +} + +static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void *desc) { + keyboardInterrupt = FALSE; + sim_cancel(&sio_unit); + return SCPE_OK; +} + +static t_stat sio_svc(UNIT *uptr) { + if (sio0s(0, 0, 0) & KBD_HAS_CHAR) { + keyboardInterrupt = TRUE; + } + if (sio_unit.flags & UNIT_SIO_INTERRUPT) + sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ + return SCPE_OK; +} + +static void mapAltairPorts(void) { + int32 i = 0; + SIO_PORT_INFO spi; + do { + spi = port_table[i++]; + if ((0x02 <= spi.port) && (spi.port <= 0x19)) + sim_map_resource(spi.port, 1, RESOURCE_TYPE_IO, spi.hasOUT ? &sio0d : &sio0s, FALSE); + } while (spi.port >= 0); +} + +int32 nulldev(const int32 port, const int32 io, const int32 data) { + if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) { + warnUnassignedPort++; + if (io == 0) { + printf("SIO: " ADDRESS_FORMAT " Attempt to input from unassigned port 0x%04x - ignored." NLP, PCX, port); + } + else { + printf("SIO: " ADDRESS_FORMAT " Attempt to output 0x%02x to unassigned port 0x%04x - ignored." NLP, PCX, data, port); + } + } + return io == 0 ? 0xff : 0; +} + +int32 sr_dev(const int32 port, const int32 io, const int32 data) { + return io == 0 ? SR : 0; +} + +static int32 toBCD(const int32 x) { + return (x / 10) * 16 + (x % 10); +} + +static int32 fromBCD(const int32 x) { + return 10 * ((0xf0 & x) >> 4) + (0x0f & x); +} + +/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe. + The following principles apply: + + 1) For commands that do not require parameters and do not return results + ld a, + out (0feh),a + Special case is the reset command which needs to be send 128 times to make + sure that the internal state is properly reset. + + 2) For commands that require parameters and do not return results + ld a, + out (0feh),a + ld a, + out (0feh),a + ld a, + out (0feh),a + ... + Note: The calling program must send all parameter bytes. Otherwise + the pseudo device is left in an undefined 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 undefined state. + + 4) Commands requiring parameters and returning results do not exist currently. + +*/ + +enum simhPseudoDeviceCommands { /* do not change order or remove commands, add only at the end */ + printTimeCmd, /* 0 print the current time in milliseconds */ + startTimerCmd, /* 1 start a new timer on the top of the timer stack */ + stopTimerCmd, /* 2 stop timer on top of timer stack and show time difference */ + resetPTRCmd, /* 3 reset the PTR device */ + attachPTRCmd, /* 4 attach the PTR device */ + detachPTRCmd, /* 5 detach the PTR device */ + getSIMHVersionCmd, /* 6 get the current version of the SIMH pseudo device */ + getClockZSDOSCmd, /* 7 get the current time in ZSDOS format */ + setClockZSDOSCmd, /* 8 set the current time in ZSDOS format */ + getClockCPM3Cmd, /* 9 get the current time in CP/M 3 format */ + setClockCPM3Cmd, /* 10 set the current time in CP/M 3 format */ + getBankSelectCmd, /* 11 get the selected bank */ + setBankSelectCmd, /* 12 set the selected bank */ + getCommonCmd, /* 13 get the base address of the common memory segment */ + resetSIMHInterfaceCmd, /* 14 reset the SIMH pseudo device */ + showTimerCmd, /* 15 show time difference to timer on top of stack */ + attachPTPCmd, /* 16 attach PTP to the file with name at beginning of CP/M command line*/ + detachPTPCmd, /* 17 detach PTP */ + hasBankedMemoryCmd, /* 18 determines whether machine has banked memory */ + setZ80CPUCmd, /* 19 set the CPU to a Z80 */ + set8080CPUCmd, /* 20 set the CPU to an 8080 */ + startTimerInterruptsCmd, /* 21 start timer interrupts */ + stopTimerInterruptsCmd, /* 22 stop timer interrupts */ + setTimerDeltaCmd, /* 23 set the timer interval in which interrupts occur */ + setTimerInterruptAdrCmd, /* 24 set the address to call by timer interrupts */ + resetStopWatchCmd, /* 25 reset the millisecond stop watch */ + readStopWatchCmd, /* 26 read the millisecond stop watch */ + SIMHSleepCmd, /* 27 let SIMH sleep for SIMHSleep microseconds */ + getHostOSPathSeparatorCmd, /* 28 obtain the file path separator of the OS under which SIMH runs */ + getHostFilenamesCmd /* 29 perform wildcard expansion and obtain list of file names */ +}; + +static int32 lastSIMHCommand = getHostFilenamesCmd; + +static char *cmdNames[] = { + "printTime", + "startTimer", + "stopTimer", + "resetPTR", + "attachPTR", + "detachPTR", + "getSIMHVersion", + "getClockZSDOS", + "setClockZSDOS", + "getClockCPM3", + "setClockCPM3", + "getBankSelect", + "setBankSelect", + "getCommon", + "resetSIMHInterface", + "showTimer", + "attachPTP", + "detachPTP", + "hasBankedMemory", + "setZ80CPU", + "set8080CPU", + "startTimerInterrupts", + "stopTimerInterrupts", + "setTimerDelta", + "setTimerInterruptAdr", + "resetStopWatch", + "readStopWatch", + "SIMHSleep", + "getHostOSPathSeparator", + "getHostFilenames" +}; + +#define CPM_COMMAND_LINE_LENGTH 128 +#define TIMER_STACK_LIMIT 10 /* stack depth of timer stack */ +static uint32 markTime[TIMER_STACK_LIMIT]; /* timer stack */ +static struct tm currentTime; +static int32 currentTimeValid = FALSE; +static char version[] = "SIMH003"; + +static t_stat simh_dev_reset(DEVICE *dptr) { + sim_map_resource(0xfe, 1, RESOURCE_TYPE_IO, &simh_dev, dptr->flags & DEV_DIS); + 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) { + TRACE_PRINT(VERBOSE_MSG, + ("SIMH: " ADDRESS_FORMAT " Sorry - no real time clock available." NLP, PCX)); +} + +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 */ + } + warnNoRealTimeClock(); + return SCPE_ARG; +} + +static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) { + timerInterrupt = FALSE; + sim_cancel(&simh_unit); + return SCPE_OK; +} + +static t_stat simh_svc(UNIT *uptr) { + uint32 n = sim_os_msec(); + if (n >= timeOfNextInterrupt) { + timerInterrupt = TRUE; + timeOfNextInterrupt += timerDelta; + if (n >= timeOfNextInterrupt) /* time of next interrupt is not in the future */ + timeOfNextInterrupt = n + timerDelta; /* make sure it is in the future! */ + } + if (simh_unit.flags & UNIT_SIMH_TIMERON) + sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ + return SCPE_OK; +} + +static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH]; +static void createCPMCommandLine(void) { + int32 i, len = (GetBYTEWrapper(0x80) & 0x7f); /* 0x80 contains length of command line, discard first char */ + for (i = 0; i < len - 1; i++) + cpmCommandLine[i] = (char)GetBYTEWrapper(0x82 + i); /* the first char, typically ' ', is discarded */ + cpmCommandLine[i] = 0; /* make C string */ +} + +#if defined (_WIN32) +static void setLastPathSeparator(void) { + int32 i = 0; + while (cpmCommandLine[i]) + i++; + while ((i >= 0) && (cpmCommandLine[i] != '\\')) + i--; + lastPathSeparator = i; + firstPathCharacter = 0; +} +#endif + +/* 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) { + createCPMCommandLine(); + if (uptr == &ptr_unit) + sim_switches = SWMASK('R') | SWMASK('Q'); + else if (uptr == &ptp_unit) + sim_switches = SWMASK('W') | SWMASK('C') | SWMASK('Q'); + /* 'C' option makes sure that file is properly truncated if it had existed before */ + sim_quiet = sim_switches & SWMASK ('Q'); /* -q means quiet */ + lastCPMStatus = attach_unit(uptr, cpmCommandLine); + if ((lastCPMStatus != SCPE_OK) && (simh_device.dctrl & VERBOSE_MSG)) + printf("SIMH: " ADDRESS_FORMAT " Cannot open '%s' (%s)." NLP, PCX, cpmCommandLine, scp_error_messages[lastCPMStatus - SCPE_BASE]); +} + +/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */ +static void setClockZSDOS(void) { + struct tm newTime; + int32 year = fromBCD(GetBYTEWrapper(setClockZSDOSAdr)); + newTime.tm_year = year < 50 ? year + 100 : year; + newTime.tm_mon = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 1)) - 1; + newTime.tm_mday = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 2)); + newTime.tm_hour = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 3)); + newTime.tm_min = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 4)); + newTime.tm_sec = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 5)); + ClockZSDOSDelta = mktime(&newTime) - time(NULL); +} + +#define SECONDS_PER_MINUTE 60 +#define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE) +#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) +static time_t mkCPM3Origin(void) { + struct tm date; + date.tm_year = 77; + date.tm_mon = 11; + date.tm_mday = 31; + date.tm_hour = 0; + date.tm_min = 0; + date.tm_sec = 0; + return mktime(&date); +} + +/* setClockCPM3Adr points to 5 byte block in M: + 0 - 1 int16: days since 31 Dec 77 + 2 BCD byte: HH + 3 BCD byte: MM + 4 BCD byte: SS */ +static void setClockCPM3(void) { + ClockCPM3Delta = mkCPM3Origin() + + (GetBYTEWrapper(setClockCPM3Adr) + GetBYTEWrapper(setClockCPM3Adr + 1) * 256) * SECONDS_PER_DAY + + fromBCD(GetBYTEWrapper(setClockCPM3Adr + 2)) * SECONDS_PER_HOUR + + fromBCD(GetBYTEWrapper(setClockCPM3Adr + 3)) * SECONDS_PER_MINUTE + + fromBCD(GetBYTEWrapper(setClockCPM3Adr + 4)) - time(NULL); +} + +static int32 simh_in(const int32 port) { + int32 result = 0; + switch(lastCommand) { + + case getHostFilenamesCmd: +#if UNIX_PLATFORM + if (globValid) + if (globPosNameList < globS.gl_pathc) { + if (!(result = globS.gl_pathv[globPosNameList][globPosName++])) { + globPosNameList++; + globPosName = 0; + } + } + else { + globValid = FALSE; + lastCommand = 0; + globfree(&globS); + } +#elif defined (_WIN32) + if (globValid) + if (globFinished) + globValid = FALSE; + else if (firstPathCharacter <= lastPathSeparator) { + result = cpmCommandLine[firstPathCharacter++]; + } + else if (!(result = FindFileData.cFileName[globPosName++])) { + globPosName = firstPathCharacter = 0; + if (!FindNextFile(hFind, &FindFileData)) { + globFinished = TRUE; + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + } + } +#else + lastCommand = 0; +#endif + break; + + 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_CPU_BANKED) + result = getBankSelect(); + else { + result = 0; + TRACE_PRINT(VERBOSE_MSG, + ("SIMH: " ADDRESS_FORMAT " Get selected bank ignored for non-banked memory." NLP, PCX)); + } + 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_CPU_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; + + case getHostOSPathSeparatorCmd: +#if defined (__MWERKS__) && defined (macintosh) + result = ':'; /* colon on Macintosh OS 9 */ +#elif defined (_WIN32) + result = '\\'; /* back slash in Windows */ +#else + result = '/'; /* slash in UNIX */ +#endif + break; + + default: + TRACE_PRINT(VERBOSE_MSG, + ("SIMH: " ADDRESS_FORMAT " Undefined IN from SIMH pseudo device on port %03xh ignored." NLP, + PCX, port)); + result = lastCommand = 0; + } + return result; +} + +void do_SIMH_sleep(void) { +#if defined (_WIN32) + if ((SIMHSleep / 1000) && !sio_unit.u4) /* time to sleep and SIO not attached to a file */ + Sleep(SIMHSleep / 1000); +#else + if (SIMHSleep && !sio_unit.u4) /* time to sleep and SIO not attached to a file */ + usleep(SIMHSleep); +#endif +} + +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_CPU_BANKED) + setBankSelect(data & BANKMASK); + else { + TRACE_PRINT(VERBOSE_MSG, + ("SIMH: " ADDRESS_FORMAT " Set selected bank to %i ignored for non-banked memory." + NLP, PCX, 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: + TRACE_PRINT(CMD_MSG, + ("SIMH: " ADDRESS_FORMAT " CMD(0x%02x) <- %i (0x%02x, '%s')" NLP, PCX, port, data, data, + (0 <= data) && (data <= lastSIMHCommand) ? cmdNames[data] : "Unknown command")); + + lastCommand = data; + switch(data) { + + case getHostFilenamesCmd: +#if UNIX_PLATFORM + if (!globValid) { + globValid = TRUE; + globPosNameList = globPosName = 0; + createCPMCommandLine(); + globError = glob(cpmCommandLine, GLOB_ERR, NULL, &globS); + if (globError) { + TRACE_PRINT(VERBOSE_MSG, + ("SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %i." + NLP, PCX, cpmCommandLine, globError)); + globfree(&globS); + globValid = FALSE; + } + } +#elif defined (_WIN32) + if (!globValid) { + globValid = TRUE; + globPosName = 0; + globFinished = FALSE; + createCPMCommandLine(); + setLastPathSeparator(); + hFind = FindFirstFile(cpmCommandLine, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) { + TRACE_PRINT(VERBOSE_MSG, + ("SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %lu." + NLP, PCX, cpmCommandLine, GetLastError())); + globValid = FALSE; + } + } +#endif + break; + + case SIMHSleepCmd: + do_SIMH_sleep(); + break; + + case printTimeCmd: /* print time */ + if (rtc_avail) { + printf("SIMH: " ADDRESS_FORMAT " Current time in milliseconds = %d." NLP, PCX, sim_os_msec()); + } + else { + warnNoRealTimeClock(); + } + break; + + case startTimerCmd: /* create a new timer on top of stack */ + if (rtc_avail) + if (markTimeSP < TIMER_STACK_LIMIT) + markTime[markTimeSP++] = sim_os_msec(); + else { + printf("SIMH: " ADDRESS_FORMAT " Timer stack overflow." NLP, PCX); + } + 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]; + printf("SIMH: " ADDRESS_FORMAT " Timer stopped. Elapsed time in milliseconds = %d." NLP, PCX, delta); + } + else { + printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX); + } + 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 = (int32) ((now - mkCPM3Origin()) / SECONDS_PER_DAY); + getClockCPM3Pos = 0; + break; + + case setClockCPM3Cmd: + setClockCPM3Pos = 0; + break; + + case getBankSelectCmd: + case setBankSelectCmd: + case getCommonCmd: + case hasBankedMemoryCmd: + case getHostOSPathSeparatorCmd: + break; + + case resetSIMHInterfaceCmd: + markTimeSP = 0; + lastCommand = 0; +#if UNIX_PLATFORM + if (globValid) { + globValid = FALSE; + globfree(&globS); + } +#elif defined (_WIN32) + if (globValid) { + globValid = FALSE; + if (hFind != INVALID_HANDLE_VALUE) { + FindClose(hFind); + } + } +#endif + 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]; + printf("SIMH: " ADDRESS_FORMAT " Timer running. Elapsed in milliseconds = %d." NLP, PCX, delta); + } + else { + printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX); + } + 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: + chiptype = CHIP_TYPE_Z80; + break; + + case set8080CPUCmd: + chiptype = CHIP_TYPE_8080; + 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: + TRACE_PRINT(CMD_MSG, + ("SIMH: " ADDRESS_FORMAT " Unknown command (%i) to SIMH pseudo device on port %03xh ignored." + NLP, PCX, data, port)); + } + } + return 0x00; /* 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) { + int32 result = 0; + if (io == 0) { + result = simh_in(port); + TRACE_PRINT(IN_MSG, + ("SIMH: " ADDRESS_FORMAT " IN(0x%02x) -> %i (0x%02x, '%c')" NLP, PCX, port, result, result, + (32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?')); + + } + else { + TRACE_PRINT(OUT_MSG, + ("SIMH: " ADDRESS_FORMAT " OUT(0x%02x) <- %i (0x%02x, '%c')" NLP, PCX, port, data, data, + (32 <= (data & 0xff)) && ((data & 0xff) <= 127) ? (data & 0xff) : '?')); + simh_out(port, data); + } + return result; +} diff --git a/AltairZ80/altairZ80_sys.c b/AltairZ80/altairZ80_sys.c index 5b2066cd..66534a9c 100644 --- a/AltairZ80/altairZ80_sys.c +++ b/AltairZ80/altairZ80_sys.c @@ -1,790 +1,875 @@ -/* altairz80_sys.c: MITS Altair system interface - - Copyright (c) 2002-2008, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited) -*/ - -#include -#include "altairz80_defs.h" - -#define SIM_EMAX 6 - -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern DEVICE cpu_dev; -extern DEVICE sio_dev; -extern DEVICE simh_device; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE dsk_dev; -extern DEVICE hdsk_dev; -extern DEVICE net_dev; - -extern DEVICE mfdc_dev; -extern DEVICE fw2_dev; -extern DEVICE fif_dev; -extern DEVICE vfdhd_dev; -extern DEVICE mdsad_dev; -extern DEVICE nsfpb_dev; -extern DEVICE disk1a_dev; -extern DEVICE disk2_dev; -extern DEVICE selchan_dev; -extern DEVICE ss1_dev; -extern DEVICE i8272_dev; -extern DEVICE mdriveh_dev; - -extern DEVICE cromfdc_dev; -extern DEVICE wd179x_dev; -extern DEVICE n8vem_dev; -extern DEVICE scp300f_dev; - -#ifdef USE_FPC -extern DEVICE fpc_dev; -#endif /* USE_FPC */ - -extern int32 chiptype; -extern long disasm (unsigned char *data, char *output, int segsize, long offset); - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); /* psco */ -t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw); /* psco */ - -t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); - -/* 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 -*/ - -char sim_name[] = "Altair 8800 (Z80)"; -REG *sim_PC = &cpu_reg[6]; -int32 sim_emax = SIM_EMAX; -DEVICE *sim_devices[] = { - &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, - &hdsk_dev, &net_dev, &mfdc_dev, &fw2_dev, &fif_dev, &vfdhd_dev, &mdsad_dev, - &disk1a_dev, &disk2_dev, &selchan_dev, &ss1_dev, &i8272_dev, &mdriveh_dev, - &cromfdc_dev, &wd179x_dev, &n8vem_dev, &scp300f_dev, -#ifdef USE_FPC - &fpc_dev, -#endif /* USE_FPC */ - NULL -}; - -char memoryAccessMessage[80]; -const char *sim_stop_messages[] = { - "HALT instruction", - "Breakpoint", - memoryAccessMessage, - "Invalid Opcode" -}; - -static char *const Mnemonics8080[] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */ - "DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */ - "DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */ - "DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */ - "DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */ - "DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */ - "DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */ - "DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */ - "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */ - "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */ - "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */ - "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 58-5f */ - "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 60-67 */ - "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 68-6f */ - "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */ - "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 78-7f */ - "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */ - "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */ - "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */ - "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */ - "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */ - "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */ - "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */ - "RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */ - "RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */ - "RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */ - "RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */ - "RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */ - "RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */ - "RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */ - "RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */ -}; - -static char *const MnemonicsZ80[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF", /* 30-37 */ - "JR C,$h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,H", "LD B,L", "LD B,(HL)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,H", "LD C,L", "LD C,(HL)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,H", "LD D,L", "LD D,(HL)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,H", "LD E,L", "LD E,(HL)", "LD E,A", /* 58-5f */ - "LD H,B", "LD H,C", "LD H,D", "LD H,E", "LD H,H", "LD H,L", "LD H,(HL)", "LD H,A", /* 60-67 */ - "LD L,B", "LD L,C", "LD L,D", "LD L,E", "LD L,H", "LD L,L", "LD L,(HL)", "LD L,A", /* 68-6f */ - "LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,H", "LD A,L", "LD A,(HL)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,H", "ADD A,L", "ADD A,(HL)", "ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,H", "ADC A,L", "ADC A,(HL)", "ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,H", "SBC A,L", "SBC A,(HL)", "SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c0-c7 */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP HL", "JP PO,#h", "EX (SP),HL", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsCB[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(HL)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(HL)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(HL)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(HL)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(HL)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(HL)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(HL)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(HL)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(HL)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(HL)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(HL)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(HL)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(HL)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(HL)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(HL)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(HL)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(HL)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(HL)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(HL)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(HL)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(HL)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(HL)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(HL)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A" /* f8-ff */ -}; - -static char *const MnemonicsED[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h", /* 00-07 */ - "DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh", /* 08-0f */ - "DB EDh,10h", "DB EDh,11h", "DB EDh,12h", "DB EDh,13h", "DB EDh,14h", "DB EDh,15h", "DB EDh,16h", "DB EDh,17h", /* 10-17 */ - "DB EDh,18h", "DB EDh,19h", "DB EDh,1Ah", "DB EDh,1Bh", "DB EDh,1Ch", "DB EDh,1Dh", "DB EDh,1Eh", "DB EDh,1Fh", /* 18-1f */ - "DB EDh,20h", "DB EDh,21h", "DB EDh,22h", "DB EDh,23h", "DB EDh,24h", "DB EDh,25h", "DB EDh,26h", "DB EDh,27h", /* 20-27 */ - "DB EDh,28h", "DB EDh,29h", "DB EDh,2Ah", "DB EDh,2Bh", "DB EDh,2Ch", "DB EDh,2Dh", "DB EDh,2Eh", "DB EDh,2Fh", /* 28-2f */ - "DB EDh,30h", "DB EDh,31h", "DB EDh,32h", "DB EDh,33h", "DB EDh,34h", "DB EDh,35h", "DB EDh,36h", "DB EDh,37h", /* 30-37 */ - "DB EDh,38h", "DB EDh,39h", "DB EDh,3Ah", "DB EDh,3Bh", "DB EDh,3Ch", "DB EDh,3Dh", "DB EDh,3Eh", "DB EDh,3Fh", /* 38-3f */ - "IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A", /* 40-47 */ - "IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A", /* 48-4f */ - "IN D,(C)", "OUT (C),D", "SBC HL,DE", "LD (#h),DE", "DB EDh,54h", "DB EDh,55h", "IM 1", "LD A,I", /* 50-57 */ - "IN E,(C)", "OUT (C),E", "ADC HL,DE", "LD DE,(#h)", "DB EDh,5Ch", "DB EDh,5Dh", "IM 2", "LD A,R", /* 58-5f */ - "IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD", /* 60-67 */ - "IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD", /* 68-6f */ - "IN F,(C)", "DB EDh,71h", "SBC HL,SP", "LD (#h),SP", "DB EDh,74h", "DB EDh,75h", "DB EDh,76h", "DB EDh,77h", /* 70-77 */ - "IN A,(C)", "OUT (C),A", "ADC HL,SP", "LD SP,(#h)", "DB EDh,7Ch", "DB EDh,7Dh", "DB EDh,7Eh", "DB EDh,7Fh", /* 78-7f */ - "DB EDh,80h", "DB EDh,81h", "DB EDh,82h", "DB EDh,83h", "DB EDh,84h", "DB EDh,85h", "DB EDh,86h", "DB EDh,87h", /* 80-87 */ - "DB EDh,88h", "DB EDh,89h", "DB EDh,8Ah", "DB EDh,8Bh", "DB EDh,8Ch", "DB EDh,8Dh", "DB EDh,8Eh", "DB EDh,8Fh", /* 88-8f */ - "DB EDh,90h", "DB EDh,91h", "DB EDh,92h", "DB EDh,93h", "DB EDh,94h", "DB EDh,95h", "DB EDh,96h", "DB EDh,97h", /* 90-97 */ - "DB EDh,98h", "DB EDh,99h", "DB EDh,9Ah", "DB EDh,9Bh", "DB EDh,9Ch", "DB EDh,9Dh", "DB EDh,9Eh", "DB EDh,9Fh", /* 98-9f */ - "LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h", /* a0-a7 */ - "LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh", /* a8-af */ - "LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h", /* b0-b7 */ - "LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh", /* b8-bf */ - "DB EDh,C0h", "DB EDh,C1h", "DB EDh,C2h", "DB EDh,C3h", "DB EDh,C4h", "DB EDh,C5h", "DB EDh,C6h", "DB EDh,C7h", /* c0-c7 */ - "DB EDh,C8h", "DB EDh,C9h", "DB EDh,CAh", "DB EDh,CBh", "DB EDh,CCh", "DB EDh,CDh", "DB EDh,CEh", "DB EDh,CFh", /* c8-cf */ - "DB EDh,D0h", "DB EDh,D1h", "DB EDh,D2h", "DB EDh,D3h", "DB EDh,D4h", "DB EDh,D5h", "DB EDh,D6h", "DB EDh,D7h", /* d0-d7 */ - "DB EDh,D8h", "DB EDh,D9h", "DB EDh,DAh", "DB EDh,DBh", "DB EDh,DCh", "DB EDh,DDh", "DB EDh,DEh", "DB EDh,DFh", /* d8-df */ - "DB EDh,E0h", "DB EDh,E1h", "DB EDh,E2h", "DB EDh,E3h", "DB EDh,E4h", "DB EDh,E5h", "DB EDh,E6h", "DB EDh,E7h", /* e0-e7 */ - "DB EDh,E8h", "DB EDh,E9h", "DB EDh,EAh", "DB EDh,EBh", "DB EDh,ECh", "DB EDh,EDh", "DB EDh,EEh", "DB EDh,EFh", /* e8-ef */ - "DB EDh,F0h", "DB EDh,F1h", "DB EDh,F2h", "DB EDh,F3h", "DB EDh,F4h", "DB EDh,F5h", "DB EDh,F6h", "DB EDh,F7h", /* f0-f7 */ - "DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh" /* f8-ff */ -}; - -static char *const MnemonicsXX[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h","SCF", /* 30-37 */ - "JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%H", "LD B,I%L", "LD B,(I%+^h)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%H", "LD C,I%L", "LD C,(I%+^h)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%H", "LD D,I%L", "LD D,(I%+^h)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%H", "LD E,I%L", "LD E,(I%+^h)", "LD E,A", /* 58-5f */ - "LD I%H,B", "LD I%H,C", "LD I%H,D", "LD I%H,E", "LD I%H,I%H", "LD I%H,I%L", "LD H,(I%+^h)", "LD I%H,A", /* 60-67 */ - "LD I%L,B", "LD I%L,C", "LD I%L,D", "LD I%L,E", "LD I%L,I%H", "LD I%L,I%L", "LD L,(I%+^h)", "LD I%L,A", /* 68-6f */ - "LD (I%+^h),B", "LD (I%+^h),C", "LD (I%+^h),D", "LD (I%+^h),E", "LD (I%+^h),H", "LD (I%+^h),L", "HALT", "LD (I%+^h),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%H", "LD A,I%L", "LD A,(I%+^h)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%H", "ADD A,I%L", "ADD A,(I%+^h)","ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%H", "ADC A,I%L", "ADC A,(I%+^h)","ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%H", "SBC A,I%L", "SBC A,(I%+^h)","SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP I%", "JP PO,#h", "EX (SP),I%", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsXCB[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(I%@h)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(I%@h)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(I%@h)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(I%@h)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(I%@h)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(I%@h)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(I%@h)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(I%@h)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(I%@h)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(I%@h)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(I%@h)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(I%@h)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(I%@h)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(I%@h)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(I%@h)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(I%@h)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(I%@h)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(I%@h)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(I%@h)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(I%@h)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(I%@h)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(I%@h)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(I%@h)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */ -}; - -/* Symbolic disassembler - - Inputs: - *val = instructions to disassemble - useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used - addr = current PC - Outputs: - *S = output text - - DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997 - You are not allowed to distribute this software - commercially. - -*/ - -static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) { - char R[128], H[10], C = '\0', *T, *P; - uint8 J = 0, Offset = 0; - uint16 B = 0; - - if (useZ80Mnemonics) - switch(val[B]) { - - case 0xcb: - B++; - T = MnemonicsCB[val[B++]]; - break; - - case 0xed: - B++; - T = MnemonicsED[val[B++]]; - break; - - case 0xdd: - - case 0xfd: - C = (val[B++] == 0xdd) ? 'X' : 'Y'; - if (val[B] == 0xcb) { - B++; - Offset = val[B++]; - J = 1; - T = MnemonicsXCB[val[B++]]; - } - else T = MnemonicsXX[val[B++]]; - break; - - default: - T = MnemonicsZ80[val[B++]]; - } - else T = Mnemonics8080[val[B++]]; - - if ( (P = strchr(T, '^')) ) { - strncpy(R, T, P - T); - R[P - T] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(R, H); - strcat(R, P + 1); - } - else strcpy(R, T); - if ( (P = strchr(R, '%')) ) { - *P = C; - if ( (P = strchr(P + 1, '%')) ) *P = C; - } - - if ( (P = strchr(R, '*')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(S, H); - strcat(S, P + 1); - } - else if ( (P = strchr(R, '@')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - if (!J) Offset = val[B++]; - strcat(S, Offset & 0x80 ? "-" : "+"); - J = Offset & 0x80 ? 256 - Offset : Offset; - sprintf(H, "%02X", J); - strcat(S, H); - strcat(S, P + 1); - } - else if ( (P = strchr(R, '$')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - Offset = val[B++]; - sprintf(H, "%04X", (addr + 2 + (Offset & 0x80 ? (Offset - 256) : Offset)) & 0xFFFF); - strcat(S, H); - strcat(S, P + 1); - } - else if ( (P = strchr(R, '#')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%04X", val[B] + 256 * val[B + 1]); - strcat(S, H); - strcat(S, P + 1); - B += 2; - } - else strcpy(S, R); - return(B); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { - char disasm_result[128]; - int32 ch = val[0] & 0x7f; - long r; - unsigned char vals[SIM_EMAX]; - int32 i; - 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; - if (chiptype == CHIP_TYPE_8086) { - for (i = 0; i < SIM_EMAX; i++) vals[i] = val[i] & 0xff; - r = disasm(vals, disasm_result, 16, addr); - } - else - r = DAsm(disasm_result, val, chiptype == CHIP_TYPE_Z80, addr); - fprintf(of, "%s", disasm_result); - return 1 - r; -} - -/* 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); -} - -static int32 numok(char ch, const char **numString, const int32 minvalue, - const int32 maxvalue, const int32 requireSign, int32 *result) { - int32 sign = 1, value = 0, base; - if (requireSign) - if (ch == '+') ch = *(*numString)++; - else if (ch == '-') { - sign = -1; - ch = *(*numString)++; - } - else return FALSE; - if (!(base = checkbase(ch, *numString))) return FALSE; - while (isxdigit(ch)) { - value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10)); - ch = *(*numString)++; - } - if (toupper(ch) != 'H') (*numString)--; - *result = value * sign; - return (minvalue <= value) && (value <= maxvalue); -} - -static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, - int32 *at, int32 *hat, int32 *dollar) { - char pat = *pattern++; - char inp = *input++; - while ((pat) && (inp)) { - switch(pat) { - - case '_': /* patterns 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 int32 checkXY(const char xy) { - return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */ -} - -static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) { - char xyFirst = 0, xy; - int32 op, number, star, at, hat, dollar; - for (op = 0; op < 256; op++) { - number = star = at = dollar = -129; - if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = op; - if (number >= 0) { - val[1] = (0xff) & number; - val[2] = (0xff) & (number >> 8); - return -2; /* two additional bytes returned */ - } - else if (star >= 0) { - val[1] = (0xff) & star; - return -1; /* one additional byte returned */ - } - else if (at > -129) - if ((-128 <= at) && (at <= 127)) { - val[1] = (int8)(at); - return -1; /* one additional byte returned */ - } - else return SCPE_ARG; - else if (dollar >= 0) { - dollar -= addr + 2; /* relative translation */ - if ((-128 <= dollar) && (dollar <= 127)) { - val[1] = (int8)(dollar); - return -1; /* one additional byte returned */ - } - else return SCPE_ARG; - } - else return SCPE_OK; - } - } - if (Mnemonics == Mnemonics8080) return SCPE_ARG; - - for (op = 0; op < 256; op++) - if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xcb; - val[1] = op; - return -1; /* one additional byte returned */ - } - - for (op = 0; op < 256; op++) { - number = -1; - if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xed; - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else return -1; /* one additional byte returned */ - } - } - - for (op = 0; op < 256; op++) { - number = star = hat = -1; - xy = 0; - if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) return SCPE_ARG; - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else if ((star >= 0) && (hat >= 0)) { - val[2] = (0xff) & hat; - val[3] = (0xff) & star; - return -3; /* three additional bytes returned */ - } - else if (star >= 0) { - val[2] = (0xff) & star; - return -2; /* two additional bytes returned */ - } - else if (hat >= 0) { - val[2] = (0xff) & hat; - return -2; /* two additional bytes returned */ - } - else return -1; /* one additional byte returned */ - } - } - - for (op = 0; op < 256; op++) { - at = -129; - xy = 0; - if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) return SCPE_ARG; - val[1] = 0xcb; - if (at > -129) val[2] = (int8) (at); - else { - printf("Offset expected.\n"); - return SCPE_ARG; - } - val[3] = op; - return -3; /* three additional bytes returned */ - } - } - return SCPE_ARG; -} - - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ -t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *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, chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80 : Mnemonics8080); -} - -/* Set Memory Base Address routine */ -t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - uint32 newba; - t_stat r; - - if (cptr == NULL) return SCPE_ARG; - if (uptr == NULL) return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) return SCPE_IERR; - - newba = get_uint (cptr, 16, 0xFFFF, &r); - if (r != SCPE_OK) return r; - - if ((newba > 0xFFFF) || - (newba % pnp->mem_size)) return SCPE_ARG; - - if(dptr->flags & DEV_DIS) { - printf("device not enabled yet.\n"); - pnp->mem_base = newba & ~(pnp->mem_size-1); - } else { - dptr->flags |= DEV_DIS; - dptr->reset(dptr); - pnp->mem_base = newba & ~(pnp->mem_size-1); - dptr->flags &= ~DEV_DIS; - dptr->reset(dptr); - } - - return SCPE_OK; -} - -/* Show Base Address routine */ -t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - - if (uptr == NULL) return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) return SCPE_IERR; - - fprintf(st, "MEM=0x%04X-0x%04X", pnp->mem_base, pnp->mem_base+pnp->mem_size-1); - return SCPE_OK; -} - -/* Set Memory Base Address routine */ -t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - uint32 newba; - t_stat r; - - if (cptr == NULL) return SCPE_ARG; - if (uptr == NULL) return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) return SCPE_IERR; - - newba = get_uint (cptr, 16, 0xFF, &r); - if (r != SCPE_OK) return r; - - if ((newba > 0xFF) || - (newba % pnp->io_size)) return SCPE_ARG; - - if(dptr->flags & DEV_DIS) { - printf("device not enabled yet.\n"); - pnp->io_base = newba & ~(pnp->io_size-1); - } else { - dptr->flags |= DEV_DIS; - dptr->reset(dptr); - pnp->io_base = newba & ~(pnp->io_size-1); - dptr->flags &= ~DEV_DIS; - dptr->reset(dptr); - } - - return SCPE_OK; -} - -/* Show I/O Base Address routine */ -t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - - if (uptr == NULL) return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) return SCPE_IERR; - - fprintf(st, "I/O=0x%02X-0x%02X", pnp->io_base, pnp->io_base+pnp->io_size-1); - return SCPE_OK; -} - +/* altairz80_sys.c: MITS Altair system interface + + Copyright (c) 2002-2008, Peter Schorn + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Peter Schorn shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Peter Schorn. + + Based on work by Charles E Owen (c) 1997 + Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited) +*/ + +#include +#include "altairz80_defs.h" + +#define SIM_EMAX 6 + +extern UNIT cpu_unit; +extern REG cpu_reg[]; +extern DEVICE cpu_dev; +extern DEVICE sio_dev; +extern DEVICE simh_device; +extern DEVICE ptr_dev; +extern DEVICE ptp_dev; +extern DEVICE dsk_dev; +extern DEVICE hdsk_dev; +extern DEVICE net_dev; + +extern DEVICE mfdc_dev; +extern DEVICE fw2_dev; +extern DEVICE fif_dev; +extern DEVICE vfdhd_dev; +extern DEVICE mdsad_dev; +extern DEVICE nsfpb_dev; +extern DEVICE disk1a_dev; +extern DEVICE disk2_dev; +extern DEVICE disk3_dev; +extern DEVICE selchan_dev; +extern DEVICE ss1_dev; +extern DEVICE if3_dev; +extern DEVICE i8272_dev; +extern DEVICE mdriveh_dev; +extern DEVICE switchcpu_dev; + +extern DEVICE adcs6_dev; +extern DEVICE hdc1001_dev; + +extern DEVICE cromfdc_dev; +extern DEVICE wd179x_dev; +extern DEVICE n8vem_dev; +extern DEVICE wdi2_dev; + +extern DEVICE scp300f_dev; + +#ifdef USE_FPC +extern DEVICE fpc_dev; +#endif /* USE_FPC */ + +extern int32 chiptype; +extern long disasm (unsigned char *data, char *output, int segsize, long offset); + +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); +t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw); + +t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); + +/* 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 +*/ + +char sim_name[] = "Altair 8800 (Z80)"; +REG *sim_PC = &cpu_reg[6]; +int32 sim_emax = SIM_EMAX; +DEVICE *sim_devices[] = { + /* AltairZ80 Devices */ + &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, + &hdsk_dev, &net_dev, + /* Advanced Digital (ADC) Devices */ + &adcs6_dev, + &hdc1001_dev, + /* Compupro Devices */ + &disk1a_dev, &disk2_dev, &disk3_dev, &ss1_dev, &mdriveh_dev, &selchan_dev, &if3_dev, + /* Cromemco Devices */ + &cromfdc_dev, + /* IMSAI Devices */ + &fif_dev, + /* Micropolis Devices */ + &mfdc_dev, + /* North Star Devices */ + &mdsad_dev, + /* Seattle Computer Products Devices */ + &scp300f_dev, + /* Vector Graphic Devices */ + &fw2_dev, &vfdhd_dev, + /* Single-Board Computers */ + &n8vem_dev, + /* Floppy Controller Cores */ + &i8272_dev, &wd179x_dev, + NULL +}; + +char memoryAccessMessage[80]; +const char *sim_stop_messages[] = { + "HALT instruction", + "Breakpoint", + memoryAccessMessage, + "Invalid Opcode" +}; + +static char *const Mnemonics8080[] = { +/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + "NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */ + "DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */ + "DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */ + "DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */ + "DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */ + "DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */ + "DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */ + "DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */ + "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */ + "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */ + "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */ + "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 58-5f */ + "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 60-67 */ + "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 68-6f */ + "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */ + "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 78-7f */ + "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */ + "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */ + "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */ + "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */ + "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */ + "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */ + "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */ + "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */ + "RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */ + "RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */ + "RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */ + "RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */ + "RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */ + "RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */ + "RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */ + "RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */ +}; + +static char *const MnemonicsZ80[256] = { +/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ + "EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ + "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ + "JR $h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ + "JR NZ,$h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA", /* 20-27 */ + "JR Z,$h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL", /* 28-2f */ + "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF", /* 30-37 */ + "JR C,$h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ + "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,H", "LD B,L", "LD B,(HL)", "LD B,A", /* 40-47 */ + "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,H", "LD C,L", "LD C,(HL)", "LD C,A", /* 48-4f */ + "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,H", "LD D,L", "LD D,(HL)", "LD D,A", /* 50-57 */ + "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,H", "LD E,L", "LD E,(HL)", "LD E,A", /* 58-5f */ + "LD H,B", "LD H,C", "LD H,D", "LD H,E", "LD H,H", "LD H,L", "LD H,(HL)", "LD H,A", /* 60-67 */ + "LD L,B", "LD L,C", "LD L,D", "LD L,E", "LD L,H", "LD L,L", "LD L,(HL)", "LD L,A", /* 68-6f */ + "LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A", /* 70-77 */ + "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,H", "LD A,L", "LD A,(HL)", "LD A,A", /* 78-7f */ + "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,H", "ADD A,L", "ADD A,(HL)", "ADD A,A", /* 80-87 */ + "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,H", "ADC A,L", "ADC A,(HL)", "ADC A,A", /* 88-8f */ + "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A", /* 90-97 */ + "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,H", "SBC A,L", "SBC A,(HL)", "SBC A,A", /* 98-9f */ + "AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A", /* a0-a7 */ + "XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A", /* a8-af */ + "OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A", /* b0-b7 */ + "CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A", /* b8-bf */ + "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c0-c7 */ + "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ + "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ + "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ + "RET PO", "POP HL", "JP PO,#h", "EX (SP),HL", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h", /* e0-e7 */ + "RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ + "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ + "RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ +}; + +static char *const MnemonicsCB[256] = { +/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */ + "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */ + "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", /* 10-17 */ + "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", /* 18-1f */ + "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", /* 20-27 */ + "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", /* 28-2f */ + "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A", /* 30-37 */ + "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", /* 38-3f */ + "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(HL)", "BIT 0,A", /* 40-47 */ + "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(HL)", "BIT 1,A", /* 48-4f */ + "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(HL)", "BIT 2,A", /* 50-57 */ + "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(HL)", "BIT 3,A", /* 58-5f */ + "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(HL)", "BIT 4,A", /* 60-67 */ + "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(HL)", "BIT 5,A", /* 68-6f */ + "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(HL)", "BIT 6,A", /* 70-77 */ + "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(HL)", "BIT 7,A", /* 78-7f */ + "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(HL)", "RES 0,A", /* 80-87 */ + "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(HL)", "RES 1,A", /* 88-8f */ + "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(HL)", "RES 2,A", /* 90-97 */ + "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(HL)", "RES 3,A", /* 98-9f */ + "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(HL)", "RES 4,A", /* a0-a7 */ + "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(HL)", "RES 5,A", /* a8-af */ + "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(HL)", "RES 6,A", /* b0-b7 */ + "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(HL)", "RES 7,A", /* b8-bf */ + "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(HL)", "SET 0,A", /* c0-c7 */ + "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(HL)", "SET 1,A", /* c8-cf */ + "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(HL)", "SET 2,A", /* d0-d7 */ + "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(HL)", "SET 3,A", /* d8-df */ + "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(HL)", "SET 4,A", /* e0-e7 */ + "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(HL)", "SET 5,A", /* e8-ef */ + "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(HL)", "SET 6,A", /* f0-f7 */ + "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A" /* f8-ff */ +}; + +static char *const MnemonicsED[256] = { +/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + "DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h", /* 00-07 */ + "DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh", /* 08-0f */ + "DB EDh,10h", "DB EDh,11h", "DB EDh,12h", "DB EDh,13h", "DB EDh,14h", "DB EDh,15h", "DB EDh,16h", "DB EDh,17h", /* 10-17 */ + "DB EDh,18h", "DB EDh,19h", "DB EDh,1Ah", "DB EDh,1Bh", "DB EDh,1Ch", "DB EDh,1Dh", "DB EDh,1Eh", "DB EDh,1Fh", /* 18-1f */ + "DB EDh,20h", "DB EDh,21h", "DB EDh,22h", "DB EDh,23h", "DB EDh,24h", "DB EDh,25h", "DB EDh,26h", "DB EDh,27h", /* 20-27 */ + "DB EDh,28h", "DB EDh,29h", "DB EDh,2Ah", "DB EDh,2Bh", "DB EDh,2Ch", "DB EDh,2Dh", "DB EDh,2Eh", "DB EDh,2Fh", /* 28-2f */ + "DB EDh,30h", "DB EDh,31h", "DB EDh,32h", "DB EDh,33h", "DB EDh,34h", "DB EDh,35h", "DB EDh,36h", "DB EDh,37h", /* 30-37 */ + "DB EDh,38h", "DB EDh,39h", "DB EDh,3Ah", "DB EDh,3Bh", "DB EDh,3Ch", "DB EDh,3Dh", "DB EDh,3Eh", "DB EDh,3Fh", /* 38-3f */ + "IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A", /* 40-47 */ + "IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A", /* 48-4f */ + "IN D,(C)", "OUT (C),D", "SBC HL,DE", "LD (#h),DE", "DB EDh,54h", "DB EDh,55h", "IM 1", "LD A,I", /* 50-57 */ + "IN E,(C)", "OUT (C),E", "ADC HL,DE", "LD DE,(#h)", "DB EDh,5Ch", "DB EDh,5Dh", "IM 2", "LD A,R", /* 58-5f */ + "IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD", /* 60-67 */ + "IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD", /* 68-6f */ + "IN F,(C)", "DB EDh,71h", "SBC HL,SP", "LD (#h),SP", "DB EDh,74h", "DB EDh,75h", "DB EDh,76h", "DB EDh,77h", /* 70-77 */ + "IN A,(C)", "OUT (C),A", "ADC HL,SP", "LD SP,(#h)", "DB EDh,7Ch", "DB EDh,7Dh", "DB EDh,7Eh", "DB EDh,7Fh", /* 78-7f */ + "DB EDh,80h", "DB EDh,81h", "DB EDh,82h", "DB EDh,83h", "DB EDh,84h", "DB EDh,85h", "DB EDh,86h", "DB EDh,87h", /* 80-87 */ + "DB EDh,88h", "DB EDh,89h", "DB EDh,8Ah", "DB EDh,8Bh", "DB EDh,8Ch", "DB EDh,8Dh", "DB EDh,8Eh", "DB EDh,8Fh", /* 88-8f */ + "DB EDh,90h", "DB EDh,91h", "DB EDh,92h", "DB EDh,93h", "DB EDh,94h", "DB EDh,95h", "DB EDh,96h", "DB EDh,97h", /* 90-97 */ + "DB EDh,98h", "DB EDh,99h", "DB EDh,9Ah", "DB EDh,9Bh", "DB EDh,9Ch", "DB EDh,9Dh", "DB EDh,9Eh", "DB EDh,9Fh", /* 98-9f */ + "LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h", /* a0-a7 */ + "LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh", /* a8-af */ + "LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h", /* b0-b7 */ + "LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh", /* b8-bf */ + "DB EDh,C0h", "DB EDh,C1h", "DB EDh,C2h", "DB EDh,C3h", "DB EDh,C4h", "DB EDh,C5h", "DB EDh,C6h", "DB EDh,C7h", /* c0-c7 */ + "DB EDh,C8h", "DB EDh,C9h", "DB EDh,CAh", "DB EDh,CBh", "DB EDh,CCh", "DB EDh,CDh", "DB EDh,CEh", "DB EDh,CFh", /* c8-cf */ + "DB EDh,D0h", "DB EDh,D1h", "DB EDh,D2h", "DB EDh,D3h", "DB EDh,D4h", "DB EDh,D5h", "DB EDh,D6h", "DB EDh,D7h", /* d0-d7 */ + "DB EDh,D8h", "DB EDh,D9h", "DB EDh,DAh", "DB EDh,DBh", "DB EDh,DCh", "DB EDh,DDh", "DB EDh,DEh", "DB EDh,DFh", /* d8-df */ + "DB EDh,E0h", "DB EDh,E1h", "DB EDh,E2h", "DB EDh,E3h", "DB EDh,E4h", "DB EDh,E5h", "DB EDh,E6h", "DB EDh,E7h", /* e0-e7 */ + "DB EDh,E8h", "DB EDh,E9h", "DB EDh,EAh", "DB EDh,EBh", "DB EDh,ECh", "DB EDh,EDh", "DB EDh,EEh", "DB EDh,EFh", /* e8-ef */ + "DB EDh,F0h", "DB EDh,F1h", "DB EDh,F2h", "DB EDh,F3h", "DB EDh,F4h", "DB EDh,F5h", "DB EDh,F6h", "DB EDh,F7h", /* f0-f7 */ + "DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh" /* f8-ff */ +}; + +static char *const MnemonicsXX[256] = { +/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ + "EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ + "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ + "JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ + "JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */ + "JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */ + "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h","SCF", /* 30-37 */ + "JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ + "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%H", "LD B,I%L", "LD B,(I%+^h)", "LD B,A", /* 40-47 */ + "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%H", "LD C,I%L", "LD C,(I%+^h)", "LD C,A", /* 48-4f */ + "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%H", "LD D,I%L", "LD D,(I%+^h)", "LD D,A", /* 50-57 */ + "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%H", "LD E,I%L", "LD E,(I%+^h)", "LD E,A", /* 58-5f */ + "LD I%H,B", "LD I%H,C", "LD I%H,D", "LD I%H,E", "LD I%H,I%H", "LD I%H,I%L", "LD H,(I%+^h)", "LD I%H,A", /* 60-67 */ + "LD I%L,B", "LD I%L,C", "LD I%L,D", "LD I%L,E", "LD I%L,I%H", "LD I%L,I%L", "LD L,(I%+^h)", "LD I%L,A", /* 68-6f */ + "LD (I%+^h),B", "LD (I%+^h),C", "LD (I%+^h),D", "LD (I%+^h),E", "LD (I%+^h),H", "LD (I%+^h),L", "HALT", "LD (I%+^h),A", /* 70-77 */ + "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%H", "LD A,I%L", "LD A,(I%+^h)", "LD A,A", /* 78-7f */ + "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%H", "ADD A,I%L", "ADD A,(I%+^h)","ADD A,A", /* 80-87 */ + "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%H", "ADC A,I%L", "ADC A,(I%+^h)","ADC A,A", /* 88-8f */ + "SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */ + "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%H", "SBC A,I%L", "SBC A,(I%+^h)","SBC A,A", /* 98-9f */ + "AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */ + "XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */ + "OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */ + "CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */ + "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */ + "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ + "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ + "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ + "RET PO", "POP I%", "JP PO,#h", "EX (SP),I%", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h", /* e0-e7 */ + "RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ + "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ + "RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ +}; + +static char *const MnemonicsXCB[256] = { +/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */ + "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */ + "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A", /* 10-17 */ + "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A", /* 18-1f */ + "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A", /* 20-27 */ + "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A", /* 28-2f */ + "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A", /* 30-37 */ + "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A", /* 38-3f */ + "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(I%@h)", "BIT 0,A", /* 40-47 */ + "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(I%@h)", "BIT 1,A", /* 48-4f */ + "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(I%@h)", "BIT 2,A", /* 50-57 */ + "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(I%@h)", "BIT 3,A", /* 58-5f */ + "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(I%@h)", "BIT 4,A", /* 60-67 */ + "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(I%@h)", "BIT 5,A", /* 68-6f */ + "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(I%@h)", "BIT 6,A", /* 70-77 */ + "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(I%@h)", "BIT 7,A", /* 78-7f */ + "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(I%@h)", "RES 0,A", /* 80-87 */ + "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(I%@h)", "RES 1,A", /* 88-8f */ + "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(I%@h)", "RES 2,A", /* 90-97 */ + "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(I%@h)", "RES 3,A", /* 98-9f */ + "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(I%@h)", "RES 4,A", /* a0-a7 */ + "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(I%@h)", "RES 5,A", /* a8-af */ + "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(I%@h)", "RES 6,A", /* b0-b7 */ + "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(I%@h)", "RES 7,A", /* b8-bf */ + "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(I%@h)", "SET 0,A", /* c0-c7 */ + "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(I%@h)", "SET 1,A", /* c8-cf */ + "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(I%@h)", "SET 2,A", /* d0-d7 */ + "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(I%@h)", "SET 3,A", /* d8-df */ + "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(I%@h)", "SET 4,A", /* e0-e7 */ + "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(I%@h)", "SET 5,A", /* e8-ef */ + "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(I%@h)", "SET 6,A", /* f0-f7 */ + "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */ +}; + +/* Symbolic disassembler + + Inputs: + *val = instructions to disassemble + useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used + addr = current PC + Outputs: + *S = output text + + DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997 + You are not allowed to distribute this software + commercially. + +*/ + +static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) { + char R[128], H[10], C = '\0', *T, *P; + uint8 J = 0, Offset = 0; + uint16 B = 0; + + if (useZ80Mnemonics) + switch(val[B]) { + + case 0xcb: + B++; + T = MnemonicsCB[val[B++]]; + break; + + case 0xed: + B++; + T = MnemonicsED[val[B++]]; + break; + + case 0xdd: + + case 0xfd: + C = (val[B++] == 0xdd) ? 'X' : 'Y'; + if (val[B] == 0xcb) { + B++; + Offset = val[B++]; + J = 1; + T = MnemonicsXCB[val[B++]]; + } + else + T = MnemonicsXX[val[B++]]; + break; + + default: + T = MnemonicsZ80[val[B++]]; + } + else + T = Mnemonics8080[val[B++]]; + + if ( (P = strchr(T, '^')) ) { + strncpy(R, T, P - T); + R[P - T] = '\0'; + sprintf(H, "%02X", val[B++]); + strcat(R, H); + strcat(R, P + 1); + } + else + strcpy(R, T); + if ( (P = strchr(R, '%')) ) { + *P = C; + if ( (P = strchr(P + 1, '%')) ) + *P = C; + } + + if ( (P = strchr(R, '*')) ) { + strncpy(S, R, P - R); + S[P - R] = '\0'; + sprintf(H, "%02X", val[B++]); + strcat(S, H); + strcat(S, P + 1); + } + else if ( (P = strchr(R, '@')) ) { + strncpy(S, R, P - R); + S[P - R] = '\0'; + if (!J) + Offset = val[B++]; + strcat(S, Offset & 0x80 ? "-" : "+"); + J = Offset & 0x80 ? 256 - Offset : Offset; + sprintf(H, "%02X", J); + strcat(S, H); + strcat(S, P + 1); + } + else if ( (P = strchr(R, '$')) ) { + strncpy(S, R, P - R); + S[P - R] = '\0'; + Offset = val[B++]; + sprintf(H, "%04X", (addr + 2 + (Offset & 0x80 ? (Offset - 256) : Offset)) & 0xFFFF); + strcat(S, H); + strcat(S, P + 1); + } + else if ( (P = strchr(R, '#')) ) { + strncpy(S, R, P - R); + S[P - R] = '\0'; + sprintf(H, "%04X", val[B] + 256 * val[B + 1]); + strcat(S, H); + strcat(S, P + 1); + B += 2; + } + else + strcpy(S, R); + return(B); +} + +/* Symbolic output + + Inputs: + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches + Outputs: + status = error code +*/ + +t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { + char disasm_result[128]; + int32 ch = val[0] & 0x7f; + long r; + unsigned char vals[SIM_EMAX]; + int32 i; + 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; + if (chiptype == CHIP_TYPE_8086) { + for (i = 0; i < SIM_EMAX; i++) + vals[i] = val[i] & 0xff; + r = disasm(vals, disasm_result, 16, addr); + } + else + r = DAsm(disasm_result, val, chiptype == CHIP_TYPE_Z80, addr); + fprintf(of, "%s", disasm_result); + return 1 - r; +} + +/* 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); +} + +static int32 numok(char ch, const char **numString, const int32 minvalue, + const int32 maxvalue, const int32 requireSign, int32 *result) { + int32 sign = 1, value = 0, base; + if (requireSign) + if (ch == '+') + ch = *(*numString)++; + else if (ch == '-') { + sign = -1; + ch = *(*numString)++; + } + else + return FALSE; + if (!(base = checkbase(ch, *numString))) + return FALSE; + while (isxdigit(ch)) { + value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10)); + ch = *(*numString)++; + } + if (toupper(ch) != 'H') + (*numString)--; + *result = value * sign; + return (minvalue <= value) && (value <= maxvalue); +} + +static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, + int32 *at, int32 *hat, int32 *dollar) { + char pat = *pattern++; + char inp = *input++; + while ((pat) && (inp)) { + switch(pat) { + + case '_': /* patterns 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 int32 checkXY(const char xy) { + return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */ +} + +static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) { + char xyFirst = 0, xy; + int32 op, number, star, at, hat, dollar; + for (op = 0; op < 256; op++) { + number = star = at = dollar = -129; + if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { + val[0] = op; + if (number >= 0) { + val[1] = (0xff) & number; + val[2] = (0xff) & (number >> 8); + return -2; /* two additional bytes returned */ + } + else if (star >= 0) { + val[1] = (0xff) & star; + return -1; /* one additional byte returned */ + } + else if (at > -129) + if ((-128 <= at) && (at <= 127)) { + val[1] = (int8)(at); + return -1; /* one additional byte returned */ + } + else + return SCPE_ARG; + else if (dollar >= 0) { + dollar -= addr + 2; /* relative translation */ + if ((-128 <= dollar) && (dollar <= 127)) { + val[1] = (int8)(dollar); + return -1; /* one additional byte returned */ + } + else + return SCPE_ARG; + } + else + return SCPE_OK; + } + } + if (Mnemonics == Mnemonics8080) + return SCPE_ARG; + + for (op = 0; op < 256; op++) + if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { + val[0] = 0xcb; + val[1] = op; + return -1; /* one additional byte returned */ + } + + for (op = 0; op < 256; op++) { + number = -1; + if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { + val[0] = 0xed; + val[1] = op; + if (number >= 0) { + val[2] = (0xff) & number; + val[3] = (0xff) & (number >> 8); + return -3; /* three additional bytes returned */ + } + else + return -1; /* one additional byte returned */ + } + } + + for (op = 0; op < 256; op++) { + number = star = hat = -1; + xy = 0; + if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { + /* all matches must have contained a '%' character */ + if (!(val[0] = checkXY(xy))) + return SCPE_ARG; + val[1] = op; + if (number >= 0) { + val[2] = (0xff) & number; + val[3] = (0xff) & (number >> 8); + return -3; /* three additional bytes returned */ + } + else if ((star >= 0) && (hat >= 0)) { + val[2] = (0xff) & hat; + val[3] = (0xff) & star; + return -3; /* three additional bytes returned */ + } + else if (star >= 0) { + val[2] = (0xff) & star; + return -2; /* two additional bytes returned */ + } + else if (hat >= 0) { + val[2] = (0xff) & hat; + return -2; /* two additional bytes returned */ + } + else + return -1; /* one additional byte returned */ + } + } + + for (op = 0; op < 256; op++) { + at = -129; + xy = 0; + if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { + /* all matches must have contained a '%' character */ + if (!(val[0] = checkXY(xy))) + return SCPE_ARG; + val[1] = 0xcb; + if (at > -129) + val[2] = (int8) (at); + else { + printf("Offset expected.\n"); + return SCPE_ARG; + } + val[3] = op; + return -3; /* three additional bytes returned */ + } + } + return SCPE_ARG; +} + + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = error status +*/ +t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *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, chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80 : Mnemonics8080); +} + +/* Set Memory Base Address routine */ +t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc) +{ + DEVICE *dptr; + PNP_INFO *pnp; + uint32 newba; + t_stat r; + + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + pnp = (PNP_INFO *) dptr->ctxt; + if (pnp == NULL) + return SCPE_IERR; + + newba = get_uint (cptr, 16, 0xFFFF, &r); + if (r != SCPE_OK) + return r; + + if ((newba > 0xFFFF) || (newba % pnp->mem_size)) + return SCPE_ARG; + + if (dptr->flags & DEV_DIS) { + printf("device not enabled yet.\n"); + pnp->mem_base = newba & ~(pnp->mem_size-1); + } else { + dptr->flags |= DEV_DIS; + dptr->reset(dptr); + pnp->mem_base = newba & ~(pnp->mem_size-1); + dptr->flags &= ~DEV_DIS; + dptr->reset(dptr); + } + + return SCPE_OK; +} + +/* Show Base Address routine */ +t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc) +{ + DEVICE *dptr; + PNP_INFO *pnp; + + if (uptr == NULL) + return SCPE_IERR; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + pnp = (PNP_INFO *) dptr->ctxt; + if (pnp == NULL) + return SCPE_IERR; + + fprintf(st, "MEM=0x%04X-0x%04X", pnp->mem_base, pnp->mem_base+pnp->mem_size-1); + return SCPE_OK; +} + +/* Set Memory Base Address routine */ +t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc) +{ + DEVICE *dptr; + PNP_INFO *pnp; + uint32 newba; + t_stat r; + + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + pnp = (PNP_INFO *) dptr->ctxt; + if (pnp == NULL) + return SCPE_IERR; + + newba = get_uint (cptr, 16, 0xFF, &r); + if (r != SCPE_OK) + return r; + + if ((newba > 0xFF) || + (newba % pnp->io_size)) + return SCPE_ARG; + + if (dptr->flags & DEV_DIS) { + printf("device not enabled yet.\n"); + pnp->io_base = newba & ~(pnp->io_size-1); + } else { + dptr->flags |= DEV_DIS; + dptr->reset(dptr); + pnp->io_base = newba & ~(pnp->io_size-1); + dptr->flags &= ~DEV_DIS; + dptr->reset(dptr); + } + + return SCPE_OK; +} + +/* Show I/O Base Address routine */ +t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc) +{ + DEVICE *dptr; + PNP_INFO *pnp; + + if (uptr == NULL) + return SCPE_IERR; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + pnp = (PNP_INFO *) dptr->ctxt; + if (pnp == NULL) + return SCPE_IERR; + + fprintf(st, "I/O=0x%02X-0x%02X", pnp->io_base, pnp->io_base+pnp->io_size-1); + return SCPE_OK; +} + diff --git a/AltairZ80/altairz80_cpu_nommu.c b/AltairZ80/altairz80_cpu_nommu.c index 67d92bec..c952539c 100644 --- a/AltairZ80/altairz80_cpu_nommu.c +++ b/AltairZ80/altairz80_cpu_nommu.c @@ -987,7 +987,7 @@ static uint16 GET_WORD(register uint32 a) { t_stat sim_instr_nommu(void) { extern int32 sim_interval; extern uint32 sim_brk_summ; - int32 reason = 0; + int32 reason = SCPE_OK; register uint32 AF; register uint32 BC; register uint32 DE; @@ -1018,9 +1018,11 @@ t_stat sim_instr_nommu(void) { while (TRUE) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ #if !UNIX_PLATFORM - if ((reason = sim_poll_kbd()) == SCPE_STOP) break; /* poll on platforms without reliable signalling */ + if ((reason = sim_poll_kbd()) == SCPE_STOP) + break; /* poll on platforms without reliable signalling */ #endif - if ((reason = sim_process_event())) break; + if ((reason = sim_process_event())) + break; } if (l_sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) {/* breakpoint? */ @@ -1115,8 +1117,10 @@ t_stat sim_instr_nommu(void) { case 0x10: /* DJNZ dd */ CHECK_CPU_8080; - if ((BC -= 0x100) & 0xff00) PC += (int8) GET_BYTE(PC) + 1; - else PC++; + if ((BC -= 0x100) & 0xff00) + PC += (int8) GET_BYTE(PC) + 1; + else + PC++; break; case 0x11: /* LD DE,nnnn */ @@ -1196,8 +1200,10 @@ t_stat sim_instr_nommu(void) { case 0x20: /* JR NZ,dd */ CHECK_CPU_8080; - if (TSTFLAG(Z)) PC++; - else PC += (int8) GET_BYTE(PC) + 1; + if (TSTFLAG(Z)) + PC++; + else + PC += (int8) GET_BYTE(PC) + 1; break; case 0x21: /* LD HL,nnnn */ @@ -1238,26 +1244,31 @@ t_stat sim_instr_nommu(void) { 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); + if (temp > 5) + SETFLAG(H, 0); acu -= 6; acu &= 0xff; } - if (hd) acu -= 0x160; /* adjust high digit */ + if (hd) + acu -= 0x160; /* adjust high digit */ } 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)) acu += 0x60; /* adjust high digit */ + if (cbits || ((acu & 0x1f0) > 0x90)) + acu += 0x60; /* adjust high digit */ } AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | ((acu >> 8) & 1) | cbits; break; case 0x28: /* JR Z,dd */ CHECK_CPU_8080; - if (TSTFLAG(Z)) PC += (int8) GET_BYTE(PC) + 1; - else PC++; + if (TSTFLAG(Z)) + PC += (int8) GET_BYTE(PC) + 1; + else + PC++; break; case 0x29: /* ADD HL,HL */ @@ -1299,8 +1310,10 @@ t_stat sim_instr_nommu(void) { case 0x30: /* JR NC,dd */ CHECK_CPU_8080; - if (TSTFLAG(C)) PC++; - else PC += (int8) GET_BYTE(PC) + 1; + if (TSTFLAG(C)) + PC++; + else + PC += (int8) GET_BYTE(PC) + 1; break; case 0x31: /* LD SP,nnnn */ @@ -1340,8 +1353,10 @@ t_stat sim_instr_nommu(void) { case 0x38: /* JR C,dd */ CHECK_CPU_8080; - if (TSTFLAG(C)) PC += (int8) GET_BYTE(PC) + 1; - else PC++; + if (TSTFLAG(C)) + PC += (int8) GET_BYTE(PC) + 1; + else + PC++; break; case 0x39: /* ADD HL,SP */ @@ -2050,7 +2065,8 @@ t_stat sim_instr_nommu(void) { break; case 0xc0: /* RET NZ */ - if (!(TSTFLAG(Z))) POP(PC); + if (!(TSTFLAG(Z))) + POP(PC); break; case 0xc1: /* POP BC */ @@ -2087,7 +2103,8 @@ t_stat sim_instr_nommu(void) { break; case 0xc8: /* RET Z */ - if (TSTFLAG(Z)) POP(PC); + if (TSTFLAG(Z)) + POP(PC); break; case 0xc9: /* RET */ @@ -2194,8 +2211,10 @@ t_stat sim_instr_nommu(void) { case 0x40: /* BIT */ 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); + else + AF = (AF & ~0xfe) | 0x54; + if ((op & 7) != 6) + AF |= (acu & 0x28); temp = acu; break; @@ -2265,7 +2284,8 @@ t_stat sim_instr_nommu(void) { break; case 0xd0: /* RET NC */ - if (!(TSTFLAG(C))) POP(PC); + if (!(TSTFLAG(C))) + POP(PC); break; case 0xd1: /* POP DE */ @@ -2302,7 +2322,8 @@ t_stat sim_instr_nommu(void) { break; case 0xd8: /* RET C */ - if (TSTFLAG(C)) POP(PC); + if (TSTFLAG(C)) + POP(PC); break; case 0xd9: /* EXX */ @@ -2845,8 +2866,10 @@ t_stat sim_instr_nommu(void) { case 0x40: /* BIT */ 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); + else + AF = (AF & ~0xfe) | 0x54; + if ((op & 7) != 6) + AF |= (acu & 0x28); temp = acu; break; @@ -2936,7 +2959,8 @@ t_stat sim_instr_nommu(void) { break; case 0xe0: /* RET PO */ - if (!(TSTFLAG(P))) POP(PC); + if (!(TSTFLAG(P))) + POP(PC); break; case 0xe1: /* POP HL */ @@ -2971,7 +2995,8 @@ t_stat sim_instr_nommu(void) { break; case 0xe8: /* RET PE */ - if (TSTFLAG(P)) POP(PC); + if (TSTFLAG(P)) + POP(PC); break; case 0xe9: /* JP (HL) */ @@ -3296,7 +3321,8 @@ t_stat sim_instr_nommu(void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; /* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. @@ -3349,7 +3375,8 @@ t_stat sim_instr_nommu(void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; /* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. @@ -3380,7 +3407,8 @@ t_stat sim_instr_nommu(void) { case 0xb0: /* LDIR */ acu = HIGH_REGISTER(AF); BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { acu = RAM_PP(HL); PUT_BYTE_PP(DE, acu); @@ -3392,7 +3420,8 @@ t_stat sim_instr_nommu(void) { case 0xb1: /* CPIR */ acu = HIGH_REGISTER(AF); BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { temp = RAM_PP(HL); op = --BC != 0; @@ -3403,12 +3432,14 @@ t_stat sim_instr_nommu(void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; case 0xb2: /* INIR */ temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { acu = in(LOW_REGISTER(BC)); PUT_BYTE(HL, acu); @@ -3421,7 +3452,8 @@ t_stat sim_instr_nommu(void) { case 0xb3: /* OTIR */ temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { acu = GET_BYTE(HL); out(LOW_REGISTER(BC), acu); @@ -3434,7 +3466,8 @@ t_stat sim_instr_nommu(void) { case 0xb8: /* LDDR */ BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { acu = RAM_MM(HL); PUT_BYTE_MM(DE, acu); @@ -3446,7 +3479,8 @@ t_stat sim_instr_nommu(void) { case 0xb9: /* CPDR */ acu = HIGH_REGISTER(AF); BC &= ADDRMASK; - if (BC == 0) BC = 0x10000; + if (BC == 0) + BC = 0x10000; do { temp = RAM_MM(HL); op = --BC != 0; @@ -3457,12 +3491,14 @@ t_stat sim_instr_nommu(void) { (((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; + if ((sum & 15) == 8 && (cbits & 16) != 0) + AF &= ~8; break; case 0xba: /* INDR */ temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { acu = in(LOW_REGISTER(BC)); PUT_BYTE(HL, acu); @@ -3475,7 +3511,8 @@ t_stat sim_instr_nommu(void) { case 0xbb: /* OTDR */ temp = HIGH_REGISTER(BC); - if (temp == 0) temp = 0x100; + if (temp == 0) + temp = 0x100; do { acu = GET_BYTE(HL); out(LOW_REGISTER(BC), acu); @@ -3501,7 +3538,8 @@ t_stat sim_instr_nommu(void) { break; case 0xf0: /* RET P */ - if (!(TSTFLAG(S))) POP(PC); + if (!(TSTFLAG(S))) + POP(PC); break; case 0xf1: /* POP AF */ @@ -3534,7 +3572,8 @@ t_stat sim_instr_nommu(void) { break; case 0xf8: /* RET M */ - if (TSTFLAG(S)) POP(PC); + if (TSTFLAG(S)) + POP(PC); break; case 0xf9: /* LD SP,HL */ @@ -4068,8 +4107,10 @@ t_stat sim_instr_nommu(void) { case 0x40: /* BIT */ 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); + else + AF = (AF & ~0xfe) | 0x54; + if ((op & 7) != 6) + AF |= (acu & 0x28); temp = acu; break; diff --git a/AltairZ80/altairz80_hdsk.c b/AltairZ80/altairz80_hdsk.c index 5a01f6c5..21327dbf 100644 --- a/AltairZ80/altairz80_hdsk.c +++ b/AltairZ80/altairz80_hdsk.c @@ -29,6 +29,11 @@ #include "altairz80_defs.h" #include +/* Debug flags */ +#define READ_MSG (1 << 0) +#define WRITE_MSG (1 << 1) +#define VERBOSE_MSG (1 << 2) + /* The following routines are based on work from Howard M. Harte */ static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc); static t_stat show_geom(FILE *st, UNIT *uptr, int32 val, void *desc); @@ -40,8 +45,6 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr); #define UNIT_V_HDSK_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_HDSK_WLK (1 << UNIT_V_HDSK_WLK) -#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_MAX_SECTOR_SIZE 1024 /* maximum size of a sector */ #define HDSK_SECTOR_SIZE u5 /* size of sector */ #define HDSK_SECTORS_PER_TRACK u4 /* sectors per track */ @@ -61,13 +64,11 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr); #define DPB_NAME_LENGTH 15 #define BOOTROM_SIZE_HDSK 256 -extern char messageBuffer[]; extern uint32 PCX; extern REG *sim_PC; extern UNIT cpu_unit; extern void install_ALTAIRbootROM(void); -extern void printMessage(void); extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); extern uint8 GetBYTEWrapper(const uint32 Addr); extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); @@ -87,7 +88,6 @@ static int32 selectedDisk; static int32 selectedSector; static int32 selectedTrack; static int32 selectedDMA; -static int32 trace_level = 0; typedef struct { char name[DPB_NAME_LENGTH + 1]; /* name of CP/M disk parameter block */ @@ -152,30 +152,37 @@ static REG hdsk_reg[] = { { DRDATA (HDSEC, selectedSector, 32), REG_RO }, { DRDATA (HDTRK, selectedTrack, 32), REG_RO }, { DRDATA (HDDMA, selectedDMA, 32), REG_RO }, - { HRDATA (TRACELEVEL, trace_level, 16), }, { NULL } }; static MTAB hdsk_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { MTAB_XTD|MTAB_VUN|MTAB_VAL, 0, "FORMAT", "FORMAT", &set_format, &show_format, NULL }, - { UNIT_HDSK_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_HDSK_WLK, UNIT_HDSK_WLK, "WRTLCK", "WRTLCK", 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 }, - { MTAB_XTD|MTAB_VUN|MTAB_VAL, 0, "GEOM", "GEOM", &set_geom, &show_geom, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", &set_format, &show_format, NULL }, + { UNIT_HDSK_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_HDSK_WLK, UNIT_HDSK_WLK, "WRTLCK", "WRTLCK", NULL }, + { MTAB_XTD|MTAB_VUN, 0, "GEOM", "GEOM", &set_geom, &show_geom, NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if (hdsk_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB hdsk_dt[] = { + { "READ", READ_MSG }, + { "WRITE", WRITE_MSG }, + { "VERBOSE", VERBOSE_MSG }, + { NULL, 0 } +}; + DEVICE hdsk_dev = { "HDSK", hdsk_unit, hdsk_reg, hdsk_mod, 8, 10, 31, 1, 8, 8, NULL, NULL, &hdsk_reset, &hdsk_boot, &hdsk_attach, NULL, - &hdsk_info_data, (DEV_DISABLE), 0, - NULL, NULL, NULL + &hdsk_info_data, (DEV_DISABLE | DEV_DEBUG), 0, + hdsk_dt, NULL, "Hard Disk HDSK" }; /* Reset routine */ @@ -235,11 +242,13 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr) { uptr -> flags |= UNIT_HDSK_WLK; printf("HDSK%c: WARNING: Forcing WRTLCK.\n", unitChar); /* check whether capacity corresponds to setting of tracks, sectors per track and sector size */ - if (uptr -> capac != (uptr -> HDSK_NUMBER_OF_TRACKS * + if (uptr -> capac != (uint32)(uptr -> HDSK_NUMBER_OF_TRACKS * uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE)) { printf("HDSK%c: WARNING: Fixing geometry.\n", unitChar); - if (uptr -> HDSK_SECTORS_PER_TRACK == 0) uptr -> HDSK_SECTORS_PER_TRACK = 32; - if (uptr -> HDSK_SECTOR_SIZE == 0) uptr -> HDSK_SECTOR_SIZE = 128; + if (uptr -> HDSK_SECTORS_PER_TRACK == 0) + uptr -> HDSK_SECTORS_PER_TRACK = 32; + if (uptr -> HDSK_SECTOR_SIZE == 0) + uptr -> HDSK_SECTOR_SIZE = 128; } } else { /* Case 2: disk parameter block found */ @@ -263,12 +272,15 @@ static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc) { uint32 numberOfTracks, numberOfSectors, sectorSize; int result, n; - if (cptr == NULL) return SCPE_ARG; - if (uptr == NULL) return SCPE_IERR; + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; result = sscanf(cptr, "%d/%d/%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n); if ((result != 3) || (result == EOF) || (cptr[n] != 0)) { result = sscanf(cptr, "T:%d/N:%d/S:%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n); - if ((result != 3) || (result == EOF) || (cptr[n] != 0)) return SCPE_ARG; + if ((result != 3) || (result == EOF) || (cptr[n] != 0)) + return SCPE_ARG; } uptr -> HDSK_NUMBER_OF_TRACKS = numberOfTracks; uptr -> HDSK_SECTORS_PER_TRACK = numberOfSectors; @@ -279,7 +291,8 @@ static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc) { /* Show disk geometry routine */ static t_stat show_geom(FILE *st, UNIT *uptr, int32 val, void *desc) { - if (uptr == NULL) return SCPE_IERR; + if (uptr == NULL) + return SCPE_IERR; fprintf(st, "T:%d/N:%d/S:%d", uptr -> HDSK_NUMBER_OF_TRACKS, uptr -> HDSK_SECTORS_PER_TRACK, uptr -> HDSK_SECTOR_SIZE); return SCPE_OK; @@ -292,9 +305,12 @@ static t_stat set_format(UNIT *uptr, int32 val, char *cptr, void *desc) { char fmtname[DPB_NAME_LENGTH + 1]; int32 i; - if (cptr == NULL) return SCPE_ARG; - if (uptr == NULL) return SCPE_IERR; - if (sscanf(cptr, "%" QUOTE2(DPB_NAME_LENGTH) "s", fmtname) == 0) return SCPE_ARG; + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + if (sscanf(cptr, "%" QUOTE2(DPB_NAME_LENGTH) "s", fmtname) == 0) + return SCPE_ARG; for (i = 0; dpb[i].capac != 0; i++) { if (strncmp(fmtname, dpb[i].name, strlen(fmtname)) == 0) { uptr -> HDSK_FORMAT_TYPE = i; @@ -315,7 +331,8 @@ static t_stat set_format(UNIT *uptr, int32 val, char *cptr, void *desc) { /* Show disk format routine */ static t_stat show_format(FILE *st, UNIT *uptr, int32 val, void *desc) { - if (uptr == NULL) return SCPE_IERR; + if (uptr == NULL) + return SCPE_IERR; fprintf(st, "%s", dpb[uptr -> HDSK_FORMAT_TYPE].name); return SCPE_OK; } @@ -375,14 +392,6 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) { return SCPE_OK; } -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hdsk_hasVerbose(void) { - int32 i; - for (i = 0; i < HDSK_NUMBER; i++) - if (hdsk_dev.units[i].flags & UNIT_HDSK_VERBOSE) return TRUE; - return FALSE; -} - /* The hard disk port is 0xfd. It understands the following commands. 1. Reset @@ -436,40 +445,33 @@ static int32 hdsk_hasVerbose(void) { /* check the parameters and return TRUE iff parameters are correct or have been repaired */ static int32 checkParameters(void) { UNIT *uptr = &hdsk_dev.units[selectedDisk]; - int32 currentFlag; if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) { - if (hdsk_hasVerbose()) { - MESSAGE_2("HDSK%d does not exist, will use HDSK0 instead.", selectedDisk); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Disk %i does not exist, will use HDSK0 instead." NLP, + selectedDisk, PCX, selectedDisk)); selectedDisk = 0; } - currentFlag = hdsk_dev.units[selectedDisk].flags; - if ((currentFlag & UNIT_ATT) == 0) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - MESSAGE_2("HDSK%d is not attached.", selectedDisk); - } + if ((hdsk_dev.units[selectedDisk].flags & UNIT_ATT) == 0) { + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Disk %i is not attached." NLP, + selectedDisk, PCX, selectedDisk)); return FALSE; /* cannot read or write */ } if ((selectedSector < 0) || (selectedSector >= uptr -> HDSK_SECTORS_PER_TRACK)) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - MESSAGE_4("HDSK%d: 0 <= Sector=%02d < %d violated, will use 0 instead.", - selectedDisk, selectedSector, uptr -> HDSK_SECTORS_PER_TRACK); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Constraint violation 0 <= Sector=%02d < %d, will use sector 0 instead." NLP, + selectedDisk, PCX, selectedSector, uptr -> HDSK_SECTORS_PER_TRACK)); selectedSector = 0; } if ((selectedTrack < 0) || (selectedTrack >= uptr -> HDSK_NUMBER_OF_TRACKS)) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - MESSAGE_4("HDSK%d: 0 <= Track=%04d < %04d violated, will use 0 instead.", - selectedDisk, selectedTrack, uptr -> HDSK_NUMBER_OF_TRACKS); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Constraint violation 0 <= Track=%04d < %04d, will use track 0 instead." NLP, + selectedDisk, PCX, selectedTrack, uptr -> HDSK_NUMBER_OF_TRACKS)); selectedTrack = 0; } selectedDMA &= ADDRMASK; - if (trace_level) { - MESSAGE_7("%s HDSK%d Track=%04d Sector=%02d Len=%04d DMA=%04x", - (hdskLastCommand == HDSK_READ) ? "Read" : "Write", - selectedDisk, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA); - } + if ((hdsk_dev.dctrl & READ_MSG) && (hdskLastCommand == HDSK_READ)) + printf("HDSK%d " ADDRESS_FORMAT " Read Track=%04d Sector=%02d Len=%04d DMA=%04x" NLP, + selectedDisk, PCX, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA); + if ((hdsk_dev.dctrl & WRITE_MSG) && (hdskLastCommand == HDSK_WRITE)) + printf("HDSK%d " ADDRESS_FORMAT " Write Track=%04d Sector=%02d Len=%04d DMA=%04x" NLP, + selectedDisk, PCX, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA); return TRUE; } @@ -478,13 +480,12 @@ static int32 doSeek(void) { if (fseek(uptr -> fileref, (uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) * selectedTrack + (uptr -> HDSK_SECTOR_SIZE * selectedSector), SEEK_SET)) { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - MESSAGE_4("Could not access HDSK%d Sector=%02d Track=%04d.", - selectedDisk, selectedSector, selectedTrack); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not access Sector=%02d Track=%04d." NLP, + selectedDisk, PCX, selectedSector, selectedTrack)); return CPM_ERROR; } - else return CPM_OK; + else + return CPM_OK; } uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */ @@ -492,17 +493,18 @@ uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */ static int32 doRead(void) { int32 i; UNIT *uptr = &hdsk_dev.units[selectedDisk]; - if (doSeek()) return CPM_ERROR; + if (doSeek()) + return CPM_ERROR; if (fread(hdskbuf, uptr -> HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) { - for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) hdskbuf[i] = CPM_EMPTY; - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - MESSAGE_4("Could not read HDSK%d Sector=%02d Track=%04d.", - selectedDisk, selectedSector, selectedTrack); - } + for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) + hdskbuf[i] = CPM_EMPTY; + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not read Sector=%02d Track=%04d." NLP, + selectedDisk, PCX, selectedSector, selectedTrack)); return CPM_OK; /* allows the creation of empty hard disks */ } - for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) PutBYTEWrapper(selectedDMA + i, hdskbuf[i]); + for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) + PutBYTEWrapper(selectedDMA + i, hdskbuf[i]); return CPM_OK; } @@ -511,21 +513,19 @@ static int32 doWrite(void) { UNIT *uptr = &hdsk_dev.units[selectedDisk]; if (((uptr -> flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */ - if (doSeek()) return CPM_ERROR; - for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); + if (doSeek()) + return CPM_ERROR; + for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) + hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); if (fwrite(hdskbuf, uptr -> HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - MESSAGE_4("Could not write HDSK%d Sector=%02d Track=%04d.", - selectedDisk, selectedSector, selectedTrack); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not write Sector=%02d Track=%04d." NLP, + selectedDisk, PCX, selectedSector, selectedTrack)); return CPM_ERROR; } } else { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - MESSAGE_4("Could not write to locked HDSK%d Sector=%02d Track=%04d.", - selectedDisk, selectedSector, selectedTrack); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not write to locked disk Sector=%02d Track=%04d." NLP, + selectedDisk, PCX, selectedSector, selectedTrack)); return CPM_ERROR; } return CPM_OK; @@ -555,7 +555,8 @@ static int32 hdsk_in(const int32 port) { params[13] = current.off & 0xff; params[14] = (current.off >> 8) & 0xff; params[15] = current.psh; params[16] = current.phm; - if (++paramcount >= 19) hdskLastCommand = HDSK_NONE; + if (++paramcount >= 19) + hdskLastCommand = HDSK_NONE; if (paramcount <= 17) return params[paramcount - 1]; else if (paramcount == 18) @@ -563,13 +564,14 @@ static int32 hdsk_in(const int32 port) { else if (paramcount == 19) return (uptr -> HDSK_SECTOR_SIZE >> 8); else { - MESSAGE_2("HDSK%d Get parameter error.", selectedDisk); + printf("HDSK%d: " ADDRESS_FORMAT " Get parameter error." NLP, + selectedDisk, PCX); } } - else if (hdsk_hasVerbose()) { - MESSAGE_4("Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).", - port, hdskLastCommand, hdskCommandPosition); + else { + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Illegal IN command detected (port=%03xh, cmd=%d, pos=%d)." NLP, + selectedDisk, PCX, port, hdskLastCommand, hdskCommandPosition)); } return CPM_OK; } @@ -627,10 +629,8 @@ static int32 hdsk_out(const int32 port, const int32 data) { if ((HDSK_RESET <= data) && (data <= HDSK_PARAM)) hdskLastCommand = data; else { - if (hdsk_hasVerbose()) { - MESSAGE_3("Illegal OUT command detected (port=%03xh, cmd=%d).", - port, data); - } + TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Illegal OUT command detected (port=%03xh, cmd=%d)." NLP, + selectedDisk, PCX, port, data)); hdskLastCommand = HDSK_RESET; } hdskCommandPosition = 0; diff --git a/AltairZ80/altairz80_net.c b/AltairZ80/altairz80_net.c index 3b4607b5..4c67b206 100644 --- a/AltairZ80/altairz80_net.c +++ b/AltairZ80/altairz80_net.c @@ -26,9 +26,14 @@ #include "altairz80_defs.h" #include "sim_sock.h" + +/* Debug flags */ +#define ACCEPT_MSG (1 << 0) +#define DROP_MSG (1 << 1) +#define IN_MSG (1 << 2) +#define OUT_MSG (1 << 3) + extern uint32 PCX; -extern char messageBuffer[]; -extern void printMessage(void); #define UNIT_V_SERVER (UNIT_V_UF + 0) /* define machine as a server */ #define UNIT_SERVER (1 << UNIT_V_SERVER) @@ -43,13 +48,11 @@ static t_stat set_net (UNIT *uptr, int32 value, char *cptr, void *desc); int32 netStatus (const int32 port, const int32 io, const int32 data); int32 netData (const int32 port, const int32 io, const int32 data); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); + #define MAX_CONNECTIONS 2 /* maximal number of server connections */ #define BUFFER_LENGTH 512 /* length of input and output buffer */ -#define NET_ACCEPT 1 /* bit masks for trace_level */ -#define NET_DROP 2 -#define NET_IN 4 -#define NET_OUT 8 -static int32 trace_level = 0; static struct { int32 Z80StatusPort; /* Z80 status port associated with this ioSocket, read only */ @@ -66,9 +69,9 @@ static struct { int32 outputSize; /* number of characters in circular output buffer */ } serviceDescriptor[MAX_CONNECTIONS+1] = { /* serviceDescriptor[0] holds the information for a client */ /* stat dat ms ios in inPR inPW inS out outPR outPW outS */ - {50, 51, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* client Z80 port 50 and 51 */ - {40, 41, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* server Z80 port 40 and 41 */ - {42, 43, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0} /* server Z80 port 42 and 43 */ + {0x32, 0x33, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* client Z80 port 50 and 51 */ + {0x28, 0x29, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* server Z80 port 40 and 41 */ + {0x2a, 0x2b, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0} /* server Z80 port 42 and 43 */ }; static UNIT net_unit = { @@ -84,7 +87,6 @@ static REG net_reg[] = { { DRDATA (POLL, net_unit.wait, 32) }, { HRDATA (IPHOST, net_unit.u4, 32), REG_RO }, { DRDATA (PORT, net_unit.u3, 32), REG_RO }, - { HRDATA (TRACELEVEL, trace_level, 32) }, { NULL } }; @@ -94,18 +96,31 @@ static MTAB net_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if (net_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB net_dt[] = { + { "ACCEPT", ACCEPT_MSG }, + { "DROP", DROP_MSG }, + { "IN", IN_MSG }, + { "OUT", OUT_MSG }, + { NULL, 0 } +}; + DEVICE net_dev = { "NET", &net_unit, net_reg, net_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &net_reset, NULL, &net_attach, &net_detach, - NULL, 0, 0, - NULL, NULL, NULL + NULL, (DEV_DISABLE | DEV_DEBUG), 0, + net_dt, NULL, "Network NET" }; static t_stat set_net(UNIT *uptr, int32 value, char *cptr, void *desc) { char temp[CBUFSIZE]; - if ((net_unit.flags & UNIT_ATT) && ((net_unit.flags & UNIT_SERVER) != value)) { + if ((net_unit.flags & UNIT_ATT) && ((net_unit.flags & UNIT_SERVER) != (uint32)value)) { strncpy(temp, net_unit.filename, CBUFSIZE); /* save name for later attach */ net_detach(&net_unit); net_unit.flags ^= UNIT_SERVER; /* now switch from client to server and vice versa */ @@ -128,41 +143,54 @@ static t_stat net_reset(DEVICE *dptr) { uint32 i; if (net_unit.flags & UNIT_ATT) sim_activate(&net_unit, net_unit.wait); /* start poll */ - for (i = 0; i <= MAX_CONNECTIONS; i++) + for (i = 0; i <= MAX_CONNECTIONS; i++) { serviceDescriptor_reset(i); + sim_map_resource(serviceDescriptor[i].Z80StatusPort, 1, + RESOURCE_TYPE_IO, &netStatus, dptr->flags & DEV_DIS); + sim_map_resource(serviceDescriptor[i].Z80DataPort, 1, + RESOURCE_TYPE_IO, &netData, dptr->flags & DEV_DIS); + } return SCPE_OK; } static t_stat net_attach(UNIT *uptr, char *cptr) { uint32 i, ipa, ipp; t_stat r = get_ipaddr(cptr, &ipa, &ipp); - if (r != SCPE_OK) return SCPE_ARG; - if (ipa == 0) ipa = 0x7F000001; /* localhost = 127.0.0.1 */ - if (ipp == 0) ipp = 3000; + if (r != SCPE_OK) + return SCPE_ARG; + if (ipa == 0) + ipa = 0x7F000001; /* localhost = 127.0.0.1 */ + if (ipp == 0) + ipp = 3000; net_unit.u3 = ipp; net_unit.u4 = ipa; net_reset(&net_dev); - for (i = 0; i <= MAX_CONNECTIONS; i++) serviceDescriptor[i].ioSocket = 0; + for (i = 0; i <= MAX_CONNECTIONS; i++) + serviceDescriptor[i].ioSocket = 0; if (net_unit.flags & UNIT_SERVER) { net_unit.wait = NET_INIT_POLL_SERVER; serviceDescriptor[1].masterSocket = sim_master_sock(ipp); - if (serviceDescriptor[1].masterSocket == INVALID_SOCKET) return SCPE_IOERR; + if (serviceDescriptor[1].masterSocket == INVALID_SOCKET) + return SCPE_IOERR; } else { net_unit.wait = NET_INIT_POLL_CLIENT; serviceDescriptor[0].ioSocket = sim_connect_sock(ipa, ipp); - if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) return SCPE_IOERR; + if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) + return SCPE_IOERR; } net_unit.flags |= UNIT_ATT; net_unit.filename = (char *) calloc(CBUFSIZE, sizeof (char)); /* alloc name buf */ - if (net_unit.filename == NULL) return SCPE_MEM; + if (net_unit.filename == NULL) + return SCPE_MEM; strncpy(net_unit.filename, cptr, CBUFSIZE); /* save name */ return SCPE_OK; } static t_stat net_detach(UNIT *uptr) { uint32 i; - if (!(net_unit.flags & UNIT_ATT)) return SCPE_OK; /* if not attached simply return */ + if (!(net_unit.flags & UNIT_ATT)) + return SCPE_OK; /* if not attached simply return */ if (net_unit.flags & UNIT_SERVER) sim_close_sock(serviceDescriptor[1].masterSocket, TRUE); for (i = 0; i <= MAX_CONNECTIONS; i++) @@ -187,15 +215,14 @@ static t_stat net_svc(UNIT *uptr) { s = sim_accept_conn(serviceDescriptor[1].masterSocket, NULL); if (s != INVALID_SOCKET) { serviceDescriptor[i].ioSocket = s; - if (trace_level & NET_ACCEPT) { - MESSAGE_3("Accepted connection %i with socket %i.", i, s); - } + TRACE_PRINT(ACCEPT_MSG, ("NET: " ADDRESS_FORMAT " Accepted connection %i with socket %i." NLP, PCX, i, s)); } } } else if (serviceDescriptor[0].ioSocket == 0) { serviceDescriptor[0].ioSocket = sim_connect_sock(net_unit.u4, net_unit.u3); - if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) return SCPE_IOERR; + if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) + return SCPE_IOERR; printf("\rWaiting for server ... Type g (possibly twice) when ready" NLP); return SCPE_STOP; } @@ -205,9 +232,8 @@ static t_stat net_svc(UNIT *uptr) { r = sim_read_sock(serviceDescriptor[i].ioSocket, svcBuffer, BUFFER_LENGTH - serviceDescriptor[i].inputSize); if (r == -1) { - if (trace_level & NET_DROP) { - MESSAGE_3("Drop connection %i with socket %i.", i, serviceDescriptor[i].ioSocket); - } + TRACE_PRINT(DROP_MSG, ("NET: " ADDRESS_FORMAT " Drop connection %i with socket %i." NLP, + PCX, i, serviceDescriptor[i].ioSocket)); sim_close_sock(serviceDescriptor[i].ioSocket, FALSE); serviceDescriptor[i].ioSocket = 0; serviceDescriptor_reset(i); @@ -226,7 +252,8 @@ static t_stat net_svc(UNIT *uptr) { k = serviceDescriptor[i].outputPosRead; for (j = 0; j < serviceDescriptor[i].outputSize; j++) { svcBuffer[j] = serviceDescriptor[i].outputBuffer[k++]; - if (k == BUFFER_LENGTH) k = 0; + if (k == BUFFER_LENGTH) + k = 0; } r = sim_write_sock(serviceDescriptor[i].ioSocket, svcBuffer, serviceDescriptor[i].outputSize); if (r >= 0) { @@ -235,7 +262,8 @@ static t_stat net_svc(UNIT *uptr) { if (serviceDescriptor[i].outputPosRead >= BUFFER_LENGTH) serviceDescriptor[i].outputPosRead -= BUFFER_LENGTH; } - else printf("write %i" NLP, r); + else + printf("write %i" NLP, r); } } } @@ -244,7 +272,8 @@ static t_stat net_svc(UNIT *uptr) { int32 netStatus(const int32 port, const int32 io, const int32 data) { uint32 i; - if ((net_unit.flags & UNIT_ATT) == 0) return 0; + if ((net_unit.flags & UNIT_ATT) == 0) + return 0; net_svc(&net_unit); if (io == 0) /* IN */ for (i = 0; i <= MAX_CONNECTIONS; i++) @@ -257,7 +286,8 @@ int32 netStatus(const int32 port, const int32 io, const int32 data) { int32 netData(const int32 port, const int32 io, const int32 data) { uint32 i; char result; - if ((net_unit.flags & UNIT_ATT) == 0) return 0; + if ((net_unit.flags & UNIT_ATT) == 0) + return 0; net_svc(&net_unit); for (i = 0; i <= MAX_CONNECTIONS; i++) if (serviceDescriptor[i].Z80DataPort == port) @@ -273,10 +303,8 @@ int32 netData(const int32 port, const int32 io, const int32 data) { serviceDescriptor[i].inputPosRead = 0; serviceDescriptor[i].inputSize--; } - if (trace_level & NET_IN) { - MESSAGE_4(" IN(%i)=%03xh (%c)", port, (result & 0xff), - (32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?'); - } + TRACE_PRINT(IN_MSG, ("NET: " ADDRESS_FORMAT " IN(%i)=%03xh (%c)" NLP, PCX, port, (result & 0xff), + (32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?')); return result; } else { /* OUT */ @@ -291,10 +319,8 @@ int32 netData(const int32 port, const int32 io, const int32 data) { serviceDescriptor[i].outputPosWrite = 0; serviceDescriptor[i].outputSize++; } - if (trace_level & NET_OUT) { - MESSAGE_4("OUT(%i)=%03xh (%c)", port, data, - (32 <= data) && (data <= 127) ? data : '?'); - } + TRACE_PRINT(OUT_MSG, ("NET: " ADDRESS_FORMAT " OUT(%i)=%03xh (%c)" NLP, PCX, port, data, + (32 <= data) && (data <= 127) ? data : '?')); return 0; } return 0; diff --git a/AltairZ80/disasm.c b/AltairZ80/disasm.c index 8baaf151..9b6059f5 100644 --- a/AltairZ80/disasm.c +++ b/AltairZ80/disasm.c @@ -1223,45 +1223,47 @@ long disasm (unsigned char *data, char *output, int segsize, long offset) for (p = itable[*data]; *p; p++) { if ( (length = matches(*p, data, asize, osize, segsize, rep, &tmp_ins)) ) { - works = TRUE; - /* - * Final check to make sure the types of r/m match up. - */ - for (i = 0; i < (*p)->operands; i++) { - if ( - /* If it's a mem-only EA but we have a register, die. */ - ((tmp_ins.oprs[i].segment & SEG_RMREG) && - !(MEMORY & ~(*p)->opd[i])) || + works = TRUE; + /* + * Final check to make sure the types of r/m match up. + */ + for (i = 0; i < (*p)->operands; i++) { + if ( + /* If it's a mem-only EA but we have a register, die. */ + ((tmp_ins.oprs[i].segment & SEG_RMREG) && + !(MEMORY & ~(*p)->opd[i])) || - /* If it's a reg-only EA but we have a memory ref, die. */ - (!(tmp_ins.oprs[i].segment & SEG_RMREG) && - !(REGNORM & ~(*p)->opd[i]) && - !((*p)->opd[i] & REG_SMASK)) || + /* If it's a reg-only EA but we have a memory ref, die. */ + (!(tmp_ins.oprs[i].segment & SEG_RMREG) && + !(REGNORM & ~(*p)->opd[i]) && + !((*p)->opd[i] & REG_SMASK)) || - /* Register type mismatch (eg FS vs REG_DESS): die. */ - ((((*p)->opd[i] & (REGISTER | FPUREG)) || - (tmp_ins.oprs[i].segment & SEG_RMREG)) && - !whichreg ((*p)->opd[i], tmp_ins.oprs[i].basereg))) { - works = FALSE; - break; + /* Register type mismatch (eg FS vs REG_DESS): die. */ + ((((*p)->opd[i] & (REGISTER | FPUREG)) || + (tmp_ins.oprs[i].segment & SEG_RMREG)) && + !whichreg ((*p)->opd[i], tmp_ins.oprs[i].basereg))) { + works = FALSE; + break; + } + } + + if (works) { + goodness = (*p)->flags & IF_PFMASK; + if ( goodness < best ) { + /* This is the best one found so far */ + best = goodness; + best_p = p; + best_length = length; + ins = tmp_ins; + } + } } } - if (works) { - goodness = (*p)->flags & IF_PFMASK; - if ( goodness < best ) { - /* This is the best one found so far */ - best = goodness; - best_p = p; - best_length = length; - ins = tmp_ins; - } + if (!best_p) { /* no instruction was matched */ + sprintf(output, "db 0%02xh", data[0]); + return 1; } - } - } - - if (!best_p) - return 0; /* no instruction was matched */ /* Pick the best match */ p = best_p; @@ -1282,13 +1284,13 @@ long disasm (unsigned char *data, char *output, int segsize, long offset) case P_O32: slen += sprintf(output+slen, "o32 "); break; } - for (i = 0; i < elements(ico); i++) + for (i = 0; i < (int)elements(ico); i++) if ((*p)->opcode == ico[i]) { slen += sprintf(output+slen, "%s%s", icn[i], whichcond(ins.condition)); break; } - if (i >= elements(ico)) + if (i >= (int)elements(ico)) slen += sprintf(output+slen, "%s", insn_names[(*p)->opcode]); colon = FALSE; length += data - origdata; /* fix up for prefixes */ diff --git a/AltairZ80/flashwriter2.c b/AltairZ80/flashwriter2.c index 7ff8d541..d4511ce6 100644 --- a/AltairZ80/flashwriter2.c +++ b/AltairZ80/flashwriter2.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: flashwriter2.c 1753 2008-01-02 16:36:47Z Hharte $ * + * $Id: flashwriter2.c 1941 2008-06-13 05:31:03Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http:/*www.hartetec.com * @@ -43,21 +43,12 @@ #include "altairz80_defs.h" -#if defined (_WIN32) -#include -#else -#include "sim_sock.h" -#endif - -#include "sim_tmxr.h" - #ifdef DBG_MSG #define DBG_PRINT(args) printf args #else #define DBG_PRINT(args) #endif - 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 uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, @@ -80,19 +71,16 @@ typedef struct { uint8 M[FW2_CAPACITY]; /* FlashWriter 2K Video Memory */ } FW2_INFO; -static FW2_INFO *fw2_info[4]; -static uint8 port_map[4] = { 0x11, 0x15, 0x17, 0x19 }; +static FW2_INFO *fw2_info[FW2_MAX_BOARDS]; +static uint8 port_map[FW2_MAX_BOARDS] = { 0x11, 0x15, 0x17, 0x19 }; static int32 fw2dev(const int32 Addr, const int32 rw, const int32 data); -static t_stat fw2_reset(DEVICE *dptr); static t_stat fw2_attach(UNIT *uptr, char *cptr); static t_stat fw2_detach(UNIT *uptr); static uint8 FW2_Read(const uint32 Addr); static uint8 FW2_Write(const uint32 Addr, uint8 cData); static t_stat get_base_address(char *cptr, uint32 *baseaddr); -static int32 FWIITrace = FALSE; - static UNIT fw2_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }, @@ -100,11 +88,6 @@ static UNIT fw2_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) } }; -static REG fw2_reg[] = { - { DRDATA (FWIITRACE, FWIITrace, 8), }, - { NULL } -}; - static MTAB fw2_mod[] = { /* quiet, no warning messages */ { UNIT_FW2_VERBOSE, 0, "QUIET", "QUIET", NULL }, @@ -114,20 +97,14 @@ static MTAB fw2_mod[] = { }; DEVICE fw2_dev = { - "FWII", fw2_unit, fw2_reg, fw2_mod, + "FWII", fw2_unit, NULL, fw2_mod, FW2_MAX_BOARDS, 10, 31, 1, FW2_MAX_BOARDS, FW2_MAX_BOARDS, - NULL, NULL, &fw2_reset, + NULL, NULL, NULL, NULL, &fw2_attach, &fw2_detach, - NULL, 0, 0, - NULL, NULL, NULL + NULL, (DEV_DISABLE | DEV_DIS), 0, + NULL, NULL, "Vector Graphic Flashwriter 2 FWII" }; -/* Reset routine */ -static t_stat fw2_reset(DEVICE *dptr) -{ - return SCPE_OK; -} - /* Attach routine */ static t_stat fw2_attach(UNIT *uptr, char *cptr) { @@ -137,7 +114,7 @@ static t_stat fw2_attach(UNIT *uptr, char *cptr) char *tptr; r = get_base_address(cptr, &baseaddr); - if(r != SCPE_OK) /* error?*/ + if(r != SCPE_OK) /* error? */ return r; DBG_PRINT(("%s\n", __FUNCTION__)); @@ -145,7 +122,7 @@ static t_stat fw2_attach(UNIT *uptr, char *cptr) for(i = 0; i < FW2_MAX_BOARDS; i++) { if(&fw2_dev.units[i] == uptr) { if(uptr->flags & UNIT_FW2_VERBOSE) { - printf("Attaching unit %d\n at %04x", i, baseaddr); + printf("Attaching unit %d at %04x\n", i, baseaddr); } break; } @@ -171,7 +148,8 @@ static t_stat fw2_attach(UNIT *uptr, char *cptr) } tptr = (char *) malloc (strlen (cptr) + 3); /* get string buf */ - if (tptr == NULL) return SCPE_MEM; /* no more mem? */ + if (tptr == NULL) + return SCPE_MEM; /* no more mem? */ sprintf(tptr, "0x%04x", baseaddr); /* copy base address */ uptr->filename = tptr; /* save */ uptr->flags = uptr->flags | UNIT_ATT; @@ -192,7 +170,8 @@ static t_stat fw2_detach(UNIT *uptr) } } - if (i >= FW2_MAX_BOARDS) return SCPE_ARG; + if (i >= FW2_MAX_BOARDS) + return SCPE_ARG; /* Disconnect FlashWriter2: unmap memory and I/O resources */ sim_map_resource(fw2_info[i]->uptr->u3, FW2_CAPACITY, RESOURCE_TYPE_MEMORY, &fw2dev, TRUE); @@ -200,7 +179,7 @@ static t_stat fw2_detach(UNIT *uptr) sim_map_resource(0x01, 1, RESOURCE_TYPE_IO, &sio0d, TRUE); if(fw2_info[i]) { - free(fw2_info[1]); + free(fw2_info[i]); } free (uptr->filename); /* free base address string */ @@ -209,7 +188,8 @@ static t_stat fw2_detach(UNIT *uptr) return SCPE_OK; } -static t_stat get_base_address(char *cptr, uint32 *baseaddr) { +static t_stat get_base_address(char *cptr, uint32 *baseaddr) +{ uint32 b; sscanf(cptr, "%x", &b); if(b & (FW2_CAPACITY-1)) { @@ -227,12 +207,13 @@ static int32 fw2dev(const int32 Addr, const int32 rw, const int32 data) { int32 bank = getBankSelect(); if(bank == 0) { - if(rw == 0) { /* Read */ - return(FW2_Read(Addr)); - } else { /* Write */ - return(FW2_Write(Addr, data)); - } - } else return 0xff; + if(rw == 0) { /* Read */ + return(FW2_Read(Addr)); + } else { /* Write */ + return(FW2_Write(Addr, data)); + } + } else + return 0xff; } diff --git a/AltairZ80/i8272.c b/AltairZ80/i8272.c index da2a4e36..af828bab 100644 --- a/AltairZ80/i8272.c +++ b/AltairZ80/i8272.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: i8272.c 1773 2008-01-11 05:46:19Z hharte $ * + * $Id: i8272.c 1999 2008-07-22 04:25:28Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -41,6 +41,8 @@ /* Change log: - 19-Apr-2008, Tony Nicholson, added other .IMD formats + - 06-Aug-2008, Tony Nicholson, READID should use HDS bit and add support + for logical Head and Cylinder maps in the .IMD image file (AGN) */ /*#define DBG_MSG */ @@ -60,19 +62,26 @@ #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 -#define VERBOSE_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define FMT_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) +#define IRQ_MSG (1 << 8) #define I8272_MAX_DRIVES 4 +#define I8272_MAX_SECTOR 26 #define I8272_SECTOR_LEN 8192 +/* 2^(7 + I8272_MAX_N) == I8272_SECTOR_LEN */ +#define I8272_MAX_N 6 -#define CMD_PHASE 0 -#define EXEC_PHASE 1 -#define DATA_PHASE 2 +#define CMD_PHASE 0 +#define EXEC_PHASE 1 +#define DATA_PHASE 2 typedef union { uint8 raw[I8272_SECTOR_LEN]; @@ -99,7 +108,7 @@ typedef struct { uint8 fdc_nd; /* Non-DMA Mode 1=Non-DMA, 0=DMA */ uint8 fdc_head; /* H Head Number */ uint8 fdc_sector; /* R Record (Sector) */ - uint8 fdc_sec_len; /* N Sector Length */ + uint8 fdc_sec_len; /* N Sector Length, in bytes: 2^(7 + fdc_sec_len), fdc_sec_len <= I8272_MAX_N */ uint8 fdc_eot; /* EOT End of Track (Final sector number of cyl) */ uint8 fdc_gpl; /* GPL Gap3 Length */ uint8 fdc_dtl; /* DTL Data Length */ @@ -109,6 +118,8 @@ typedef struct { uint8 fdc_hds; /* Head Select */ uint8 fdc_fillbyte; /* Fill-byte used for FORMAT TRACK */ uint8 fdc_sc; /* Sector count for FORMAT TRACK */ + uint8 fdc_sectorcount; /* Current sector being formatted by FORMAT TRACK */ + uint8 fdc_sectormap[I8272_MAX_SECTOR]; /* Physical to logical sector map for FORMAT TRACK */ uint8 fdc_status[3];/* Status Register Bytes */ uint8 fdc_seek_end; /* Seek was executed successfully */ uint8 cmd_index; /* Index of command byte */ @@ -129,8 +140,8 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ int32 (*routine)(const int32, const int32, const int32), uint8 unmap); /* These are needed for DMA. PIO Mode has not been implemented yet. */ -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); +extern void PutByteDMA(const uint32 Addr, const uint32 Value); +extern uint8 GetByteDMA(const uint32 Addr); #define UNIT_V_I8272_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_I8272_WLK (1 << UNIT_V_I8272_WLK) @@ -166,9 +177,7 @@ extern uint8 GetBYTEWrapper(const uint32 Addr); #define DRIVE_STATUS_WP 0x40 #define DRIVE_STATUS_FAULT 0x80 -static int32 trace_level = 0; /* Disable all tracing by default. */ -static int32 bootstrap = 0; - +static void raise_i8272_interrupt(void); static int32 i8272dev(const int32 port, const int32 io, const int32 data); static t_stat i8272_reset(DEVICE *dptr); int32 find_unit_index (UNIT *uptr); @@ -176,6 +185,8 @@ int32 find_unit_index (UNIT *uptr); I8272_INFO i8272_info_data = { { 0x0, 0, 0xC0, 2 } }; I8272_INFO *i8272_info = &i8272_info_data; +uint8 i8272_irq = 1; + static UNIT i8272_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) }, @@ -183,12 +194,6 @@ static UNIT i8272_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) } }; -static REG i8272_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, - { DRDATA (BOOTSTRAP, bootstrap, 10), }, - { NULL } -}; - static MTAB i8272_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { UNIT_I8272_WLK, 0, "WRTENB", "WRTENB", NULL }, @@ -200,13 +205,32 @@ static MTAB i8272_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if(i8272_dev.dctrl & level) { \ + printf args; \ + } + + +/* Debug Flags */ +static DEBTAB i8272_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "FMT", FMT_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "IRQ", IRQ_MSG }, + { NULL, 0 } +}; + DEVICE i8272_dev = { - "I8272", i8272_unit, i8272_reg, i8272_mod, + "I8272", i8272_unit, NULL, i8272_mod, I8272_MAX_DRIVES, 10, 31, 1, I8272_MAX_DRIVES, I8272_MAX_DRIVES, NULL, NULL, &i8272_reset, NULL, &i8272_attach, &i8272_detach, - &i8272_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &i8272_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + i8272_dt, NULL, "Intel/NEC(765) FDC Core I8272" }; static uint8 I8272_Setup_Cmd(uint8 fdc_cmd); @@ -242,7 +266,8 @@ int32 find_unit_index (UNIT *uptr) DEVICE *dptr; uint32 i; - if (uptr == NULL) return (-1); + if (uptr == NULL) + return (-1); dptr = find_dev_from_unit(uptr); for(i=0; inumunits; i++) { if(dptr->units + i == uptr) { @@ -283,45 +308,41 @@ t_stat i8272_attach(UNIT *uptr, char *cptr) if(uptr->capac > 0) { fgets(header, 4, uptr->fileref); - if(!strcmp(header, "IMD")) { - uptr->u3 = IMAGE_TYPE_IMD; - } else if(!strcmp(header, "CPT")) { - printf("CPT images not yet supported\n"); - uptr->u3 = IMAGE_TYPE_CPT; - i8272_detach(uptr); - return SCPE_OPENERR; - } else { - printf("DSK images not yet supported\n"); - uptr->u3 = IMAGE_TYPE_DSK; - i8272_detach(uptr); + if(strncmp(header, "IMD", 3)) { + printf("I8272: Only IMD disk images are supported\n"); + i8272_info->drive[i].uptr = NULL; return SCPE_OPENERR; } } else { - /* creating file, must be DSK format. */ - printf("Cannot create images, must start with a I8272 IMD image.\n"); - uptr->u3 = IMAGE_TYPE_DSK; - i8272_detach(uptr); - return SCPE_OPENERR; + /* create a disk image file in IMD format. */ + if (diskCreate(uptr->fileref, "$Id: i8272.c 1999 2008-07-22 04:25:28Z hharte $") != SCPE_OK) { + printf("I8272: Failed to create IMD disk.\n"); + i8272_info->drive[i].uptr = NULL; + return SCPE_OPENERR; + } + uptr->capac = sim_fsize(uptr->fileref); } - if (uptr->flags & UNIT_I8272_VERBOSE) + uptr->u3 = IMAGE_TYPE_IMD; + + if (uptr->flags & UNIT_I8272_VERBOSE) { printf("I8272%d: attached to '%s', type=%s, len=%d\n", i, cptr, uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", uptr->capac); + } if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < I8272_CAPACITY_SSSD) { /*was 318000 but changed to allow 8inch SSSD disks*/ - printf("IMD file too small for use with SIMH.\nCopy an existing file and format it with CP/M.\n"); - i8272_detach(uptr); - return SCPE_OPENERR; - } - if (uptr->flags & UNIT_I8272_VERBOSE) printf("--------------------------------------------------------\n"); - i8272_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_I8272_VERBOSE)); - i8272_info->drive[i].ready = 1; + i8272_info->drive[i].imd = diskOpen(uptr->fileref, uptr->flags & UNIT_I8272_VERBOSE); if (uptr->flags & UNIT_I8272_VERBOSE) printf("\n"); + if (i8272_info->drive[i].imd == NULL) { + printf("I8272: IMD disk corrupt.\n"); + i8272_info->drive[i].uptr = NULL; + return SCPE_OPENERR; + } + i8272_info->drive[i].ready = 1; } else { i8272_info->drive[i].imd = NULL; } @@ -343,11 +364,13 @@ t_stat i8272_detach(UNIT *uptr) } DBG_PRINT(("Detach I8272%d\n", i)); - diskClose(i8272_info->drive[i].imd); + r = diskClose(&i8272_info->drive[i].imd); i8272_info->drive[i].ready = 0; + if (r != SCPE_OK) + return r; r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) + if (r != SCPE_OK) return r; return SCPE_OK; @@ -373,17 +396,12 @@ uint8 I8272_Set_DMA(const uint32 dma_addr) return 0; } -static uint8 floorlog2(unsigned int n) -{ - /* Compute log2(n) */ - uint8 r = 0; - if(n >= 1<<16) { n >>=16; r += 16; } - if(n >= 1<< 8) { n >>= 8; r += 8; } - if(n >= 1<< 4) { n >>= 4; r += 4; } - if(n >= 1<< 2) { n >>= 2; r += 2; } - if(n >= 1<< 1) { r += 1; } - return ((n == 0) ? (0xFF) : r); /* 0xFF is error return value */ -} +extern uint8 floorlog2(unsigned int n); + +#define I8272_MSR_RQM (1 << 7) +#define I8272_MSR_DATA_OUT (1 << 6) +#define I8272_MSR_NON_DMA (1 << 5) +#define I8272_MSR_FDC_BUSY (1 << 4) uint8 I8272_Read(const uint32 Addr) { @@ -400,27 +418,36 @@ uint8 I8272_Read(const uint32 Addr) switch(Addr & 0x3) { case I8272_FDC_MSR: - cData = i8272_info->fdc_msr | 0x80; - if(i8272_info->fdc_phase == 0) { - cData &= ~0x40; + cData = i8272_info->fdc_msr | I8272_MSR_RQM; + if(i8272_info->fdc_phase == CMD_PHASE) { + cData &= ~I8272_MSR_DATA_OUT; } else { - cData |= 0x40; + cData |= I8272_MSR_DATA_OUT; } - +#if 0 + if(i8272_info->fdc_phase == EXEC_PHASE) { + cData |= I8272_MSR_FDC_BUSY; + } else { + cData |= ~I8272_MSR_FDC_BUSY; + } +#endif /* 0 hharte */ TRACE_PRINT(STATUS_MSG, ("I8272: " ADDRESS_FORMAT " RD FDC MSR = 0x%02x" NLP, PCX, cData)); break; case I8272_FDC_DATA: if(i8272_info->fdc_phase == DATA_PHASE) { cData = i8272_info->result[i8272_info->result_index]; + TRACE_PRINT(VERBOSE_MSG, ("I8272: " ADDRESS_FORMAT " RD Data, phase=%d, [%d]=0x%02x" NLP, PCX, i8272_info->fdc_phase, i8272_info->result_index, cData)); + i8272_irq = 0; i8272_info->result_index ++; if(i8272_info->result_index == i8272_info->result_len) { TRACE_PRINT(VERBOSE_MSG, ("I8272: " ADDRESS_FORMAT " result phase complete." NLP, PCX)); - i8272_info->fdc_phase = 0; + i8272_info->fdc_phase = CMD_PHASE; } + } else { + cData = i8272_info->result[0]; /* hack, in theory any value should be ok but this makes "format" work */ + TRACE_PRINT(VERBOSE_MSG, ("I8272: " ADDRESS_FORMAT " error, reading data register when not in data phase. " + "Returning 0x%02x" NLP, PCX, cData)); } - - TRACE_PRINT(VERBOSE_MSG, ("I8272: " ADDRESS_FORMAT " RD Data, phase=%d, [%d]=0x%02x" NLP, PCX, i8272_info->fdc_phase, i8272_info->result_index-1, cData)); - break; default: TRACE_PRINT(VERBOSE_MSG, ("I8272: " ADDRESS_FORMAT " Cannot read register %x" NLP, PCX, Addr)); @@ -452,7 +479,7 @@ static char *messages[0x20] = { uint8 I8272_Write(const uint32 Addr, uint8 cData) { I8272_DRIVE_INFO *pDrive; - unsigned int flags; + unsigned int flags = 0; unsigned int readlen; uint8 disk_read = 0; int32 i; @@ -469,6 +496,7 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) PCX, cData)); break; case I8272_FDC_DATA: + i8272_info->fdc_msr &= 0xF0; TRACE_PRINT(VERBOSE_MSG, ("I8272: " ADDRESS_FORMAT " WR Data, phase=%d, index=%d" NLP, PCX, i8272_info->fdc_phase, i8272_info->cmd_index)); if(i8272_info->fdc_phase == CMD_PHASE) { @@ -512,10 +540,27 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) } else { i8272_info->fdc_seek_end = 0; } + if(pDrive->track != i8272_info->cmd[2]) { + TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT + " ERROR: CMD=0x%02x[%s]: Drive: %d, Command wants track %d, but positioner is on track %d." NLP, + PCX, + i8272_info->cmd[0] & 0x1F, + messages[i8272_info->cmd[0] & 0x1F], + i8272_info->sel_drive, + i8272_info->cmd[2], + pDrive->track)); + } + pDrive->track = i8272_info->cmd[2]; - i8272_info->fdc_head = i8272_info->cmd[3]; + i8272_info->fdc_head = i8272_info->cmd[3] & 1; /* AGN mask to head 0 or 1 */ i8272_info->fdc_sector = i8272_info->cmd[4]; i8272_info->fdc_sec_len = i8272_info->cmd[5]; + if(i8272_info->fdc_sec_len > I8272_MAX_N) { + TRACE_PRINT(ERROR_MSG, ("I8272: " ADDRESS_FORMAT " Illegal sector size %d [N=%d]. Reset to %d [N=%d]." NLP, + PCX, 128 << i8272_info->fdc_sec_len, i8272_info->fdc_sec_len, + 128 << I8272_MAX_N, I8272_MAX_N)); + i8272_info->fdc_sec_len = I8272_MAX_N; + } i8272_info->fdc_eot = i8272_info->cmd[6]; i8272_info->fdc_gpl = i8272_info->cmd[7]; i8272_info->fdc_dtl = i8272_info->cmd[8]; @@ -537,7 +582,7 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) i8272_info->fdc_dtl)); i8272_info->fdc_status[0] = (i8272_info->fdc_hds & 1) << 2; - i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 3); + i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03); i8272_info->fdc_status[0] |= 0x40; i8272_info->fdc_status[1] = 0; @@ -546,8 +591,8 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) i8272_info->result[0] = i8272_info->fdc_status[0]; i8272_info->result[1] = i8272_info->fdc_status[1]; i8272_info->result[2] = i8272_info->fdc_status[2]; - i8272_info->result[3] = pDrive->track; - i8272_info->result[4] = i8272_info->fdc_head; + i8272_info->result[3] = pDrive->imd->track[pDrive->track][i8272_info->fdc_head].logicalCyl[i8272_info->fdc_sector]; /* AGN logicalCyl */ + i8272_info->result[4] = pDrive->imd->track[pDrive->track][i8272_info->fdc_head].logicalHead[i8272_info->fdc_sector]; /* AGN logicalHead */ i8272_info->result[5] = i8272_info->fdc_sector; i8272_info->result[6] = i8272_info->fdc_sec_len; break; @@ -559,17 +604,26 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) if(pDrive->uptr == NULL) { return 0xFF; } - /* Compute the i8272 "N" value from the sectorsize of this */ - /* disk's current track - i.e. N = log2(sectsize) - log2(128) */ - /* The calculation also works for non-standard format disk images with */ - /* sectorsizes of 2048, 4096 and 8192 bytes */ + /* Compute the i8272 "N" value from the sectorsize of this */ + /* disk's current track - i.e. N = log2(sectsize) - log2(128) */ + /* The calculation also works for non-standard format disk images with */ + /* sectorsizes of 2048, 4096 and 8192 bytes */ i8272_info->fdc_sec_len = floorlog2( - pDrive->imd->track[pDrive->track][i8272_info->fdc_head].sectsize) - 7; - if(i8272_info->fdc_sec_len == 0xF8) { /*Error calculating N*/ + pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].sectsize) - 7; /* AGN fix to use fdc_hds (was fdc_head)*/ + /* For now always return the starting sector number */ + /* but could return (say) a valid sector number based */ + /* on elapsed time for a more "realistic" simulation. */ + /* This would allow disk analysis programs that use */ + /* READID to detect non-standard disk formats. */ + i8272_info->fdc_sector = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].start_sector; + if((i8272_info->fdc_sec_len == 0xF8) || (i8272_info->fdc_sec_len > I8272_MAX_N)) { /* Error calculating N or N too large */ + TRACE_PRINT(ERROR_MSG, ("I8272: " ADDRESS_FORMAT " Illegal sector size N=%d. Reset to 0." NLP, + PCX, i8272_info->fdc_sec_len)); + i8272_info->fdc_sec_len = 0; return 0xFF; } i8272_info->fdc_status[0] = (i8272_info->fdc_hds & 1) << 2; - i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 3); + i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03); i8272_info->fdc_status[1] = 0; i8272_info->fdc_status[2] = 0; @@ -577,21 +631,20 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) i8272_info->result[0] = i8272_info->fdc_status[0]; i8272_info->result[1] = i8272_info->fdc_status[1]; i8272_info->result[2] = i8272_info->fdc_status[2]; - i8272_info->result[3] = pDrive->track; - i8272_info->result[4] = i8272_info->fdc_head; + i8272_info->result[3] = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].logicalCyl[i8272_info->fdc_sector]; /* AGN logicalCyl */ + i8272_info->result[4] = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].logicalHead[i8272_info->fdc_sector]; /* AGN logicalHead */ i8272_info->result[5] = i8272_info->fdc_sector; - i8272_info->result[6] = i8272_info->fdc_sec_len; /*was hardcoded to 0x3*/ + i8272_info->result[6] = i8272_info->fdc_sec_len; break; case I8272_RECALIBRATE: /* RECALIBRATE */ - i8272_info->sel_drive = i8272_info->cmd[1] & 3; + i8272_info->sel_drive = i8272_info->cmd[1] & 0x03; pDrive = &i8272_info->drive[i8272_info->sel_drive]; if(pDrive->uptr == NULL) { return 0xFF; } pDrive->track = 0; - i8272_info->fdc_phase = 0; /* No result phase */ - pDrive->track = 0; + i8272_info->fdc_phase = CMD_PHASE; /* No result phase */ i8272_info->fdc_seek_end = 1; TRACE_PRINT(SEEK_MSG, ("I8272: " ADDRESS_FORMAT " Recalibrate: Drive 0x%02x" NLP, PCX, i8272_info->sel_drive)); @@ -599,7 +652,7 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) case I8272_FORMAT_TRACK: /* FORMAT A TRACK */ i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6; i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2; - i8272_info->fdc_head = i8272_info->fdc_hds; /* psco added */ + i8272_info->fdc_head = i8272_info->fdc_hds; i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03); pDrive = &i8272_info->drive[i8272_info->sel_drive]; if(pDrive->uptr == NULL) { @@ -612,34 +665,40 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) i8272_info->fdc_seek_end = 0; } i8272_info->fdc_sec_len = i8272_info->cmd[2]; + if(i8272_info->fdc_sec_len > I8272_MAX_N) { + TRACE_PRINT(ERROR_MSG, ("I8272: " ADDRESS_FORMAT " Illegal sector size %d [N=%d]. Reset to %d [N=%d]." NLP, + PCX, 128 << i8272_info->fdc_sec_len, i8272_info->fdc_sec_len, + 128 << I8272_MAX_N, I8272_MAX_N)); + i8272_info->fdc_sec_len = I8272_MAX_N; + } i8272_info->fdc_sc = i8272_info->cmd[3]; i8272_info->fdc_gpl = i8272_info->cmd[4]; i8272_info->fdc_fillbyte = i8272_info->cmd[5]; - TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Format Drive: %d, %s, C=%d. H=%d. N=%d, SC=%d, GPL=%02x, FILL=%02x" NLP, - PCX, - i8272_info->sel_drive, - i8272_info->fdc_mfm ? "MFM" : "FM", - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sec_len, - i8272_info->fdc_sc, - i8272_info->fdc_gpl, - i8272_info->fdc_fillbyte)); + TRACE_PRINT(FMT_MSG, ("I8272: " ADDRESS_FORMAT " Format Drive: %d, %s, C=%d. H=%d. N=%d, SC=%d, GPL=%02x, FILL=%02x" NLP, + PCX, + i8272_info->sel_drive, + i8272_info->fdc_mfm ? "MFM" : "FM", + pDrive->track, + i8272_info->fdc_head, + i8272_info->fdc_sec_len, + i8272_info->fdc_sc, + i8272_info->fdc_gpl, + i8272_info->fdc_fillbyte)); i8272_info->fdc_status[0] = (i8272_info->fdc_hds & 1) << 2; - i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 3); - /*i8272_info->fdc_status[0] |= 0x40; psco removed */ + i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03); i8272_info->fdc_status[1] = 0; i8272_info->fdc_status[2] = 0; + i8272_info->fdc_sectorcount = 0; i8272_info->result[0] = i8272_info->fdc_status[0]; i8272_info->result[1] = i8272_info->fdc_status[1]; i8272_info->result[2] = i8272_info->fdc_status[2]; i8272_info->result[3] = pDrive->track; - i8272_info->result[4] = i8272_info->fdc_head; - i8272_info->result[5] = i8272_info->fdc_sector; + i8272_info->result[4] = i8272_info->fdc_head; /* AGN for now we cannot format with logicalHead */ + i8272_info->result[5] = i8272_info->fdc_sector; /* AGN ditto for logicalCyl */ i8272_info->result[6] = i8272_info->fdc_sec_len; break; case I8272_SENSE_INTR_STATUS: /* SENSE INTERRUPT STATUS */ @@ -647,13 +706,14 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) i8272_info->result[0] = i8272_info->fdc_seek_end ? 0x20 : 0x00; /* SEEK_END */ i8272_info->result[0] |= i8272_info->sel_drive; i8272_info->result[1] = pDrive->track; + i8272_irq = 0; break; case I8272_SPECIFY: /* SPECIFY */ i8272_info->fdc_srt = 16 - ((i8272_info->cmd[1] & 0xF0) >> 4); i8272_info->fdc_hut = (i8272_info->cmd[1] & 0x0F) * 16; i8272_info->fdc_hlt = ((i8272_info->cmd[2] & 0xFE) >> 1) * 2; i8272_info->fdc_nd = (i8272_info->cmd[2] & 0x01); - i8272_info->fdc_phase = 0; /* No result phase */ + i8272_info->fdc_phase = CMD_PHASE; /* No result phase */ TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Specify: SRT=%d, HUT=%d, HLT=%d, ND=%s" NLP, PCX, i8272_info->fdc_srt, @@ -671,15 +731,15 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) i8272_info->result[0] = (pDrive->ready) ? DRIVE_STATUS_READY : 0; /* Drive Ready */ if(imdGetSides(pDrive->imd) == 2) { - i8272_info->result[0] |= DRIVE_STATUS_TWO_SIDED; /* Two-sided? */ + i8272_info->result[0] |= DRIVE_STATUS_TWO_SIDED; /* Two-sided? */ } if(imdIsWriteLocked(pDrive->imd)) { - i8272_info->result[0] |= DRIVE_STATUS_WP; /* Write Protected? */ + i8272_info->result[0] |= DRIVE_STATUS_WP; /* Write Protected? */ } i8272_info->result[0] |= (i8272_info->fdc_hds & 1) << 2; - i8272_info->result[0] |= (i8272_info->sel_drive & 3); + i8272_info->result[0] |= (i8272_info->sel_drive & 0x03); i8272_info->result[0] |= (pDrive->track == 0) ? DRIVE_STATUS_TRACK0 : 0x00; /* Track 0 */ - TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Sense Drive Status = %02x" NLP, + TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Sense Drive Status = 0x%02x" NLP, PCX, i8272_info->result[0])); break; case I8272_SEEK: /* SEEK */ @@ -694,100 +754,69 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) } pDrive->track = i8272_info->cmd[2]; + i8272_info->fdc_head = i8272_info->fdc_hds; /*AGN seek should save the head */ i8272_info->fdc_seek_end = 1; - TRACE_PRINT(SEEK_MSG, ("I8272: " ADDRESS_FORMAT " Seek %d" NLP, - PCX, pDrive->track)); + TRACE_PRINT(SEEK_MSG, ("I8272: " ADDRESS_FORMAT + " Seek Drive: %d, %s %s, C=%d. Skip Deleted Data=%s Head Select=%s" NLP, + PCX, + i8272_info->sel_drive, + i8272_info->fdc_mt ? "Multi" : "Single", + i8272_info->fdc_mfm ? "MFM" : "FM", + i8272_info->cmd[2], + i8272_info->fdc_sk ? "True" : "False", + i8272_info->fdc_hds ? "True" : "False")); break; default: /* INVALID */ break; } - if(i8272_info->fdc_phase == EXEC_PHASE) { - switch(i8272_info->cmd[0] & 0x1F) { - case I8272_READ_TRACK: - printf("I8272: " ADDRESS_FORMAT " Read a track (untested.)" NLP, PCX); - i8272_info->fdc_sector = 1; /* Read entire track from sector 1...eot */ - case I8272_READ_DATA: - case I8272_READ_DELETED_DATA: - disk_read = 1; - case I8272_WRITE_DATA: - case I8272_WRITE_DELETED_DATA: - for(;i8272_info->fdc_sector<=i8272_info->fdc_eot;i8272_info->fdc_sector++) { - TRACE_PRINT(RD_DATA_MSG, ("I8272: " ADDRESS_FORMAT " %s Data, sector: %d sector len=%d" NLP, - PCX, disk_read ? "RD" : "WR", - i8272_info->fdc_sector, - 128 << i8272_info->fdc_sec_len)); - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } - if(disk_read) { /* Read sector */ - sectRead(pDrive->imd, - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sector, - sdata.raw, - 128 << i8272_info->fdc_sec_len, - &flags, - &readlen); + if(i8272_info->fdc_phase == EXEC_PHASE) { + switch(i8272_info->cmd[0] & 0x1F) { + case I8272_READ_TRACK: + printf("I8272: " ADDRESS_FORMAT " Read a track (untested.)" NLP, PCX); + i8272_info->fdc_sector = 1; /* Read entire track from sector 1...eot */ + case I8272_READ_DATA: + case I8272_READ_DELETED_DATA: + disk_read = 1; + case I8272_WRITE_DATA: + case I8272_WRITE_DELETED_DATA: + for(;i8272_info->fdc_sector<=i8272_info->fdc_eot;i8272_info->fdc_sector++) { + TRACE_PRINT(RD_DATA_MSG, ("I8272: " ADDRESS_FORMAT " %s Data, sector: %d sector len=%d" NLP, + PCX, disk_read ? "RD" : "WR", + i8272_info->fdc_sector, + 128 << i8272_info->fdc_sec_len)); - for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) { - PutBYTEWrapper(i8272_info->fdc_dma_addr, sdata.raw[i]); - i8272_info->fdc_dma_addr++; - } - TRACE_PRINT(RD_DATA_MSG, ("I8272: " ADDRESS_FORMAT " Data transferred to RAM at 0x%06x" NLP, - PCX, i8272_info->fdc_dma_addr)); - } else { /* Write */ - for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) { - sdata.raw[i] = GetBYTEWrapper(i8272_info->fdc_dma_addr); - i8272_info->fdc_dma_addr++; - } - TRACE_PRINT(WR_DATA_MSG, ("I8272: " ADDRESS_FORMAT " Data transferred from RAM at 0x%06x" NLP, - PCX, i8272_info->fdc_dma_addr)); - sectWrite(pDrive->imd, - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sector, - sdata.raw, - 128 << i8272_info->fdc_sec_len, - &flags, - &readlen); - } + if(pDrive->imd == NULL) { + printf(".imd is NULL!" NLP); + } + if(disk_read) { /* Read sector */ + sectRead(pDrive->imd, + pDrive->track, + i8272_info->fdc_head, + i8272_info->fdc_sector, + sdata.raw, + 128 << i8272_info->fdc_sec_len, + &flags, + &readlen); - i8272_info->result[5] = i8272_info->fdc_sector; - i8272_info->result[1] = 0x80; - break; - case IMAGE_TYPE_DSK: - printf("%s: DSK Format not supported" NLP, __FUNCTION__); - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; - } - } - break; - case I8272_FORMAT_TRACK: /* FORMAT A TRACK */ - for(i8272_info->fdc_sector = 1;i8272_info->fdc_sector<=i8272_info->fdc_sc;i8272_info->fdc_sector++) { - TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Format Track %d, Sector=%d, len=%d" NLP, - PCX, - pDrive->track, - i8272_info->fdc_sector, - 128 << i8272_info->fdc_sec_len)); - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); + for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) { + PutByteDMA(i8272_info->fdc_dma_addr, sdata.raw[i]); + i8272_info->fdc_dma_addr++; } - TRACE_PRINT(WR_DATA_MSG, ("%s: Write: imd=%p t=%i h=%i s=%i l=%i" NLP, - __FUNCTION__, pDrive->imd, pDrive->track, i8272_info->fdc_head, - i8272_info->fdc_sector, 128 << i8272_info->fdc_sec_len)); - memset(sdata.raw, i8272_info->fdc_fillbyte, 128 << i8272_info->fdc_sec_len); + TRACE_PRINT(RD_DATA_MSG, ("I8272: " ADDRESS_FORMAT " T:%d/H:%d/S:%d/L:%4d: Data transferred to RAM at 0x%06x" NLP, + PCX, + pDrive->track, + i8272_info->fdc_head, + i8272_info->fdc_sector, + 128 << i8272_info->fdc_sec_len, + i8272_info->fdc_dma_addr - i)); + } else { /* Write */ + for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) { + sdata.raw[i] = GetByteDMA(i8272_info->fdc_dma_addr); + i8272_info->fdc_dma_addr++; + } + TRACE_PRINT(WR_DATA_MSG, ("I8272: " ADDRESS_FORMAT " Data transferred from RAM at 0x%06x" NLP, + PCX, i8272_info->fdc_dma_addr)); sectWrite(pDrive->imd, pDrive->track, i8272_info->fdc_head, @@ -796,53 +825,76 @@ uint8 I8272_Write(const uint32 Addr, uint8 cData) 128 << i8272_info->fdc_sec_len, &flags, &readlen); - i8272_info->result[1] = 0x80; - i8272_info->result[5] = i8272_info->fdc_sector; - break; - case IMAGE_TYPE_DSK: - printf("%s: DSK Format not supported" NLP, __FUNCTION__); - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; + } + + i8272_info->result[5] = i8272_info->fdc_sector; + i8272_info->result[1] = 0x80; } - } - break; + break; + case I8272_FORMAT_TRACK: /* FORMAT A TRACK */ + for(i8272_info->fdc_sector = 1;i8272_info->fdc_sector<=i8272_info->fdc_sc;i8272_info->fdc_sector++) { + TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Format Track %d, Sector=%d, len=%d" NLP, + PCX, + pDrive->track, + i8272_info->fdc_sector, + 128 << i8272_info->fdc_sec_len)); - case I8272_SCAN_LOW_EQUAL: /* SCAN LOW OR EQUAL */ - case I8272_SCAN_HIGH_EQUAL: /* SCAN HIGH OR EQUAL */ - case I8272_SCAN_EQUAL: /* SCAN EQUAL */ - TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Scan Data" NLP, - PCX)); - printf("I8272: " ADDRESS_FORMAT " Scan not implemented." NLP, PCX); - break; - case I8272_READ_ID: /* READ ID */ - TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT - " READ ID Drive %d result ST0=%02x ST1=%02x ST2=%02x C=%02x H=%02x R=%02x N=%02x" - NLP, PCX, i8272_info->sel_drive, i8272_info->result[0], - i8272_info->result[1],i8272_info->result[2],i8272_info->result[3], - i8272_info->result[4],i8272_info->result[5],i8272_info->result[6])); - break; + if(i8272_info->fdc_sectorcount >= I8272_MAX_SECTOR) { + TRACE_PRINT(ERROR_MSG, ("I8272: " ADDRESS_FORMAT " Illegal sector count" NLP, PCX)); + i8272_info->fdc_sectorcount = 0; + } + i8272_info->fdc_sectormap[i8272_info->fdc_sectorcount] = i8272_info->fdc_sector; + i8272_info->fdc_sectorcount++; + if(i8272_info->fdc_sectorcount == i8272_info->fdc_sc) { + trackWrite(pDrive->imd, + pDrive->track, + i8272_info->fdc_head, + i8272_info->fdc_sc, + 128 << i8272_info->fdc_sec_len, + i8272_info->fdc_sectormap, + i8272_info->fdc_mfm ? 3 : 0, + i8272_info->fdc_fillbyte, + &flags); - default: - break; + /* Recalculate disk size */ + pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref); + + } + } + break; + + case I8272_SCAN_LOW_EQUAL: /* SCAN LOW OR EQUAL */ + case I8272_SCAN_HIGH_EQUAL: /* SCAN HIGH OR EQUAL */ + case I8272_SCAN_EQUAL: /* SCAN EQUAL */ + TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT " Scan Data" NLP, + PCX)); + TRACE_PRINT(ERROR_MSG, ("I8272: " ADDRESS_FORMAT " ERROR: Scan not implemented." NLP, PCX)); + break; + case I8272_READ_ID: /* READ ID */ + TRACE_PRINT(CMD_MSG, ("I8272: " ADDRESS_FORMAT + " READ ID Drive %d result ST0=%02x ST1=%02x ST2=%02x C=%d H=%d R=%02x N=%d" + NLP, PCX, i8272_info->sel_drive, i8272_info->result[0], + i8272_info->result[1],i8272_info->result[2],i8272_info->result[3], + i8272_info->result[4],i8272_info->result[5],i8272_info->result[6])); + break; + + default: + break; + } } - } - if(i8272_info->result_len != 0) { i8272_info->fdc_phase ++; } else { - i8272_info->fdc_phase = 0; + i8272_info->fdc_phase = CMD_PHASE; } i8272_info->result_index = 0; + if((i8272_info->cmd[0] & 0x1F) != I8272_SENSE_INTR_STATUS) { + raise_i8272_interrupt(); + } } - break; } @@ -904,3 +956,11 @@ static uint8 I8272_Setup_Cmd(uint8 fdc_cmd) return (result); } +extern void raise_disk1a_interrupt(void); + +static void raise_i8272_interrupt(void) +{ + TRACE_PRINT(IRQ_MSG, ("I8272: " ADDRESS_FORMAT " FDC Interrupt" NLP, PCX)); + i8272_irq = 1; + raise_disk1a_interrupt(); +} diff --git a/AltairZ80/i8272.h b/AltairZ80/i8272.h index c3fce099..3182301e 100644 --- a/AltairZ80/i8272.h +++ b/AltairZ80/i8272.h @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: i8272.h 1759 2008-01-05 04:36:46Z hharte $ * + * $Id: i8272.h 1903 2008-05-18 02:21:23Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * diff --git a/AltairZ80/i86_decode.c b/AltairZ80/i86_decode.c index 81291596..b83979ad 100644 --- a/AltairZ80/i86_decode.c +++ b/AltairZ80/i86_decode.c @@ -26,8 +26,6 @@ extern uint32 GetBYTEExtended(register uint32 Addr); extern void PutBYTEExtended(register uint32 Addr, const register uint32 Value); -extern char messageBuffer[]; -extern void printMessage(void); extern int32 AX_S; /* AX register (8086) */ extern int32 BX_S; /* BX register (8086) */ extern int32 CX_S; /* CX register (8086) */ @@ -39,10 +37,10 @@ extern int32 SS_S; /* SS register (8086) */ extern int32 DI_S; /* DI register (8086) */ extern int32 SI_S; /* SI register (8086) */ extern int32 BP_S; /* BP register (8086) */ -extern int32 SP8086_S; /* SP register (8086) */ +extern int32 SPX_S; /* SP register (8086) */ extern int32 IP_S; /* IP register (8086) */ extern int32 FLAGS_S; /* flags register (8086) */ -extern int32 PC_S; /* PC register (8080/Z80/8086), 20 bit */ +extern int32 PCX_S; /* PC register (8086), 20 bit */ extern int32 sim_interval; extern uint32 PCX; /* external view of PC */ extern uint32 sim_brk_summ; @@ -51,6 +49,7 @@ extern UNIT cpu_unit; void i86_intr_raise(PC_ENV *m,uint8 intrnum); void cpu8086reset(void); t_stat sim_instr_8086(void); +void cpu8086_intr(uint8 intrnum); /* $Log: $ * Revision 0.05 1992/04/12 23:16:42 hudgens @@ -121,13 +120,18 @@ void i86_intr_raise(PC_ENV *m,uint8 intrnum) static PC_ENV cpu8086; +void cpu8086_intr(uint8 intrnum) +{ + i86_intr_raise(&cpu8086, intrnum); +} + static void setViewRegisters(void) { FLAGS_S = cpu8086.R_FLG; AX_S = cpu8086.R_AX; BX_S = cpu8086.R_BX; CX_S = cpu8086.R_CX; DX_S = cpu8086.R_DX; - SP8086_S = cpu8086.R_SP; + SPX_S = cpu8086.R_SP; BP_S = cpu8086.R_BP; SI_S = cpu8086.R_SI; DI_S = cpu8086.R_DI; @@ -144,7 +148,7 @@ static void setCPURegisters(void) { cpu8086.R_BX = BX_S; cpu8086.R_CX = CX_S; cpu8086.R_DX = DX_S; - cpu8086.R_SP = SP8086_S; + cpu8086.R_SP = SPX_S; cpu8086.R_BP = BP_S; cpu8086.R_SI = SI_S; cpu8086.R_DI = DI_S; @@ -185,30 +189,34 @@ static uint32 getFullPC(void) { return cpu8086.R_IP + (cpu8086.R_CS << 4); } +extern int32 switch_cpu_now; /* hharte */ + t_stat sim_instr_8086(void) { t_stat reason = SCPE_OK; uint8 op1; int32 newIP; setCPURegisters(); intr = 0; - newIP = PC_S - 16 * CS_S; - if ((0 <= newIP) && (newIP <= 0xffff)) cpu8086.R_IP = newIP; + newIP = PCX_S - 16 * CS_S; + switch_cpu_now = TRUE; /* hharte */ + if ((0 <= newIP) && (newIP <= 0xffff)) + cpu8086.R_IP = newIP; else { - if (CS_S != ((PC_S & 0xf0000) >> 4)) { - cpu8086.R_CS = (PC_S & 0xf0000) >> 4; - if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - MESSAGE_2("Segment register CS set to %04x", cpu8086.R_CS); - } + if (CS_S != ((PCX_S & 0xf0000) >> 4)) { + cpu8086.R_CS = (PCX_S & 0xf0000) >> 4; + if (cpu_unit.flags & UNIT_CPU_VERBOSE) + printf("CPU: " ADDRESS_FORMAT " Segment register CS set to %04x" NLP, PCX, cpu8086.R_CS); } - cpu8086.R_IP = PC_S & 0xffff; + cpu8086.R_IP = PCX_S & 0xffff; } - while (TRUE) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ + while (switch_cpu_now == TRUE) { /* loop until halted */ + if (sim_interval <= 0) { /* check clock queue */ #if !UNIX_PLATFORM - if ((reason = sim_os_poll_kbd()) == SCPE_STOP) /* poll on platforms without reliable signalling */ + if ((reason = sim_os_poll_kbd()) == SCPE_STOP) /* poll on platforms without reliable signalling */ break; #endif - if ( (reason = sim_process_event()) ) break; + if ( (reason = sim_process_event()) ) + break; } if (sim_brk_summ && sim_brk_test(getFullPC(), SWMASK('E'))) { /* breakpoint? */ reason = STOP_IBKPT; /* stop simulation */ @@ -217,7 +225,7 @@ t_stat sim_instr_8086(void) { PCX = getFullPC(); op1 = GetBYTEExtended((((uint32)cpu8086.R_CS<<4) + cpu8086.R_IP) & 0xFFFFF); if (sim_brk_summ && sim_brk_test(op1, (1u << SIM_BKPT_V_SPC) | SWMASK('I'))) { /* instruction breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ + reason = STOP_IBKPT; /* stop simulation */ break; } sim_interval--; @@ -240,17 +248,27 @@ t_stat sim_instr_8086(void) { /* [JCE] Reversed the sense of this ACCESS_FLAG; it's set for interrupts enabled, not interrupts blocked i.e. either not blockable (intr 0 or 2) or the IF flag not set so interrupts not blocked */ - /* hharte: if a segment override exists, then treat that as "atomic" and do not handle - * an interrupt until the override is cleared. - * Not sure if this is the way an 8086 really works, need to find out for sure. - * Also, what about the REPE prefix? - */ - if((cpu8086.sysmode & SYSMODE_SEGMASK) == 0) { - i86_intr_handle(&cpu8086); - } + /* hharte: if a segment override exists, then treat that as "atomic" and do not handle + * an interrupt until the override is cleared. + * Not sure if this is the way an 8086 really works, need to find out for sure. + * Also, what about the REPE prefix? + */ + if ((cpu8086.sysmode & SYSMODE_SEGMASK) == 0) { + i86_intr_handle(&cpu8086); + } } } - PC_S = (reason == STOP_HALT) | (reason == STOP_OPCODE) ? PCX : getFullPC(); + /* It we stopped processing instructions because of a switch to the other + * CPU, then fixup the reason code. + */ + if (switch_cpu_now == FALSE) { + reason = SCPE_OK; + PCX += 2; + PCX_S = PCX; + } else { + PCX_S = (reason == STOP_HALT) | (reason == STOP_OPCODE) ? PCX : getFullPC(); + } + setViewRegisters(); return reason; } diff --git a/AltairZ80/i86_ops.c b/AltairZ80/i86_ops.c index 145e35f0..d289a5be 100644 --- a/AltairZ80/i86_ops.c +++ b/AltairZ80/i86_ops.c @@ -2192,27 +2192,31 @@ static void i86op_opc80_byte_RM_IMM(PC_ENV *m) destval = fetch_data_byte(m,destoffset); imm = fetch_byte_imm(m); destval = (*opc80_byte_operation[rh])(m, destval, imm); - if (rh != 7) store_data_byte(m,destoffset,destval); + if (rh != 7) + store_data_byte(m,destoffset,destval); break; case 1: destoffset=decode_rm01_address(m,rl); destval = fetch_data_byte(m,destoffset); imm = fetch_byte_imm(m); destval = (*opc80_byte_operation[rh])(m, destval, imm); - if (rh != 7) store_data_byte(m,destoffset,destval); + if (rh != 7) + store_data_byte(m,destoffset,destval); break; case 2: destoffset=decode_rm10_address(m,rl); destval = fetch_data_byte(m,destoffset); imm = fetch_byte_imm(m); destval = (*opc80_byte_operation[rh])(m, destval, imm); - if (rh != 7) store_data_byte(m,destoffset,destval); + if (rh != 7) + store_data_byte(m,destoffset,destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(m,rl); imm = fetch_byte_imm(m); destval = (*opc80_byte_operation[rh])(m, *destreg, imm); - if (rh != 7) *destreg = destval; + if (rh != 7) + *destreg = destval; break; } DECODE_CLEAR_SEGOVR(m); @@ -2251,27 +2255,31 @@ static void i86op_opc81_word_RM_IMM(PC_ENV *m) destval = fetch_data_word(m,destoffset); imm = fetch_word_imm(m); destval = (*opc81_word_operation[rh])(m, destval, imm); - if (rh != 7) store_data_word(m,destoffset,destval); + if (rh != 7) + store_data_word(m,destoffset,destval); break; case 1: destoffset=decode_rm01_address(m,rl); destval = fetch_data_word(m,destoffset); imm = fetch_word_imm(m); destval = (*opc81_word_operation[rh])(m, destval, imm); - if (rh != 7) store_data_word(m,destoffset,destval); + if (rh != 7) + store_data_word(m,destoffset,destval); break; case 2: destoffset=decode_rm10_address(m,rl); destval = fetch_data_word(m,destoffset); imm = fetch_word_imm(m); destval = (*opc81_word_operation[rh])(m, destval, imm); - if (rh != 7) store_data_word(m,destoffset,destval); + if (rh != 7) + store_data_word(m,destoffset,destval); break; case 3: /* register to register */ destreg = DECODE_RM_WORD_REGISTER(m,rl); imm = fetch_word_imm(m); destval = (*opc81_word_operation[rh])(m, *destreg, imm); - if (rh != 7) *destreg = destval; + if (rh != 7) + *destreg = destval; break; } DECODE_CLEAR_SEGOVR(m); @@ -2313,27 +2321,31 @@ static void i86op_opc82_byte_RM_IMM(PC_ENV *m) destval = fetch_data_byte(m,destoffset); imm = fetch_byte_imm(m); destval = (*opc82_byte_operation[rh])(m, destval, imm); - if (rh != 7) store_data_byte(m,destoffset,destval); + if (rh != 7) + store_data_byte(m,destoffset,destval); break; case 1: destoffset=decode_rm01_address(m,rl); destval = fetch_data_byte(m,destoffset); imm = fetch_byte_imm(m); destval = (*opc82_byte_operation[rh])(m, destval, imm); - if (rh != 7) store_data_byte(m,destoffset,destval); + if (rh != 7) + store_data_byte(m,destoffset,destval); break; case 2: destoffset=decode_rm10_address(m,rl); destval = fetch_data_byte(m,destoffset); imm = fetch_byte_imm(m); destval = (*opc82_byte_operation[rh])(m, destval, imm); - if (rh != 7) store_data_byte(m,destoffset,destval); + if (rh != 7) + store_data_byte(m,destoffset,destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(m,rl); imm = fetch_byte_imm(m); destval = (*opc82_byte_operation[rh])(m, *destreg, imm); - if (rh != 7) *destreg = destval; + if (rh != 7) + *destreg = destval; break; } DECODE_CLEAR_SEGOVR(m); @@ -2375,27 +2387,31 @@ static void i86op_opc83_word_RM_IMM(PC_ENV *m) destval = fetch_data_word(m,destoffset); imm = (int8)fetch_byte_imm(m); destval = (*opc83_word_operation[rh])(m, destval, imm); - if (rh != 7) store_data_word(m,destoffset,destval); + if (rh != 7) + store_data_word(m,destoffset,destval); break; case 1: destoffset=decode_rm01_address(m,rl); destval = fetch_data_word(m,destoffset); imm = (int8)fetch_byte_imm(m); destval = (*opc83_word_operation[rh])(m, destval, imm); - if (rh != 7) store_data_word(m,destoffset,destval); + if (rh != 7) + store_data_word(m,destoffset,destval); break; case 2: destoffset=decode_rm10_address(m,rl); destval = fetch_data_word(m,destoffset); imm = (int8) fetch_byte_imm(m); destval = (*opc83_word_operation[rh])(m, destval, imm); - if (rh != 7) store_data_word(m,destoffset,destval); + if (rh != 7) + store_data_word(m,destoffset,destval); break; case 3: /* register to register */ destreg = DECODE_RM_WORD_REGISTER(m,rl); imm = (int8) fetch_byte_imm(m); destval = (*opc83_word_operation[rh])(m, *destreg, imm); - if (rh != 7) *destreg = destval; + if (rh != 7) + *destreg = destval; break; } DECODE_CLEAR_SEGOVR(m); @@ -3160,7 +3176,8 @@ static void i86op_cmps_byte(PC_ENV *m) m->R_CX -= 1; m->R_SI += inc; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) break; + if (ACCESS_FLAG(m,F_ZF)==0) + break; } m->sysmode &= ~SYSMODE_PREFIX_REPE; } @@ -3176,7 +3193,8 @@ static void i86op_cmps_byte(PC_ENV *m) m->R_CX -= 1; m->R_SI += inc; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */ + if (ACCESS_FLAG(m,F_ZF)) + break; /* zero flag set means equal */ } m->sysmode &= ~SYSMODE_PREFIX_REPNE; } @@ -3212,7 +3230,8 @@ static void i86op_cmps_word(PC_ENV *m) m->R_CX -= 1; m->R_SI += inc; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) break; + if (ACCESS_FLAG(m,F_ZF)==0) + break; } m->sysmode &= ~SYSMODE_PREFIX_REPE; } @@ -3228,7 +3247,8 @@ static void i86op_cmps_word(PC_ENV *m) m->R_CX -= 1; m->R_SI += inc; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */ + if (ACCESS_FLAG(m,F_ZF)) + break; /* zero flag set means equal */ } m->sysmode &= ~SYSMODE_PREFIX_REPNE; } @@ -3392,7 +3412,8 @@ static void i86op_scas_byte(PC_ENV *m) cmp_byte(m, m->R_AL,val2); m->R_CX -= 1; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) break; + if (ACCESS_FLAG(m,F_ZF)==0) + break; } m->sysmode &= ~SYSMODE_PREFIX_REPE; } @@ -3406,7 +3427,8 @@ static void i86op_scas_byte(PC_ENV *m) cmp_byte(m, m->R_AL,val2); m->R_CX -= 1; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */ + if (ACCESS_FLAG(m,F_ZF)) + break; /* zero flag set means equal */ } m->sysmode &= ~SYSMODE_PREFIX_REPNE; } @@ -3438,7 +3460,8 @@ static void i86op_scas_word(PC_ENV *m) cmp_word(m,m->R_AX,val2); m->R_CX -= 1; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) break; + if (ACCESS_FLAG(m,F_ZF)==0) + break; } m->sysmode &= ~SYSMODE_PREFIX_REPE; } @@ -3452,7 +3475,8 @@ static void i86op_scas_word(PC_ENV *m) cmp_word(m, m->R_AX,val2); m->R_CX -= 1; m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */ + if (ACCESS_FLAG(m,F_ZF)) + break; /* zero flag set means equal */ } m->sysmode &= ~SYSMODE_PREFIX_REPNE; } @@ -4117,7 +4141,8 @@ static void sys_fatal(int error, char *fmt, ...) static void i86op_aam(PC_ENV *m) { uint8 a; a = fetch_byte_imm(m); /* this is a stupid encoding. */ - if (a != 10) sys_fatal(0,"error decoding aam" NLP); + if (a != 10) + sys_fatal(0,"error decoding aam" NLP); /* note the type change here --- returning AL and AH in AX. */ m->R_AX = aam_word(m,m->R_AL); DECODE_CLEAR_SEGOVR(m); diff --git a/AltairZ80/i86_prim_ops.c b/AltairZ80/i86_prim_ops.c index a1fb769d..109f31f4 100644 --- a/AltairZ80/i86_prim_ops.c +++ b/AltairZ80/i86_prim_ops.c @@ -65,7 +65,7 @@ extern void PutBYTEExtended(register uint32 Addr, const register uint32 Value); */ /* [JCE] Stop gcc -Wall complaining */ -void i86_intr_raise(PC_ENV *m, uint8 intrnum); +extern void i86_intr_raise(PC_ENV *m, uint8 intrnum); /* the following table was generated using the following code (running on an IBM AT, Turbo C++ 2.0), for all values of i @@ -83,7 +83,7 @@ void i86_intr_raise(PC_ENV *m, uint8 intrnum); } */ -char parity_tab[] = { +uint8 parity_tab[] = { /*0*/ 1, /*1*/ 0, /*2*/ 0, /*3*/ 1, /*4*/ 0, /*5*/ 1, /*6*/ 1, /*7*/ 0, /*8*/ 0, /*9*/ 1, /*a*/ 1, /*b*/ 0, @@ -150,7 +150,7 @@ char parity_tab[] = { /*fc*/ 1, /*fd*/ 0, /*fe*/ 0, /*ff*/ 1, }; -char xor_0x3_tab[] = { 0, 1, 1, 0 }; +uint8 xor_0x3_tab[] = { 0, 1, 1, 0 }; /* CARRY CHAIN CALCULATION. This represents a somewhat expensive calculation which is @@ -605,37 +605,35 @@ uint8 rcl_byte(PC_ENV *m, uint8 d, uint8 s) /* [JCE] Extra brackets to stop gcc -Wall moaning */ if ((cnt = s % 9)) /* not a typo, do nada if cnt==0 */ { - /* extract the new CARRY FLAG. */ - /* CF <- b_(8-n) */ - cf = (d >> (8-cnt)) & 0x1; - /* get the low stuff which rotated - into the range B_7 .. B_cnt */ - /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ - /* note that the right hand side done by the mask */ - res = (d << cnt) & 0xff; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ - /* shift it downward, 7-(n-2) = 9-n positions. - and mask off the result before or'ing in. - */ - mask = (1<<(cnt-1)) - 1; - res |= (d >> (9-cnt)) & mask; - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ - { - /* B_(n-1) <- cf */ - res |= 1 << (cnt-1); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - /* parenthesized this expression since it appears to - be causing OF to be misset */ - CONDITIONAL_SET_FLAG(cnt==1&& - xor_0x3_tab[cf+((res>>6)&0x2)], - m, F_OF); + /* extract the new CARRY FLAG. */ + /* CF <- b_(8-n) */ + cf = (d >> (8-cnt)) & 0x1; + /* get the low stuff which rotated + into the range B_7 .. B_cnt */ + /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ + /* note that the right hand side done by the mask */ + res = (d << cnt) & 0xff; + /* now the high stuff which rotated around + into the positions B_cnt-2 .. B_0 */ + /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ + /* shift it downward, 7-(n-2) = 9-n positions. + and mask off the result before or'ing in. + */ + mask = (1<<(cnt-1)) - 1; + res |= (d >> (9-cnt)) & mask; + /* if the carry flag was set, or it in. */ + if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ + { + /* B_(n-1) <- cf */ + res |= 1 << (cnt-1); + } + /* set the new carry flag, based on the variable "cf" */ + CONDITIONAL_SET_FLAG(cf, m, F_CF); + /* OVERFLOW is set *IFF* cnt==1, then it is the + xor of CF and the most significant bit. Blecck. */ + /* parenthesized this expression since it appears to + be causing OF to be missed. */ + CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[cf+((res>>6)&0x2)], m, F_OF); } return res & 0xff; } @@ -649,39 +647,38 @@ uint16 rcl_word(PC_ENV *m, uint16 d, uint16 s) /* [JCE] Extra brackets to stop gcc -Wall moaning */ if ((cnt = s % 17)) /* not a typo, do nada if cnt==0 */ { - /* extract the new CARRY FLAG. */ - /* CF <- b_(16-n) */ - cf = (d >> (16-cnt)) & 0x1; - /* get the low stuff which rotated - into the range B_15 .. B_cnt */ - /* B_(15) .. B_(n) <- b_(16-(n+1)) .. b_0 */ - /* note that the right hand side done by the mask */ - res = (d << cnt) & 0xffff; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(n-2) .. B_0 <- b_15 .. b_(16-(n-1)) */ - /* shift it downward, 15-(n-2) = 17-n positions. - and mask off the result before or'ing in. - */ - mask = (1<<(cnt-1)) - 1; - res |= (d >> (17-cnt)) & mask; - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m, F_CF)) /* carry flag is set */ - { - /* B_(n-1) <- cf */ - res |= 1 << (cnt-1); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. - Note that we're forming a 2 bit word here to index - into the table. The expression cf+(res>>14)&0x2 - represents the two bit word b_15 CF. + /* extract the new CARRY FLAG. */ + /* CF <- b_(16-n) */ + cf = (d >> (16-cnt)) & 0x1; + /* get the low stuff which rotated + into the range B_15 .. B_cnt */ + /* B_(15) .. B_(n) <- b_(16-(n+1)) .. b_0 */ + /* note that the right hand side done by the mask */ + res = (d << cnt) & 0xffff; + /* now the high stuff which rotated around + into the positions B_cnt-2 .. B_0 */ + /* B_(n-2) .. B_0 <- b_15 .. b_(16-(n-1)) */ + /* shift it downward, 15-(n-2) = 17-n positions. + and mask off the result before or'ing in. + */ + mask = (1<<(cnt-1)) - 1; + res |= (d >> (17-cnt)) & mask; + /* if the carry flag was set, or it in. */ + if (ACCESS_FLAG(m, F_CF)) /* carry flag is set */ + { + /* B_(n-1) <- cf */ + res |= 1 << (cnt-1); + } + /* set the new carry flag, based on the variable "cf" */ + CONDITIONAL_SET_FLAG(cf, m, F_CF); + /* OVERFLOW is set *IFF* cnt==1, then it is the + xor of CF and the most significant bit. Blecck. + Note that we're forming a 2 bit word here to index + into the table. The expression cf+(res>>14)&0x2 + represents the two bit word b_15 CF. */ - /* parenthesized following expression... */ - CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[cf+((res>>14)&0x2)], - m, F_OF); + /* parenthesized following expression... */ + CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[cf+((res>>14)&0x2)], m, F_OF); } return res & 0xffff; } @@ -692,74 +689,73 @@ uint8 rcr_byte(PC_ENV *m, uint8 d, uint8 s) uint8 mask, cf, ocf = 0; /* rotate right through carry */ /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 - The new rotate is done mod 9, and given this, - for a rotation of n bits (mod 9) the new carry flag is - then located n bits from the LSB. The low part is - then shifted up cnt bits, and the high part is or'd - in. Using CAPS for new values, and lowercase for the - original values, this can be expressed as: - IF n > 0 - 1) CF <- b_(n-1) - 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) - 3) B_(8-n) <- cf - 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) - I think this is correct. + s is the rotate distance. It varies from 0 - 8. + d is the byte object rotated. + have + CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 + The new rotate is done mod 9, and given this, + for a rotation of n bits (mod 9) the new carry flag is + then located n bits from the LSB. The low part is + then shifted up cnt bits, and the high part is or'd + in. Using CAPS for new values, and lowercase for the + original values, this can be expressed as: + IF n > 0 + 1) CF <- b_(n-1) + 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) + 3) B_(8-n) <- cf + 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) + I think this is correct. */ res = d; /* [JCE] Extra brackets to stop gcc -Wall moaning */ if ((cnt = s % 9)) /* not a typo, do nada if cnt==0 */ { - /* extract the new CARRY FLAG. */ - /* CF <- b_(n-1) */ - if (cnt == 1) - { - cf = d & 0x1; - /* note hackery here. Access_flag(..) evaluates to either - 0 if flag not set - non-zero if flag is set. - doing access_flag(..) != 0 casts that into either - 0..1 in any representation of the flags register - (i.e. packed bit array or unpacked.) - */ - ocf = ACCESS_FLAG(m,F_CF) != 0; - } - else - cf = (d >> (cnt-1)) & 0x1; - /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ - /* note that the right hand side done by the mask - This is effectively done by shifting the - object to the right. The result must be masked, - in case the object came in and was treated - as a negative number. Needed???*/ - mask = (1<<(8-cnt))-1; - res = (d >> cnt) & mask; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ - /* shift it downward, 7-(n-2) = 9-n positions. - and mask off the result before or'ing in. - */ - res |= (d << (9-cnt)); - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ - { - /* B_(8-n) <- cf */ - res |= 1 << (8 - cnt); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - /* parenthesized... */ - if (cnt == 1) - { /* [JCE] Explicit braces to stop gcc -Wall moaning */ - CONDITIONAL_SET_FLAG(xor_0x3_tab[ocf+((d>>6)&0x2)], - m, F_OF); - } + /* extract the new CARRY FLAG. */ + /* CF <- b_(n-1) */ + if (cnt == 1) + { + cf = d & 0x1; + /* note hackery here. Access_flag(..) evaluates to either + 0 if flag not set + non-zero if flag is set. + doing access_flag(..) != 0 casts that into either + 0..1 in any representation of the flags register + (i.e. packed bit array or unpacked.) + */ + ocf = ACCESS_FLAG(m,F_CF) != 0; + } + else + cf = (d >> (cnt-1)) & 0x1; + /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ + /* note that the right hand side done by the mask + This is effectively done by shifting the + object to the right. The result must be masked, + in case the object came in and was treated + as a negative number. Needed???*/ + mask = (1<<(8-cnt))-1; + res = (d >> cnt) & mask; + /* now the high stuff which rotated around + into the positions B_cnt-2 .. B_0 */ + /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ + /* shift it downward, 7-(n-2) = 9-n positions. + and mask off the result before or'ing in. + */ + res |= (d << (9-cnt)); + /* if the carry flag was set, or it in. */ + if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ + { + /* B_(8-n) <- cf */ + res |= 1 << (8 - cnt); + } + /* set the new carry flag, based on the variable "cf" */ + CONDITIONAL_SET_FLAG(cf, m, F_CF); + /* OVERFLOW is set *IFF* cnt==1, then it is the + xor of CF and the most significant bit. Blecck. */ + /* parenthesized... */ + if (cnt == 1) + { /* [JCE] Explicit braces to stop gcc -Wall moaning */ + CONDITIONAL_SET_FLAG(xor_0x3_tab[ocf+((d>>6)&0x2)], m, F_OF); + } } return res; } @@ -770,67 +766,66 @@ uint16 rcr_word(PC_ENV *m, uint16 d, uint16 s) uint16 mask, cf, ocf = 0; /* rotate right through carry */ /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - CF B_15 ... B_0 - The new rotate is done mod 17, and given this, - for a rotation of n bits (mod 17) the new carry flag is - then located n bits from the LSB. The low part is - then shifted up cnt bits, and the high part is or'd - in. Using CAPS for new values, and lowercase for the - original values, this can be expressed as: - IF n > 0 - 1) CF <- b_(n-1) - 2) B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n) - 3) B_(16-n) <- cf - 4) B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) - I think this is correct. + s is the rotate distance. It varies from 0 - 8. + d is the byte object rotated. + have + CF B_15 ... B_0 + The new rotate is done mod 17, and given this, + for a rotation of n bits (mod 17) the new carry flag is + then located n bits from the LSB. The low part is + then shifted up cnt bits, and the high part is or'd + in. Using CAPS for new values, and lowercase for the + original values, this can be expressed as: + IF n > 0 + 1) CF <- b_(n-1) + 2) B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n) + 3) B_(16-n) <- cf + 4) B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) + I think this is correct. */ res = d; /* [JCE] Extra brackets to stop gcc -Wall moaning */ if ((cnt = s % 17)) /* not a typo, do nada if cnt==0 */ { - /* extract the new CARRY FLAG. */ - /* CF <- b_(n-1) */ - if (cnt==1) - { - cf = d & 0x1; - /* see note above on teh byte version */ - ocf = ACCESS_FLAG(m,F_CF) != 0; - } - else - cf = (d >> (cnt-1)) & 0x1; - /* B_(16-(n+1)) .. B_(0) <- b_(15) .. b_n */ - /* note that the right hand side done by the mask - This is effectively done by shifting the - object to the right. The result must be masked, - in case the object came in and was treated - as a negative number. Needed???*/ - mask = (1<<(16-cnt))-1; - res = (d >> cnt) & mask; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) */ - /* shift it downward, 15-(n-2) = 17-n positions. - and mask off the result before or'ing in. - */ - res |= (d << (17-cnt)); - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ - { - /* B_(16-n) <- cf */ - res |= 1 << (16 - cnt); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - if (cnt==1) - { /* [JCE] Explicit braces to stop gcc -Wall moaning */ - CONDITIONAL_SET_FLAG(xor_0x3_tab[ocf+((d>>14)&0x2)], - m, F_OF); - } + /* extract the new CARRY FLAG. */ + /* CF <- b_(n-1) */ + if (cnt==1) + { + cf = d & 0x1; + /* see note above on teh byte version */ + ocf = ACCESS_FLAG(m,F_CF) != 0; + } + else + cf = (d >> (cnt-1)) & 0x1; + /* B_(16-(n+1)) .. B_(0) <- b_(15) .. b_n */ + /* note that the right hand side done by the mask + This is effectively done by shifting the + object to the right. The result must be masked, + in case the object came in and was treated + as a negative number. Needed???*/ + mask = (1<<(16-cnt))-1; + res = (d >> cnt) & mask; + /* now the high stuff which rotated around + into the positions B_cnt-2 .. B_0 */ + /* B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) */ + /* shift it downward, 15-(n-2) = 17-n positions. + and mask off the result before or'ing in. + */ + res |= (d << (17-cnt)); + /* if the carry flag was set, or it in. */ + if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ + { + /* B_(16-n) <- cf */ + res |= 1 << (16 - cnt); + } + /* set the new carry flag, based on the variable "cf" */ + CONDITIONAL_SET_FLAG(cf, m, F_CF); + /* OVERFLOW is set *IFF* cnt==1, then it is the + xor of CF and the most significant bit. Blecck. */ + if (cnt==1) + { /* [JCE] Explicit braces to stop gcc -Wall moaning */ + CONDITIONAL_SET_FLAG(xor_0x3_tab[ocf+((d>>14)&0x2)], m, F_OF); + } } return res; } @@ -865,9 +860,7 @@ uint8 rol_byte(PC_ENV *m, uint8 d, uint8 s) CONDITIONAL_SET_FLAG(res&0x1, m, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1 && - xor_0x3_tab[(res&0x1)+((res>>6)&0x2)], - m, F_OF); + CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[(res&0x1)+((res>>6)&0x2)], m, F_OF); } return res&0xff; } @@ -902,9 +895,7 @@ uint16 rol_word(PC_ENV *m, uint16 d, uint16 s) CONDITIONAL_SET_FLAG(res&0x1, m, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1 && - xor_0x3_tab[(res&0x1)+((res>>14)&0x2)], - m, F_OF); + CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[(res&0x1)+((res>>14)&0x2)], m, F_OF); } return res&0xffff; } @@ -937,9 +928,7 @@ uint8 ror_byte(PC_ENV *m, uint8 d, uint8 s) CONDITIONAL_SET_FLAG(res&0x80, m, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of the two most significant bits. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1 && - xor_0x3_tab[(res>>6)&0x3], - m, F_OF); + CONDITIONAL_SET_FLAG(cnt==1&& xor_0x3_tab[(res>>6)&0x3], m, F_OF); } return res&0xff; } @@ -973,9 +962,7 @@ uint16 ror_word(PC_ENV *m, uint16 d, uint16 s) CONDITIONAL_SET_FLAG(res&0x8000, m, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1 && - xor_0x3_tab[(res>>14)&0x3], - m, F_OF); + CONDITIONAL_SET_FLAG(cnt==1 && xor_0x3_tab[(res>>14)&0x3], m, F_OF); } return res & 0xffff; } @@ -985,45 +972,46 @@ uint8 shl_byte(PC_ENV *m, uint8 d, uint8 s) uint32 cnt,res,cf; if (s < 8) { - cnt = s % 8; - /* last bit shifted out goes into carry flag */ - if (cnt>0) - { - res = d << cnt; - cf = d & (1<<(8-cnt)); - CONDITIONAL_SET_FLAG(cf, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = (uint8)d; - } - if (cnt == 1) - { - /* Needs simplification. */ - CONDITIONAL_SET_FLAG( - (((res&0x80)==0x80) ^ + cnt = s % 8; + /* last bit shifted out goes into carry flag */ + if (cnt>0) + { + res = d << cnt; + cf = d & (1<<(8-cnt)); + CONDITIONAL_SET_FLAG(cf, m, F_CF); + CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); + CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); + } + else + { + res = (uint8)d; + } + if (cnt == 1) + { + /* Needs simplification. */ + CONDITIONAL_SET_FLAG( + (((res&0x80)==0x80) ^ (ACCESS_FLAG(m,F_CF) != 0)) , - /* was (m->R_FLG&F_CF)==F_CF)), */ - m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } + /* was (m->R_FLG&F_CF)==F_CF)), */ + m, F_OF); + } + else + { + CLEAR_FLAG(m,F_OF); + } } else { - res = 0; - CLEAR_FLAG(m,F_CF); - CLEAR_FLAG(m,F_OF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); - SET_FLAG(m,F_ZF); + res = 0; +/* CLEAR_FLAG(m,F_CF);*/ + CONDITIONAL_SET_FLAG((s == 8) && (d & 1), m, F_CF); /* Peter Schorn bug fix */ + CLEAR_FLAG(m,F_OF); + CLEAR_FLAG(m,F_SF); + CLEAR_FLAG(m,F_PF); + SET_FLAG(m,F_ZF); } - return res&0xff; + return res & 0xff; } uint16 shl_word(PC_ENV *m, uint16 d, uint16 s) @@ -1031,45 +1019,46 @@ uint16 shl_word(PC_ENV *m, uint16 d, uint16 s) uint32 cnt,res,cf; if (s < 16) { - cnt = s % 16; - if (cnt > 0) - { - res = d << cnt; - /* last bit shifted out goes into carry flag */ - cf = d & (1<<(16-cnt)); - CONDITIONAL_SET_FLAG(cf, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = (uint16)d; - } - if (cnt == 1) - { - /* Needs simplification. */ - CONDITIONAL_SET_FLAG( - (((res&0x8000)==0x8000) ^ - (ACCESS_FLAG(m,F_CF) != 0)), - /*((m&F_CF)==F_CF)),*/ - m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } + cnt = s % 16; + if (cnt > 0) + { + res = d << cnt; + /* last bit shifted out goes into carry flag */ + cf = d & (1<<(16-cnt)); + CONDITIONAL_SET_FLAG(cf, m, F_CF); + CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); + CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); + } + else + { + res = (uint16)d; + } + if (cnt == 1) + { + /* Needs simplification. */ + CONDITIONAL_SET_FLAG( + (((res&0x8000)==0x8000) ^ + (ACCESS_FLAG(m,F_CF) != 0)), + /*((m&F_CF)==F_CF)),*/ + m, F_OF); + } + else + { + CLEAR_FLAG(m,F_OF); + } } else { - res = 0; - CLEAR_FLAG(m,F_CF); - CLEAR_FLAG(m,F_OF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); + res = 0; + /* CLEAR_FLAG(m,F_CF);*/ + CONDITIONAL_SET_FLAG((s == 16) && (d & 1), m, F_CF); /* Peter Schorn bug fix */ + CLEAR_FLAG(m,F_OF); + SET_FLAG(m,F_ZF); + CLEAR_FLAG(m,F_SF); + CLEAR_FLAG(m,F_PF); } - return res&0xffff; + return res & 0xffff; } uint8 shr_byte(PC_ENV *m, uint8 d, uint8 s) @@ -1077,41 +1066,41 @@ uint8 shr_byte(PC_ENV *m, uint8 d, uint8 s) uint32 cnt,res,cf,mask; if (s < 8) { - cnt = s % 8; - if (cnt > 0) - { - mask = (1<<(8-cnt))-1; - cf = d & (1<<(cnt-1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = (uint8) d; - } - if (cnt == 1) - { - CONDITIONAL_SET_FLAG( - xor_0x3_tab[(res>>6)&0x3], m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } + cnt = s % 8; + if (cnt > 0) + { + mask = (1<<(8-cnt))-1; + cf = d & (1<<(cnt-1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, m, F_CF); + CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); + CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); + } + else + { + res = (uint8) d; + } + if (cnt == 1) + { + CONDITIONAL_SET_FLAG(xor_0x3_tab[(res>>6)&0x3], m, F_OF); + } + else + { + CLEAR_FLAG(m,F_OF); + } } else { - res = 0; - CLEAR_FLAG(m,F_CF); - CLEAR_FLAG(m,F_OF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); + res = 0; + /* CLEAR_FLAG(m,F_CF);*/ + CONDITIONAL_SET_FLAG((s == 8) && (d & 0x80), m, F_CF); /* Peter Schorn bug fix */ + CLEAR_FLAG(m,F_OF); + SET_FLAG(m,F_ZF); + CLEAR_FLAG(m,F_SF); + CLEAR_FLAG(m,F_PF); } - return res&0xff; + return res & 0xff; } uint16 shr_word(PC_ENV *m, uint16 d, uint16 s) @@ -1120,41 +1109,41 @@ uint16 shr_word(PC_ENV *m, uint16 d, uint16 s) res = d; if (s < 16) { - cnt = s % 16; - if (cnt > 0) - { - mask = (1<<(16-cnt))-1; - cf = d & (1<<(cnt-1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = d; - } - if (cnt == 1) - { - CONDITIONAL_SET_FLAG( - xor_0x3_tab[(res>>14)&0x3], m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } + cnt = s % 16; + if (cnt > 0) + { + mask = (1<<(16-cnt))-1; + cf = d & (1<<(cnt-1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, m, F_CF); + CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); + CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); + } + else + { + res = d; + } + if (cnt == 1) + { + CONDITIONAL_SET_FLAG(xor_0x3_tab[(res>>14)&0x3], m, F_OF); + } + else + { + CLEAR_FLAG(m,F_OF); + } } else { - res = 0; - CLEAR_FLAG(m,F_CF); - CLEAR_FLAG(m,F_OF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); + res = 0; + /* CLEAR_FLAG(m,F_CF);*/ + CONDITIONAL_SET_FLAG((s == 16) && (d & 0x8000), m, F_CF); /* Peter Schorn bug fix */ + CLEAR_FLAG(m,F_OF); + SET_FLAG(m,F_ZF); + CLEAR_FLAG(m,F_SF); + CLEAR_FLAG(m,F_PF); } - return res&0xffff; + return res & 0xffff; } /* XXXX ??? flags may be wrong??? */ @@ -1164,38 +1153,38 @@ uint8 sar_byte(PC_ENV *m, uint8 d, uint8 s) res = d; sf = d & 0x80; cnt = s % 8; - if(cnt > 0 && cnt < 8) + if (cnt > 0 && cnt < 8) { - mask = (1<<(8-cnt))-1; - cf = d & (1<<(cnt-1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, m, F_CF); - if (sf) - { - res |= ~mask; - } - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); + mask = (1<<(8-cnt))-1; + cf = d & (1<<(cnt-1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, m, F_CF); + if (sf) + { + res |= ~mask; + } + CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); + CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); + CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); } else if (cnt >= 8) { - if (sf) - { - res = 0xff; - SET_FLAG(m,F_CF); - CLEAR_FLAG(m,F_ZF); - SET_FLAG(m, F_SF); - SET_FLAG(m, F_PF); - } - else - { - res = 0; - CLEAR_FLAG(m,F_CF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m, F_SF); - CLEAR_FLAG(m, F_PF); - } + if (sf) + { + res = 0xff; + SET_FLAG(m,F_CF); + CLEAR_FLAG(m,F_ZF); + SET_FLAG(m, F_SF); + SET_FLAG(m, F_PF); + } + else + { + res = 0; + CLEAR_FLAG(m,F_CF); + SET_FLAG(m,F_ZF); + CLEAR_FLAG(m, F_SF); + CLEAR_FLAG(m, F_PF); + } } return res&0xff; } @@ -1208,38 +1197,38 @@ uint16 sar_word(PC_ENV *m, uint16 d, uint16 s) res = d; if (cnt > 0 && cnt < 16) { - mask = (1<<(16-cnt))-1; - cf = d & (1<<(cnt-1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, m, F_CF); - if (sf) - { - res |= ~mask; - } + mask = (1<<(16-cnt))-1; + cf = d & (1<<(cnt-1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, m, F_CF); + if (sf) + { + res |= ~mask; + } CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); } else if (cnt >= 16) { - if (sf) - { - res = 0xffff; - SET_FLAG(m,F_CF); - CLEAR_FLAG(m,F_ZF); - SET_FLAG(m, F_SF); - SET_FLAG(m, F_PF); - } - else - { - res = 0; - CLEAR_FLAG(m,F_CF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m, F_SF); - CLEAR_FLAG(m, F_PF); - } + if (sf) + { + res = 0xffff; + SET_FLAG(m,F_CF); + CLEAR_FLAG(m,F_ZF); + SET_FLAG(m, F_SF); + SET_FLAG(m, F_PF); + } + else + { + res = 0; + CLEAR_FLAG(m,F_CF); + SET_FLAG(m,F_ZF); + CLEAR_FLAG(m, F_SF); + CLEAR_FLAG(m, F_PF); + } } - return res&0xffff; + return res & 0xffff; } uint8 sbb_byte(PC_ENV *m, uint8 d, uint8 s) diff --git a/AltairZ80/insns.h b/AltairZ80/insns.h index f63c0d48..43548f3f 100644 --- a/AltairZ80/insns.h +++ b/AltairZ80/insns.h @@ -581,21 +581,12 @@ enum { I_SETcc }; -#define MAX_INSLEN 11 - -/* max length of any instruction, register name etc. */ -#if MAX_INSLEN > 9 /* MAX_INSLEN defined in insnsi.h */ -#define MAX_KEYWORD MAX_INSLEN -#else -#define MAX_KEYWORD 9 -#endif - struct itemplate { - int opcode; /* the token, passed from "parser.c" */ - int operands; /* number of operands */ - long opd[3]; /* bit flags for operand types */ - const char *code; /* the code it assembles to */ - unsigned long flags; /* some flags */ + int opcode; /* the token, passed from "parser.c" */ + int operands; /* number of operands */ + long opd[3]; /* bit flags for operand types */ + const char *code; /* the code it assembles to */ + unsigned long flags; /* some flags */ }; /* diff --git a/AltairZ80/insnsd.c b/AltairZ80/insnsd.c index 0f10cdb5..1037a369 100644 --- a/AltairZ80/insnsd.c +++ b/AltairZ80/insnsd.c @@ -4,1557 +4,1575 @@ #include "insns.h" static struct itemplate instrux[] = { - {I_AAA, 0, {0,0,0}, "\1\x37", IF_8086}, - {I_AAD, 0, {0,0,0}, "\2\xD5\x0A", IF_8086}, - {I_AAD, 1, {IMMEDIATE,0,0}, "\1\xD5\24", IF_8086|IF_SB}, - {I_AAM, 0, {0,0,0}, "\2\xD4\x0A", IF_8086}, - {I_AAM, 1, {IMMEDIATE,0,0}, "\1\xD4\24", IF_8086|IF_SB}, - {I_AAS, 0, {0,0,0}, "\1\x3F", IF_8086}, - {I_ADC, 2, {MEMORY,REG8,0}, "\300\1\x10\101", IF_8086|IF_SM}, - {I_ADC, 2, {REG8,REG8,0}, "\1\x10\101", IF_8086}, - {I_ADC, 2, {MEMORY,REG16,0}, "\320\300\1\x11\101", IF_8086|IF_SM}, - {I_ADC, 2, {REG16,REG16,0}, "\320\1\x11\101", IF_8086}, - {I_ADC, 2, {MEMORY,REG32,0}, "\321\300\1\x11\101", IF_386|IF_SM}, - {I_ADC, 2, {REG32,REG32,0}, "\321\1\x11\101", IF_386}, - {I_ADC, 2, {REG8,MEMORY,0}, "\301\1\x12\110", IF_8086|IF_SM}, - {I_ADC, 2, {REG8,REG8,0}, "\1\x12\110", IF_8086}, - {I_ADC, 2, {REG16,MEMORY,0}, "\320\301\1\x13\110", IF_8086|IF_SM}, - {I_ADC, 2, {REG16,REG16,0}, "\320\1\x13\110", IF_8086}, - {I_ADC, 2, {REG32,MEMORY,0}, "\321\301\1\x13\110", IF_386|IF_SM}, - {I_ADC, 2, {REG32,REG32,0}, "\321\1\x13\110", IF_386}, - {I_ADC, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\202\15", IF_8086}, - {I_ADC, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\202\15", IF_386}, - {I_ADC, 2, {REG_AL,IMMEDIATE,0}, "\1\x14\21", IF_8086|IF_SM}, - {I_ADC, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x15\31", IF_8086|IF_SM}, - {I_ADC, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x15\41", IF_386|IF_SM}, - {I_ADC, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\202\21", IF_8086|IF_SM}, - {I_ADC, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\202\131", IF_8086|IF_SM}, - {I_ADC, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\202\141", IF_386|IF_SM}, - {I_ADC, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\202\21", IF_8086|IF_SM}, - {I_ADC, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\202\131", IF_8086|IF_SM}, - {I_ADC, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\202\141", IF_386|IF_SM}, - {I_ADD, 2, {MEMORY,REG8,0}, "\300\17\101", IF_8086|IF_SM}, - {I_ADD, 2, {REG8,REG8,0}, "\17\101", IF_8086}, - {I_ADD, 2, {MEMORY,REG16,0}, "\320\300\1\x01\101", IF_8086|IF_SM}, - {I_ADD, 2, {REG16,REG16,0}, "\320\1\x01\101", IF_8086}, - {I_ADD, 2, {MEMORY,REG32,0}, "\321\300\1\x01\101", IF_386|IF_SM}, - {I_ADD, 2, {REG32,REG32,0}, "\321\1\x01\101", IF_386}, - {I_ADD, 2, {REG8,MEMORY,0}, "\301\1\x02\110", IF_8086|IF_SM}, - {I_ADD, 2, {REG8,REG8,0}, "\1\x02\110", IF_8086}, - {I_ADD, 2, {REG16,MEMORY,0}, "\320\301\1\x03\110", IF_8086|IF_SM}, - {I_ADD, 2, {REG16,REG16,0}, "\320\1\x03\110", IF_8086}, - {I_ADD, 2, {REG32,MEMORY,0}, "\321\301\1\x03\110", IF_386|IF_SM}, - {I_ADD, 2, {REG32,REG32,0}, "\321\1\x03\110", IF_386}, - {I_ADD, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\200\15", IF_8086}, - {I_ADD, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\200\15", IF_386}, - {I_ADD, 2, {REG_AL,IMMEDIATE,0}, "\1\x04\21", IF_8086|IF_SM}, - {I_ADD, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x05\31", IF_8086|IF_SM}, - {I_ADD, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x05\41", IF_386|IF_SM}, - {I_ADD, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\200\21", IF_8086|IF_SM}, - {I_ADD, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\200\131", IF_8086|IF_SM}, - {I_ADD, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\200\141", IF_386|IF_SM}, - {I_ADD, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\200\21", IF_8086|IF_SM}, - {I_ADD, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\200\131", IF_8086|IF_SM}, - {I_ADD, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\200\141", IF_386|IF_SM}, - {I_AND, 2, {MEMORY,REG8,0}, "\300\1\x20\101", IF_8086|IF_SM}, - {I_AND, 2, {REG8,REG8,0}, "\1\x20\101", IF_8086}, - {I_AND, 2, {MEMORY,REG16,0}, "\320\300\1\x21\101", IF_8086|IF_SM}, - {I_AND, 2, {REG16,REG16,0}, "\320\1\x21\101", IF_8086}, - {I_AND, 2, {MEMORY,REG32,0}, "\321\300\1\x21\101", IF_386|IF_SM}, - {I_AND, 2, {REG32,REG32,0}, "\321\1\x21\101", IF_386}, - {I_AND, 2, {REG8,MEMORY,0}, "\301\1\x22\110", IF_8086|IF_SM}, - {I_AND, 2, {REG8,REG8,0}, "\1\x22\110", IF_8086}, - {I_AND, 2, {REG16,MEMORY,0}, "\320\301\1\x23\110", IF_8086|IF_SM}, - {I_AND, 2, {REG16,REG16,0}, "\320\1\x23\110", IF_8086}, - {I_AND, 2, {REG32,MEMORY,0}, "\321\301\1\x23\110", IF_386|IF_SM}, - {I_AND, 2, {REG32,REG32,0}, "\321\1\x23\110", IF_386}, - {I_AND, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\204\15", IF_8086}, - {I_AND, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\204\15", IF_386}, - {I_AND, 2, {REG_AL,IMMEDIATE,0}, "\1\x24\21", IF_8086|IF_SM}, - {I_AND, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x25\31", IF_8086|IF_SM}, - {I_AND, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x25\41", IF_386|IF_SM}, - {I_AND, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\204\21", IF_8086|IF_SM}, - {I_AND, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\204\131", IF_8086|IF_SM}, - {I_AND, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\204\141", IF_386|IF_SM}, - {I_AND, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\204\21", IF_8086|IF_SM}, - {I_AND, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\204\131", IF_8086|IF_SM}, - {I_AND, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\204\141", IF_386|IF_SM}, - {I_ARPL, 2, {MEMORY,REG16,0}, "\300\1\x63\101", IF_286|IF_PROT|IF_SM}, - {I_ARPL, 2, {REG16,REG16,0}, "\1\x63\101", IF_286|IF_PROT}, - {I_BOUND, 2, {REG16,MEMORY,0}, "\320\301\1\x62\110", IF_186}, - {I_BOUND, 2, {REG32,MEMORY,0}, "\321\301\1\x62\110", IF_386}, - {I_BSF, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBC\110", IF_386|IF_SM}, - {I_BSF, 2, {REG16,REG16,0}, "\320\2\x0F\xBC\110", IF_386}, - {I_BSF, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xBC\110", IF_386|IF_SM}, - {I_BSF, 2, {REG32,REG32,0}, "\321\2\x0F\xBC\110", IF_386}, - {I_BSR, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBD\110", IF_386|IF_SM}, - {I_BSR, 2, {REG16,REG16,0}, "\320\2\x0F\xBD\110", IF_386}, - {I_BSR, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xBD\110", IF_386|IF_SM}, - {I_BSR, 2, {REG32,REG32,0}, "\321\2\x0F\xBD\110", IF_386}, - {I_BSWAP, 1, {REG32,0,0}, "\321\1\x0F\10\xC8", IF_486}, - {I_BT, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xA3\101", IF_386|IF_SM}, - {I_BT, 2, {REG16,REG16,0}, "\320\2\x0F\xA3\101", IF_386}, - {I_BT, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xA3\101", IF_386|IF_SM}, - {I_BT, 2, {REG32,REG32,0}, "\321\2\x0F\xA3\101", IF_386}, - {I_BT, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\204\25", IF_386|IF_SB}, - {I_BT, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\204\25", IF_386|IF_SB}, - {I_BTC, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xBB\101", IF_386|IF_SM}, - {I_BTC, 2, {REG16,REG16,0}, "\320\2\x0F\xBB\101", IF_386}, - {I_BTC, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xBB\101", IF_386|IF_SM}, - {I_BTC, 2, {REG32,REG32,0}, "\321\2\x0F\xBB\101", IF_386}, - {I_BTC, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\207\25", IF_386|IF_SB}, - {I_BTC, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\207\25", IF_386|IF_SB}, - {I_BTR, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xB3\101", IF_386|IF_SM}, - {I_BTR, 2, {REG16,REG16,0}, "\320\2\x0F\xB3\101", IF_386}, - {I_BTR, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xB3\101", IF_386|IF_SM}, - {I_BTR, 2, {REG32,REG32,0}, "\321\2\x0F\xB3\101", IF_386}, - {I_BTR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\206\25", IF_386|IF_SB}, - {I_BTR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\206\25", IF_386|IF_SB}, - {I_BTS, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xAB\101", IF_386|IF_SM}, - {I_BTS, 2, {REG16,REG16,0}, "\320\2\x0F\xAB\101", IF_386}, - {I_BTS, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xAB\101", IF_386|IF_SM}, - {I_BTS, 2, {REG32,REG32,0}, "\321\2\x0F\xAB\101", IF_386}, - {I_BTS, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\205\25", IF_386|IF_SB}, - {I_BTS, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\205\25", IF_386|IF_SB}, - {I_CALL, 1, {IMMEDIATE,0,0}, "\322\1\xE8\64", IF_8086}, - {I_CALL, 1, {IMMEDIATE|NEAR,0,0}, "\322\1\xE8\64", IF_8086}, - {I_CALL, 1, {IMMEDIATE|BITS16,0,0}, "\320\1\xE8\64", IF_8086}, - {I_CALL, 1, {IMMEDIATE|BITS16|NEAR,0,0}, "\320\1\xE8\64", IF_8086}, - {I_CALL, 1, {IMMEDIATE|BITS32,0,0}, "\321\1\xE8\64", IF_386}, - {I_CALL, 1, {IMMEDIATE|BITS32|NEAR,0,0}, "\321\1\xE8\64", IF_386}, - {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\322\1\x9A\35\30", IF_8086}, - {I_CALL, 2, {IMMEDIATE|BITS16|COLON,IMMEDIATE,0}, "\320\1\x9A\31\30", IF_8086}, - {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS16,0}, "\320\1\x9A\31\30", IF_8086}, - {I_CALL, 2, {IMMEDIATE|BITS32|COLON,IMMEDIATE,0}, "\321\1\x9A\41\30", IF_386}, - {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS32,0}, "\321\1\x9A\41\30", IF_386}, - {I_CALL, 1, {MEMORY|FAR,0,0}, "\322\300\1\xFF\203", IF_8086}, - {I_CALL, 1, {MEMORY|BITS16|FAR,0,0}, "\320\300\1\xFF\203", IF_8086}, - {I_CALL, 1, {MEMORY|BITS32|FAR,0,0}, "\321\300\1\xFF\203", IF_386}, - {I_CALL, 1, {MEMORY|NEAR,0,0}, "\322\300\1\xFF\202", IF_8086}, - {I_CALL, 1, {MEMORY|BITS16|NEAR,0,0}, "\320\300\1\xFF\202", IF_8086}, - {I_CALL, 1, {MEMORY|BITS32|NEAR,0,0}, "\321\300\1\xFF\202", IF_386}, - {I_CALL, 1, {REG16,0,0}, "\320\300\1\xFF\202", IF_8086}, - {I_CALL, 1, {REG32,0,0}, "\321\300\1\xFF\202", IF_386}, - {I_CALL, 1, {MEMORY,0,0}, "\322\300\1\xFF\202", IF_8086}, - {I_CALL, 1, {MEMORY|BITS16,0,0}, "\320\300\1\xFF\202", IF_8086}, - {I_CALL, 1, {MEMORY|BITS32,0,0}, "\321\300\1\xFF\202", IF_386}, - {I_CBW, 0, {0,0,0}, "\320\1\x98", IF_8086}, - {I_CDQ, 0, {0,0,0}, "\321\1\x99", IF_386}, - {I_CLC, 0, {0,0,0}, "\1\xF8", IF_8086}, - {I_CLD, 0, {0,0,0}, "\1\xFC", IF_8086}, - {I_CLI, 0, {0,0,0}, "\1\xFA", IF_8086}, - {I_CLTS, 0, {0,0,0}, "\2\x0F\x06", IF_286|IF_PRIV}, - {I_CMC, 0, {0,0,0}, "\1\xF5", IF_8086}, - {I_CMP, 2, {MEMORY,REG8,0}, "\300\1\x38\101", IF_8086|IF_SM}, - {I_CMP, 2, {REG8,REG8,0}, "\1\x38\101", IF_8086}, - {I_CMP, 2, {MEMORY,REG16,0}, "\320\300\1\x39\101", IF_8086|IF_SM}, - {I_CMP, 2, {REG16,REG16,0}, "\320\1\x39\101", IF_8086}, - {I_CMP, 2, {MEMORY,REG32,0}, "\321\300\1\x39\101", IF_386|IF_SM}, - {I_CMP, 2, {REG32,REG32,0}, "\321\1\x39\101", IF_386}, - {I_CMP, 2, {REG8,MEMORY,0}, "\301\1\x3A\110", IF_8086|IF_SM}, - {I_CMP, 2, {REG8,REG8,0}, "\1\x3A\110", IF_8086}, - {I_CMP, 2, {REG16,MEMORY,0}, "\320\301\1\x3B\110", IF_8086|IF_SM}, - {I_CMP, 2, {REG16,REG16,0}, "\320\1\x3B\110", IF_8086}, - {I_CMP, 2, {REG32,MEMORY,0}, "\321\301\1\x3B\110", IF_386|IF_SM}, - {I_CMP, 2, {REG32,REG32,0}, "\321\1\x3B\110", IF_386}, - {I_CMP, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\207\15", IF_8086}, - {I_CMP, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\207\15", IF_386}, - {I_CMP, 2, {REG_AL,IMMEDIATE,0}, "\1\x3C\21", IF_8086|IF_SM}, - {I_CMP, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x3D\31", IF_8086|IF_SM}, - {I_CMP, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x3D\41", IF_386|IF_SM}, - {I_CMP, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\207\21", IF_8086|IF_SM}, - {I_CMP, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\207\131", IF_8086|IF_SM}, - {I_CMP, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\207\141", IF_386|IF_SM}, - {I_CMP, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\207\21", IF_8086|IF_SM}, - {I_CMP, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\207\131", IF_8086|IF_SM}, - {I_CMP, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\207\141", IF_386|IF_SM}, - {I_CMPSB, 0, {0,0,0}, "\332\1\xA6", IF_8086}, - {I_CMPSD, 0, {0,0,0}, "\332\321\1\xA7", IF_386}, - {I_CMPSW, 0, {0,0,0}, "\332\320\1\xA7", IF_8086}, - {I_CMPXCHG, 2, {MEMORY,REG8,0}, "\300\2\x0F\xB0\101", IF_PENT|IF_SM}, - {I_CMPXCHG, 2, {REG8,REG8,0}, "\2\x0F\xB0\101", IF_PENT}, - {I_CMPXCHG, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xB1\101", IF_PENT|IF_SM}, - {I_CMPXCHG, 2, {REG16,REG16,0}, "\320\2\x0F\xB1\101", IF_PENT}, - {I_CMPXCHG, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xB1\101", IF_PENT|IF_SM}, - {I_CMPXCHG, 2, {REG32,REG32,0}, "\321\2\x0F\xB1\101", IF_PENT}, - {I_CMPXCHG486, 2, {MEMORY,REG8,0}, "\300\2\x0F\xA6\101", IF_486|IF_SM|IF_UNDOC}, - {I_CMPXCHG486, 2, {REG8,REG8,0}, "\2\x0F\xA6\101", IF_486|IF_UNDOC}, - {I_CMPXCHG486, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xA7\101", IF_486|IF_SM|IF_UNDOC}, - {I_CMPXCHG486, 2, {REG16,REG16,0}, "\320\2\x0F\xA7\101", IF_486|IF_UNDOC}, - {I_CMPXCHG486, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xA7\101", IF_486|IF_SM|IF_UNDOC}, - {I_CMPXCHG486, 2, {REG32,REG32,0}, "\321\2\x0F\xA7\101", IF_486|IF_UNDOC}, - {I_CMPXCHG8B, 1, {MEMORY,0,0}, "\300\2\x0F\xC7\201", IF_PENT}, - {I_CPUID, 0, {0,0,0}, "\2\x0F\xA2", IF_PENT}, - {I_CWD, 0, {0,0,0}, "\320\1\x99", IF_8086}, - {I_CWDE, 0, {0,0,0}, "\321\1\x98", IF_386}, - {I_DAA, 0, {0,0,0}, "\1\x27", IF_8086}, - {I_DAS, 0, {0,0,0}, "\1\x2F", IF_8086}, - {I_DEC, 1, {REG16,0,0}, "\320\10\x48", IF_8086}, - {I_DEC, 1, {REG32,0,0}, "\321\10\x48", IF_386}, - {I_DEC, 1, {REGMEM|BITS8,0,0}, "\300\1\xFE\201", IF_8086}, - {I_DEC, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\201", IF_8086}, - {I_DEC, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\201", IF_386}, - {I_DIV, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\206", IF_8086}, - {I_DIV, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\206", IF_8086}, - {I_DIV, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\206", IF_386}, - {I_EMMS, 0, {0,0,0}, "\2\x0F\x77", IF_PENT|IF_MMX}, - {I_ENTER, 2, {IMMEDIATE,IMMEDIATE,0}, "\1\xC8\30\25", IF_186}, - {I_EQU, 1, {IMMEDIATE,0,0}, "\0", IF_8086}, - {I_EQU, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\0", IF_8086}, - {I_F2XM1, 0, {0,0,0}, "\2\xD9\xF0", IF_8086|IF_FPU}, - {I_FABS, 0, {0,0,0}, "\2\xD9\xE1", IF_8086|IF_FPU}, - {I_FADD, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\200", IF_8086|IF_FPU}, - {I_FADD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\200", IF_8086|IF_FPU}, - {I_FADD, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xC0", IF_8086|IF_FPU}, - {I_FADD, 1, {FPUREG,0,0}, "\1\xD8\10\xC0", IF_8086|IF_FPU}, - {I_FADD, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xC0", IF_8086|IF_FPU}, - {I_FADD, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xC0", IF_8086|IF_FPU}, - {I_FADDP, 1, {FPUREG,0,0}, "\1\xDE\10\xC0", IF_8086|IF_FPU}, - {I_FADDP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xC0", IF_8086|IF_FPU}, - {I_FBLD, 1, {MEMORY|BITS80,0,0}, "\300\1\xDF\204", IF_8086|IF_FPU}, - {I_FBLD, 1, {MEMORY,0,0}, "\300\1\xDF\204", IF_8086|IF_FPU}, - {I_FBSTP, 1, {MEMORY|BITS80,0,0}, "\300\1\xDF\206", IF_8086|IF_FPU}, - {I_FBSTP, 1, {MEMORY,0,0}, "\300\1\xDF\206", IF_8086|IF_FPU}, - {I_FCHS, 0, {0,0,0}, "\2\xD9\xE0", IF_8086|IF_FPU}, - {I_FCLEX, 0, {0,0,0}, "\3\x9B\xDB\xE2", IF_8086|IF_FPU}, - {I_FCMOVB, 1, {FPUREG,0,0}, "\1\xDA\10\xC0", IF_P6|IF_FPU}, - {I_FCMOVB, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xC0", IF_P6|IF_FPU}, - {I_FCMOVBE, 1, {FPUREG,0,0}, "\1\xDA\10\xD0", IF_P6|IF_FPU}, - {I_FCMOVBE, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xD0", IF_P6|IF_FPU}, - {I_FCMOVE, 1, {FPUREG,0,0}, "\1\xDA\10\xC8", IF_P6|IF_FPU}, - {I_FCMOVE, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xC8", IF_P6|IF_FPU}, - {I_FCMOVNB, 1, {FPUREG,0,0}, "\1\xDB\10\xC0", IF_P6|IF_FPU}, - {I_FCMOVNB, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xC0", IF_P6|IF_FPU}, - {I_FCMOVNBE, 1, {FPUREG,0,0}, "\1\xDB\10\xD0", IF_P6|IF_FPU}, - {I_FCMOVNBE, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xD0", IF_P6|IF_FPU}, - {I_FCMOVNE, 1, {FPUREG,0,0}, "\1\xDB\10\xC8", IF_P6|IF_FPU}, - {I_FCMOVNE, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xC8", IF_P6|IF_FPU}, - {I_FCMOVNU, 1, {FPUREG,0,0}, "\1\xDB\10\xD8", IF_P6|IF_FPU}, - {I_FCMOVNU, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xD8", IF_P6|IF_FPU}, - {I_FCMOVU, 1, {FPUREG,0,0}, "\1\xDA\10\xD8", IF_P6|IF_FPU}, - {I_FCMOVU, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xD8", IF_P6|IF_FPU}, - {I_FCOM, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\202", IF_8086|IF_FPU}, - {I_FCOM, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\202", IF_8086|IF_FPU}, - {I_FCOM, 1, {FPUREG,0,0}, "\1\xD8\10\xD0", IF_8086|IF_FPU}, - {I_FCOM, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xD0", IF_8086|IF_FPU}, - {I_FCOMI, 1, {FPUREG,0,0}, "\1\xDB\10\xF0", IF_P6|IF_FPU}, - {I_FCOMI, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xF0", IF_P6|IF_FPU}, - {I_FCOMIP, 1, {FPUREG,0,0}, "\1\xDF\10\xF0", IF_P6|IF_FPU}, - {I_FCOMIP, 2, {FPU0,FPUREG,0}, "\1\xDF\11\xF0", IF_P6|IF_FPU}, - {I_FCOMP, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\203", IF_8086|IF_FPU}, - {I_FCOMP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\203", IF_8086|IF_FPU}, - {I_FCOMP, 1, {FPUREG,0,0}, "\1\xD8\10\xD8", IF_8086|IF_FPU}, - {I_FCOMP, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xD8", IF_8086|IF_FPU}, - {I_FCOMPP, 0, {0,0,0}, "\2\xDE\xD9", IF_8086|IF_FPU}, - {I_FCOS, 0, {0,0,0}, "\2\xD9\xFF", IF_386|IF_FPU}, - {I_FDECSTP, 0, {0,0,0}, "\2\xD9\xF6", IF_8086|IF_FPU}, - {I_FDISI, 0, {0,0,0}, "\3\x9B\xDB\xE1", IF_8086|IF_FPU}, - {I_FDIV, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\206", IF_8086|IF_FPU}, - {I_FDIV, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\206", IF_8086|IF_FPU}, - {I_FDIV, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xF8", IF_8086|IF_FPU}, - {I_FDIV, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xF8", IF_8086|IF_FPU}, - {I_FDIV, 1, {FPUREG,0,0}, "\1\xD8\10\xF0", IF_8086|IF_FPU}, - {I_FDIV, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xF0", IF_8086|IF_FPU}, - {I_FDIVP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xF8", IF_8086|IF_FPU}, - {I_FDIVP, 1, {FPUREG,0,0}, "\1\xDE\10\xF8", IF_8086|IF_FPU}, - {I_FDIVR, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\207", IF_8086|IF_FPU}, - {I_FDIVR, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\207", IF_8086|IF_FPU}, - {I_FDIVR, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xF0", IF_8086|IF_FPU}, - {I_FDIVR, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xF0", IF_8086|IF_FPU}, - {I_FDIVR, 1, {FPUREG,0,0}, "\1\xD8\10\xF8", IF_8086|IF_FPU}, - {I_FDIVR, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xF8", IF_8086|IF_FPU}, - {I_FDIVRP, 1, {FPUREG,0,0}, "\1\xDE\10\xF0", IF_8086|IF_FPU}, - {I_FDIVRP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xF0", IF_8086|IF_FPU}, - {I_FEMMS, 0, {0,0,0}, "\2\x0F\x0E", IF_PENT|IF_3DNOW}, - {I_FENI, 0, {0,0,0}, "\3\x9B\xDB\xE0", IF_8086|IF_FPU}, - {I_FFREE, 1, {FPUREG,0,0}, "\1\xDD\10\xC0", IF_8086|IF_FPU}, - {I_FFREEP, 1, {FPUREG,0,0}, "\1\xDF\10\xC0", IF_286|IF_FPU|IF_UNDOC}, - {I_FIADD, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\200", IF_8086|IF_FPU}, - {I_FIADD, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\200", IF_8086|IF_FPU}, - {I_FICOM, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\202", IF_8086|IF_FPU}, - {I_FICOM, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\202", IF_8086|IF_FPU}, - {I_FICOMP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\203", IF_8086|IF_FPU}, - {I_FICOMP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\203", IF_8086|IF_FPU}, - {I_FIDIV, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\206", IF_8086|IF_FPU}, - {I_FIDIV, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\206", IF_8086|IF_FPU}, - {I_FIDIVR, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\207", IF_8086|IF_FPU}, - {I_FIDIVR, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\207", IF_8086|IF_FPU}, - {I_FILD, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\200", IF_8086|IF_FPU}, - {I_FILD, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\200", IF_8086|IF_FPU}, - {I_FILD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\205", IF_8086|IF_FPU}, - {I_FIMUL, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\201", IF_8086|IF_FPU}, - {I_FIMUL, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\201", IF_8086|IF_FPU}, - {I_FINCSTP, 0, {0,0,0}, "\2\xD9\xF7", IF_8086|IF_FPU}, - {I_FINIT, 0, {0,0,0}, "\3\x9B\xDB\xE3", IF_8086|IF_FPU}, - {I_FIST, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\202", IF_8086|IF_FPU}, - {I_FIST, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\202", IF_8086|IF_FPU}, - {I_FISTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\203", IF_8086|IF_FPU}, - {I_FISTP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\203", IF_8086|IF_FPU}, - {I_FISTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\207", IF_8086|IF_FPU}, - {I_FISTTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDD\201", IF_PRESCOTT|IF_FPU}, - {I_FISTTP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDB\201", IF_PRESCOTT|IF_FPU}, - {I_FISTTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\201", IF_PRESCOTT|IF_FPU}, - {I_FISUB, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\204", IF_8086|IF_FPU}, - {I_FISUB, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\204", IF_8086|IF_FPU}, - {I_FISUBR, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\205", IF_8086|IF_FPU}, - {I_FISUBR, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\205", IF_8086|IF_FPU}, - {I_FLD, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\200", IF_8086|IF_FPU}, - {I_FLD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\200", IF_8086|IF_FPU}, - {I_FLD, 1, {MEMORY|BITS80,0,0}, "\300\1\xDB\205", IF_8086|IF_FPU}, - {I_FLD, 1, {FPUREG,0,0}, "\1\xD9\10\xC0", IF_8086|IF_FPU}, - {I_FLD1, 0, {0,0,0}, "\2\xD9\xE8", IF_8086|IF_FPU}, - {I_FLDCW, 1, {MEMORY,0,0}, "\300\1\xD9\205", IF_8086|IF_FPU|IF_SW}, - {I_FLDENV, 1, {MEMORY,0,0}, "\300\1\xD9\204", IF_8086|IF_FPU}, - {I_FLDL2E, 0, {0,0,0}, "\2\xD9\xEA", IF_8086|IF_FPU}, - {I_FLDL2T, 0, {0,0,0}, "\2\xD9\xE9", IF_8086|IF_FPU}, - {I_FLDLG2, 0, {0,0,0}, "\2\xD9\xEC", IF_8086|IF_FPU}, - {I_FLDLN2, 0, {0,0,0}, "\2\xD9\xED", IF_8086|IF_FPU}, - {I_FLDPI, 0, {0,0,0}, "\2\xD9\xEB", IF_8086|IF_FPU}, - {I_FLDZ, 0, {0,0,0}, "\2\xD9\xEE", IF_8086|IF_FPU}, - {I_FMUL, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\201", IF_8086|IF_FPU}, - {I_FMUL, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\201", IF_8086|IF_FPU}, - {I_FMUL, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xC8", IF_8086|IF_FPU}, - {I_FMUL, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xC8", IF_8086|IF_FPU}, - {I_FMUL, 1, {FPUREG,0,0}, "\1\xD8\10\xC8", IF_8086|IF_FPU}, - {I_FMUL, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xC8", IF_8086|IF_FPU}, - {I_FMULP, 1, {FPUREG,0,0}, "\1\xDE\10\xC8", IF_8086|IF_FPU}, - {I_FMULP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xC8", IF_8086|IF_FPU}, - {I_FNCLEX, 0, {0,0,0}, "\2\xDB\xE2", IF_8086|IF_FPU}, - {I_FNDISI, 0, {0,0,0}, "\2\xDB\xE1", IF_8086|IF_FPU}, - {I_FNENI, 0, {0,0,0}, "\2\xDB\xE0", IF_8086|IF_FPU}, - {I_FNINIT, 0, {0,0,0}, "\2\xDB\xE3", IF_8086|IF_FPU}, - {I_FNOP, 0, {0,0,0}, "\2\xD9\xD0", IF_8086|IF_FPU}, - {I_FNSAVE, 1, {MEMORY,0,0}, "\300\1\xDD\206", IF_8086|IF_FPU}, - {I_FNSTCW, 1, {MEMORY,0,0}, "\300\1\xD9\207", IF_8086|IF_FPU|IF_SW}, - {I_FNSTENV, 1, {MEMORY,0,0}, "\300\1\xD9\206", IF_8086|IF_FPU}, - {I_FNSTSW, 1, {MEMORY,0,0}, "\300\1\xDD\207", IF_8086|IF_FPU|IF_SW}, - {I_FNSTSW, 1, {REG_AX,0,0}, "\2\xDF\xE0", IF_286|IF_FPU}, - {I_FPATAN, 0, {0,0,0}, "\2\xD9\xF3", IF_8086|IF_FPU}, - {I_FPREM, 0, {0,0,0}, "\2\xD9\xF8", IF_8086|IF_FPU}, - {I_FPREM1, 0, {0,0,0}, "\2\xD9\xF5", IF_386|IF_FPU}, - {I_FPTAN, 0, {0,0,0}, "\2\xD9\xF2", IF_8086|IF_FPU}, - {I_FRNDINT, 0, {0,0,0}, "\2\xD9\xFC", IF_8086|IF_FPU}, - {I_FRSTOR, 1, {MEMORY,0,0}, "\300\1\xDD\204", IF_8086|IF_FPU}, - {I_FSAVE, 1, {MEMORY,0,0}, "\300\2\x9B\xDD\206", IF_8086|IF_FPU}, - {I_FSCALE, 0, {0,0,0}, "\2\xD9\xFD", IF_8086|IF_FPU}, - {I_FSETPM, 0, {0,0,0}, "\2\xDB\xE4", IF_286|IF_FPU}, - {I_FSIN, 0, {0,0,0}, "\2\xD9\xFE", IF_386|IF_FPU}, - {I_FSINCOS, 0, {0,0,0}, "\2\xD9\xFB", IF_386|IF_FPU}, - {I_FSQRT, 0, {0,0,0}, "\2\xD9\xFA", IF_8086|IF_FPU}, - {I_FST, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\202", IF_8086|IF_FPU}, - {I_FST, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\202", IF_8086|IF_FPU}, - {I_FST, 1, {FPUREG,0,0}, "\1\xDD\10\xD0", IF_8086|IF_FPU}, - {I_FSTCW, 1, {MEMORY,0,0}, "\300\2\x9B\xD9\207", IF_8086|IF_FPU|IF_SW}, - {I_FSTENV, 1, {MEMORY,0,0}, "\300\2\x9B\xD9\206", IF_8086|IF_FPU}, - {I_FSTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\203", IF_8086|IF_FPU}, - {I_FSTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\203", IF_8086|IF_FPU}, - {I_FSTP, 1, {MEMORY|BITS80,0,0}, "\300\1\xDB\207", IF_8086|IF_FPU}, - {I_FSTP, 1, {FPUREG,0,0}, "\1\xDD\10\xD8", IF_8086|IF_FPU}, - {I_FSTSW, 1, {MEMORY,0,0}, "\300\2\x9B\xDD\207", IF_8086|IF_FPU|IF_SW}, - {I_FSTSW, 1, {REG_AX,0,0}, "\3\x9B\xDF\xE0", IF_286|IF_FPU}, - {I_FSUB, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\204", IF_8086|IF_FPU}, - {I_FSUB, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\204", IF_8086|IF_FPU}, - {I_FSUB, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xE8", IF_8086|IF_FPU}, - {I_FSUB, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xE8", IF_8086|IF_FPU}, - {I_FSUB, 1, {FPUREG,0,0}, "\1\xD8\10\xE0", IF_8086|IF_FPU}, - {I_FSUB, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xE0", IF_8086|IF_FPU}, - {I_FSUBP, 1, {FPUREG,0,0}, "\1\xDE\10\xE8", IF_8086|IF_FPU}, - {I_FSUBP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xE8", IF_8086|IF_FPU}, - {I_FSUBR, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\205", IF_8086|IF_FPU}, - {I_FSUBR, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\205", IF_8086|IF_FPU}, - {I_FSUBR, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xE0", IF_8086|IF_FPU}, - {I_FSUBR, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xE0", IF_8086|IF_FPU}, - {I_FSUBR, 1, {FPUREG,0,0}, "\1\xD8\10\xE8", IF_8086|IF_FPU}, - {I_FSUBR, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xE8", IF_8086|IF_FPU}, - {I_FSUBRP, 1, {FPUREG,0,0}, "\1\xDE\10\xE0", IF_8086|IF_FPU}, - {I_FSUBRP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xE0", IF_8086|IF_FPU}, - {I_FTST, 0, {0,0,0}, "\2\xD9\xE4", IF_8086|IF_FPU}, - {I_FUCOM, 1, {FPUREG,0,0}, "\1\xDD\10\xE0", IF_386|IF_FPU}, - {I_FUCOM, 2, {FPU0,FPUREG,0}, "\1\xDD\11\xE0", IF_386|IF_FPU}, - {I_FUCOMI, 1, {FPUREG,0,0}, "\1\xDB\10\xE8", IF_P6|IF_FPU}, - {I_FUCOMI, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xE8", IF_P6|IF_FPU}, - {I_FUCOMIP, 1, {FPUREG,0,0}, "\1\xDF\10\xE8", IF_P6|IF_FPU}, - {I_FUCOMIP, 2, {FPU0,FPUREG,0}, "\1\xDF\11\xE8", IF_P6|IF_FPU}, - {I_FUCOMP, 1, {FPUREG,0,0}, "\1\xDD\10\xE8", IF_386|IF_FPU}, - {I_FUCOMP, 2, {FPU0,FPUREG,0}, "\1\xDD\11\xE8", IF_386|IF_FPU}, - {I_FUCOMPP, 0, {0,0,0}, "\2\xDA\xE9", IF_386|IF_FPU}, - {I_FXAM, 0, {0,0,0}, "\2\xD9\xE5", IF_8086|IF_FPU}, - {I_FXCH, 0, {0,0,0}, "\2\xD9\xC9", IF_8086|IF_FPU}, - {I_FXCH, 1, {FPUREG,0,0}, "\1\xD9\10\xC8", IF_8086|IF_FPU}, - {I_FXCH, 2, {FPUREG,FPU0,0}, "\1\xD9\10\xC8", IF_8086|IF_FPU}, - {I_FXCH, 2, {FPU0,FPUREG,0}, "\1\xD9\11\xC8", IF_8086|IF_FPU}, - {I_FXTRACT, 0, {0,0,0}, "\2\xD9\xF4", IF_8086|IF_FPU}, - {I_FYL2X, 0, {0,0,0}, "\2\xD9\xF1", IF_8086|IF_FPU}, - {I_FYL2XP1, 0, {0,0,0}, "\2\xD9\xF9", IF_8086|IF_FPU}, - {I_HLT, 0, {0,0,0}, "\1\xF4", IF_8086|IF_PRIV}, - {I_IDIV, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\207", IF_8086}, - {I_IDIV, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\207", IF_8086}, - {I_IDIV, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\207", IF_386}, - {I_IMUL, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\205", IF_8086}, - {I_IMUL, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\205", IF_8086}, - {I_IMUL, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\205", IF_386}, - {I_IMUL, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xAF\110", IF_386|IF_SM}, - {I_IMUL, 2, {REG16,REG16,0}, "\320\2\x0F\xAF\110", IF_386}, - {I_IMUL, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xAF\110", IF_386|IF_SM}, - {I_IMUL, 2, {REG32,REG32,0}, "\321\2\x0F\xAF\110", IF_386}, - {I_IMUL, 3, {REG16,MEMORY,IMMEDIATE|BITS8}, "\320\301\1\x6B\110\16", IF_186|IF_SM}, - {I_IMUL, 3, {REG16,MEMORY,IMMEDIATE|BITS16}, "\320\301\1\x69\110\32", IF_186|IF_SM}, - {I_IMUL, 3, {REG16,REG16,IMMEDIATE|BITS8}, "\320\1\x6B\110\16", IF_186}, - {I_IMUL, 3, {REG16,REG16,IMMEDIATE|BITS16}, "\320\1\x69\110\32", IF_186}, - {I_IMUL, 3, {REG32,MEMORY,IMMEDIATE|BITS8}, "\321\301\1\x6B\110\16", IF_386|IF_SM}, - {I_IMUL, 3, {REG32,MEMORY,IMMEDIATE|BITS32}, "\321\301\1\x69\110\42", IF_386|IF_SM}, - {I_IMUL, 3, {REG32,REG32,IMMEDIATE|BITS8}, "\321\1\x6B\110\16", IF_386}, - {I_IMUL, 3, {REG32,REG32,IMMEDIATE|BITS32}, "\321\1\x69\110\42", IF_386}, - {I_IMUL, 2, {REG16,IMMEDIATE|BITS8,0}, "\320\1\x6B\100\15", IF_186}, - {I_IMUL, 2, {REG16,IMMEDIATE|BITS16,0}, "\320\1\x69\100\31", IF_186}, - {I_IMUL, 2, {REG32,IMMEDIATE|BITS8,0}, "\321\1\x6B\100\15", IF_386}, - {I_IMUL, 2, {REG32,IMMEDIATE|BITS32,0}, "\321\1\x69\100\41", IF_386}, - {I_IN, 2, {REG_AL,IMMEDIATE,0}, "\1\xE4\25", IF_8086|IF_SB}, - {I_IN, 2, {REG_AX,IMMEDIATE,0}, "\320\1\xE5\25", IF_8086|IF_SB}, - {I_IN, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\xE5\25", IF_386|IF_SB}, - {I_IN, 2, {REG_AL,REG_DX,0}, "\1\xEC", IF_8086}, - {I_IN, 2, {REG_AX,REG_DX,0}, "\320\1\xED", IF_8086}, - {I_IN, 2, {REG_EAX,REG_DX,0}, "\321\1\xED", IF_386}, - {I_INC, 1, {REG16,0,0}, "\320\10\x40", IF_8086}, - {I_INC, 1, {REG32,0,0}, "\321\10\x40", IF_386}, - {I_INC, 1, {REGMEM|BITS8,0,0}, "\300\1\xFE\200", IF_8086}, - {I_INC, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\200", IF_8086}, - {I_INC, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\200", IF_386}, - {I_INSB, 0, {0,0,0}, "\1\x6C", IF_186}, - {I_INSD, 0, {0,0,0}, "\321\1\x6D", IF_386}, - {I_INSW, 0, {0,0,0}, "\320\1\x6D", IF_186}, - {I_INT, 1, {IMMEDIATE,0,0}, "\1\xCD\24", IF_8086|IF_SB}, - {I_INT1, 0, {0,0,0}, "\1\xF1", IF_386}, - {I_INT3, 0, {0,0,0}, "\1\xCC", IF_8086}, - {I_INTO, 0, {0,0,0}, "\1\xCE", IF_8086}, - {I_INVD, 0, {0,0,0}, "\2\x0F\x08", IF_486|IF_PRIV}, - {I_INVLPG, 1, {MEMORY,0,0}, "\300\2\x0F\x01\207", IF_486|IF_PRIV}, - {I_IRET, 0, {0,0,0}, "\322\1\xCF", IF_8086}, - {I_IRETD, 0, {0,0,0}, "\321\1\xCF", IF_386}, - {I_IRETW, 0, {0,0,0}, "\320\1\xCF", IF_8086}, - {I_JCXZ, 1, {IMMEDIATE,0,0}, "\310\1\xE3\50", IF_8086}, - {I_JECXZ, 1, {IMMEDIATE,0,0}, "\311\1\xE3\50", IF_386}, - {I_JMP, 1, {IMMEDIATE|SHORT,0,0}, "\1\xEB\50", IF_8086}, - {I_JMP, 1, {IMMEDIATE,0,0}, "\322\1\xE9\64", IF_8086}, - {I_JMP, 1, {IMMEDIATE|BITS16,0,0}, "\320\1\xE9\64", IF_8086}, - {I_JMP, 1, {IMMEDIATE|BITS32,0,0}, "\321\1\xE9\64", IF_386}, - {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\322\1\xEA\35\30", IF_8086}, - {I_JMP, 2, {IMMEDIATE|BITS16|COLON,IMMEDIATE,0}, "\320\1\xEA\31\30", IF_8086}, - {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS16,0}, "\320\1\xEA\31\30", IF_8086}, - {I_JMP, 2, {IMMEDIATE|BITS32|COLON,IMMEDIATE,0}, "\321\1\xEA\41\30", IF_386}, - {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS32,0}, "\321\1\xEA\41\30", IF_386}, - {I_JMP, 1, {MEMORY|FAR,0,0}, "\322\300\1\xFF\205", IF_8086}, - {I_JMP, 1, {MEMORY|BITS16|FAR,0,0}, "\320\300\1\xFF\205", IF_8086}, - {I_JMP, 1, {MEMORY|BITS32|FAR,0,0}, "\321\300\1\xFF\205", IF_386}, - {I_JMP, 1, {MEMORY|NEAR,0,0}, "\322\300\1\xFF\204", IF_8086}, - {I_JMP, 1, {MEMORY|BITS16|NEAR,0,0}, "\320\300\1\xFF\204", IF_8086}, - {I_JMP, 1, {MEMORY|BITS32|NEAR,0,0}, "\321\300\1\xFF\204", IF_386}, - {I_JMP, 1, {REG16,0,0}, "\320\300\1\xFF\204", IF_8086}, - {I_JMP, 1, {REG32,0,0}, "\321\300\1\xFF\204", IF_386}, - {I_JMP, 1, {MEMORY,0,0}, "\322\300\1\xFF\204", IF_8086}, - {I_JMP, 1, {MEMORY|BITS16,0,0}, "\320\300\1\xFF\204", IF_8086}, - {I_JMP, 1, {MEMORY|BITS32,0,0}, "\321\300\1\xFF\204", IF_386}, - {I_JMPE, 1, {IMMEDIATE,0,0}, "\322\2\x0F\xB8\64", IF_IA64}, - {I_JMPE, 1, {IMMEDIATE|BITS16,0,0}, "\320\2\x0F\xB8\64", IF_IA64}, - {I_JMPE, 1, {IMMEDIATE|BITS32,0,0}, "\321\2\x0F\xB8\64", IF_IA64}, - {I_JMPE, 1, {REGMEM|BITS16,0,0}, "\320\2\x0F\x00\206", IF_IA64}, - {I_JMPE, 1, {REGMEM|BITS32,0,0}, "\321\2\x0F\x00\206", IF_IA64}, - {I_LAHF, 0, {0,0,0}, "\1\x9F", IF_8086}, - {I_LAR, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x02\110", IF_286|IF_PROT|IF_SM}, - {I_LAR, 2, {REG16,REG16,0}, "\320\2\x0F\x02\110", IF_286|IF_PROT}, - {I_LAR, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x02\110", IF_386|IF_PROT|IF_SM}, - {I_LAR, 2, {REG32,REG32,0}, "\321\2\x0F\x02\110", IF_386|IF_PROT}, - {I_LDS, 2, {REG16,MEMORY,0}, "\320\301\1\xC5\110", IF_8086}, - {I_LDS, 2, {REG32,MEMORY,0}, "\321\301\1\xC5\110", IF_386}, - {I_LEA, 2, {REG16,MEMORY,0}, "\320\301\1\x8D\110", IF_8086}, - {I_LEA, 2, {REG32,MEMORY,0}, "\321\301\1\x8D\110", IF_386}, - {I_LEAVE, 0, {0,0,0}, "\1\xC9", IF_186}, - {I_LES, 2, {REG16,MEMORY,0}, "\320\301\1\xC4\110", IF_8086}, - {I_LES, 2, {REG32,MEMORY,0}, "\321\301\1\xC4\110", IF_386}, - {I_LFS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB4\110", IF_386}, - {I_LFS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB4\110", IF_386}, - {I_LGDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\202", IF_286|IF_PRIV}, - {I_LGS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB5\110", IF_386}, - {I_LGS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB5\110", IF_386}, - {I_LIDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\203", IF_286|IF_PRIV}, - {I_LLDT, 1, {MEMORY,0,0}, "\300\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, - {I_LLDT, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, - {I_LLDT, 1, {REG16,0,0}, "\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, - {I_LMSW, 1, {MEMORY,0,0}, "\300\2\x0F\x01\206", IF_286|IF_PRIV}, - {I_LMSW, 1, {MEMORY|BITS16,0,0}, "\300\2\x0F\x01\206", IF_286|IF_PRIV}, - {I_LMSW, 1, {REG16,0,0}, "\2\x0F\x01\206", IF_286|IF_PRIV}, - {I_LOADALL, 0, {0,0,0}, "\2\x0F\x07", IF_386|IF_UNDOC}, - {I_LOADALL286, 0, {0,0,0}, "\2\x0F\x05", IF_286|IF_UNDOC}, - {I_LODSB, 0, {0,0,0}, "\1\xAC", IF_8086}, - {I_LODSD, 0, {0,0,0}, "\321\1\xAD", IF_386}, - {I_LODSW, 0, {0,0,0}, "\320\1\xAD", IF_8086}, - {I_LOOP, 1, {IMMEDIATE,0,0}, "\312\1\xE2\50", IF_8086}, - {I_LOOP, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE2\50", IF_8086}, - {I_LOOP, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE2\50", IF_386}, - {I_LOOPE, 1, {IMMEDIATE,0,0}, "\312\1\xE1\50", IF_8086}, - {I_LOOPE, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE1\50", IF_8086}, - {I_LOOPE, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE1\50", IF_386}, - {I_LOOPNE, 1, {IMMEDIATE,0,0}, "\312\1\xE0\50", IF_8086}, - {I_LOOPNE, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE0\50", IF_8086}, - {I_LOOPNE, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE0\50", IF_386}, - {I_LOOPNZ, 1, {IMMEDIATE,0,0}, "\312\1\xE0\50", IF_8086}, - {I_LOOPNZ, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE0\50", IF_8086}, - {I_LOOPNZ, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE0\50", IF_386}, - {I_LOOPZ, 1, {IMMEDIATE,0,0}, "\312\1\xE1\50", IF_8086}, - {I_LOOPZ, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE1\50", IF_8086}, - {I_LOOPZ, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE1\50", IF_386}, - {I_LSL, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x03\110", IF_286|IF_PROT|IF_SM}, - {I_LSL, 2, {REG16,REG16,0}, "\320\2\x0F\x03\110", IF_286|IF_PROT}, - {I_LSL, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x03\110", IF_386|IF_PROT|IF_SM}, - {I_LSL, 2, {REG32,REG32,0}, "\321\2\x0F\x03\110", IF_386|IF_PROT}, - {I_LSS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB2\110", IF_386}, - {I_LSS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB2\110", IF_386}, - {I_LTR, 1, {MEMORY,0,0}, "\300\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, - {I_LTR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, - {I_LTR, 1, {REG16,0,0}, "\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, - {I_MONITOR, 0, {0,0,0}, "\3\x0F\x01\xC8", IF_PRESCOTT}, - {I_MOV, 2, {MEMORY,REG_SREG,0}, "\300\1\x8C\101", IF_8086|IF_SM}, - {I_MOV, 2, {REG16,REG_SREG,0}, "\320\1\x8C\101", IF_8086}, - {I_MOV, 2, {REG32,REG_SREG,0}, "\321\1\x8C\101", IF_386}, - {I_MOV, 2, {REG_SREG,MEMORY,0}, "\301\1\x8E\110", IF_8086|IF_SM}, - {I_MOV, 2, {REG_SREG,REG16,0}, "\1\x8E\110", IF_8086}, - {I_MOV, 2, {REG_SREG,REG32,0}, "\1\x8E\110", IF_386}, - {I_MOV, 2, {REG_AL,MEM_OFFS,0}, "\301\1\xA0\45", IF_8086|IF_SM}, - {I_MOV, 2, {REG_AX,MEM_OFFS,0}, "\301\320\1\xA1\45", IF_8086|IF_SM}, - {I_MOV, 2, {REG_EAX,MEM_OFFS,0}, "\301\321\1\xA1\45", IF_386|IF_SM}, - {I_MOV, 2, {MEM_OFFS,REG_AL,0}, "\300\1\xA2\44", IF_8086|IF_SM}, - {I_MOV, 2, {MEM_OFFS,REG_AX,0}, "\300\320\1\xA3\44", IF_8086|IF_SM}, - {I_MOV, 2, {MEM_OFFS,REG_EAX,0}, "\300\321\1\xA3\44", IF_386|IF_SM}, - {I_MOV, 2, {REG32,REG_CREG,0}, "\2\x0F\x20\101", IF_386|IF_PRIV}, - {I_MOV, 2, {REG32,REG_DREG,0}, "\2\x0F\x21\101", IF_386|IF_PRIV}, - {I_MOV, 2, {REG32,REG_TREG,0}, "\2\x0F\x24\101", IF_386|IF_PRIV}, - {I_MOV, 2, {REG_CREG,REG32,0}, "\2\x0F\x22\110", IF_386|IF_PRIV}, - {I_MOV, 2, {REG_DREG,REG32,0}, "\2\x0F\x23\110", IF_386|IF_PRIV}, - {I_MOV, 2, {REG_TREG,REG32,0}, "\2\x0F\x26\110", IF_386|IF_PRIV}, - {I_MOV, 2, {MEMORY,REG8,0}, "\300\1\x88\101", IF_8086|IF_SM}, - {I_MOV, 2, {REG8,REG8,0}, "\1\x88\101", IF_8086}, - {I_MOV, 2, {MEMORY,REG16,0}, "\320\300\1\x89\101", IF_8086|IF_SM}, - {I_MOV, 2, {REG16,REG16,0}, "\320\1\x89\101", IF_8086}, - {I_MOV, 2, {MEMORY,REG32,0}, "\321\300\1\x89\101", IF_386|IF_SM}, - {I_MOV, 2, {REG32,REG32,0}, "\321\1\x89\101", IF_386}, - {I_MOV, 2, {REG8,MEMORY,0}, "\301\1\x8A\110", IF_8086|IF_SM}, - {I_MOV, 2, {REG8,REG8,0}, "\1\x8A\110", IF_8086}, - {I_MOV, 2, {REG16,MEMORY,0}, "\320\301\1\x8B\110", IF_8086|IF_SM}, - {I_MOV, 2, {REG16,REG16,0}, "\320\1\x8B\110", IF_8086}, - {I_MOV, 2, {REG32,MEMORY,0}, "\321\301\1\x8B\110", IF_386|IF_SM}, - {I_MOV, 2, {REG32,REG32,0}, "\321\1\x8B\110", IF_386}, - {I_MOV, 2, {REG8,IMMEDIATE,0}, "\10\xB0\21", IF_8086|IF_SM}, - {I_MOV, 2, {REG16,IMMEDIATE,0}, "\320\10\xB8\31", IF_8086|IF_SM}, - {I_MOV, 2, {REG32,IMMEDIATE,0}, "\321\10\xB8\41", IF_386|IF_SM}, - {I_MOV, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC6\200\21", IF_8086|IF_SM}, - {I_MOV, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC7\200\31", IF_8086|IF_SM}, - {I_MOV, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC7\200\41", IF_386|IF_SM}, - {I_MOV, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\xC6\200\21", IF_8086|IF_SM}, - {I_MOV, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\1\xC7\200\31", IF_8086|IF_SM}, - {I_MOV, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\1\xC7\200\41", IF_386|IF_SM}, - {I_MOVD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6E\110", IF_PENT|IF_MMX|IF_SD}, - {I_MOVD, 2, {MMXREG,REG32,0}, "\2\x0F\x6E\110", IF_PENT|IF_MMX}, - {I_MOVD, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\x7E\101", IF_PENT|IF_MMX|IF_SD}, - {I_MOVD, 2, {REG32,MMXREG,0}, "\2\x0F\x7E\101", IF_PENT|IF_MMX}, - {I_MOVQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6F\110", IF_PENT|IF_MMX|IF_SM}, - {I_MOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6F\110", IF_PENT|IF_MMX}, - {I_MOVQ, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\x7F\101", IF_PENT|IF_MMX|IF_SM}, - {I_MOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x7F\101", IF_PENT|IF_MMX}, - {I_MOVSB, 0, {0,0,0}, "\1\xA4", IF_8086}, - {I_MOVSD, 0, {0,0,0}, "\321\1\xA5", IF_386}, - {I_MOVSW, 0, {0,0,0}, "\320\1\xA5", IF_8086}, - {I_MOVSX, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBE\110", IF_386|IF_SB}, - {I_MOVSX, 2, {REG16,REG8,0}, "\320\2\x0F\xBE\110", IF_386}, - {I_MOVSX, 2, {REG32,REGMEM|BITS8,0}, "\321\301\2\x0F\xBE\110", IF_386}, - {I_MOVSX, 2, {REG32,REGMEM|BITS16,0}, "\321\301\2\x0F\xBF\110", IF_386}, - {I_MOVZX, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB6\110", IF_386|IF_SB}, - {I_MOVZX, 2, {REG16,REG8,0}, "\320\2\x0F\xB6\110", IF_386}, - {I_MOVZX, 2, {REG32,REGMEM|BITS8,0}, "\321\301\2\x0F\xB6\110", IF_386}, - {I_MOVZX, 2, {REG32,REGMEM|BITS16,0}, "\321\301\2\x0F\xB7\110", IF_386}, - {I_MUL, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\204", IF_8086}, - {I_MUL, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\204", IF_8086}, - {I_MUL, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\204", IF_386}, - {I_MWAIT, 0, {0,0,0}, "\3\x0F\x01\xC9", IF_PRESCOTT}, - {I_NEG, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\203", IF_8086}, - {I_NEG, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\203", IF_8086}, - {I_NEG, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\203", IF_386}, - {I_NOP, 0, {0,0,0}, "\1\x90", IF_8086}, - {I_NOT, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\202", IF_8086}, - {I_NOT, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\202", IF_8086}, - {I_NOT, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\202", IF_386}, - {I_OR, 2, {MEMORY,REG8,0}, "\300\1\x08\101", IF_8086|IF_SM}, - {I_OR, 2, {REG8,REG8,0}, "\1\x08\101", IF_8086}, - {I_OR, 2, {MEMORY,REG16,0}, "\320\300\1\x09\101", IF_8086|IF_SM}, - {I_OR, 2, {REG16,REG16,0}, "\320\1\x09\101", IF_8086}, - {I_OR, 2, {MEMORY,REG32,0}, "\321\300\1\x09\101", IF_386|IF_SM}, - {I_OR, 2, {REG32,REG32,0}, "\321\1\x09\101", IF_386}, - {I_OR, 2, {REG8,MEMORY,0}, "\301\1\x0A\110", IF_8086|IF_SM}, - {I_OR, 2, {REG8,REG8,0}, "\1\x0A\110", IF_8086}, - {I_OR, 2, {REG16,MEMORY,0}, "\320\301\1\x0B\110", IF_8086|IF_SM}, - {I_OR, 2, {REG16,REG16,0}, "\320\1\x0B\110", IF_8086}, - {I_OR, 2, {REG32,MEMORY,0}, "\321\301\1\x0B\110", IF_386|IF_SM}, - {I_OR, 2, {REG32,REG32,0}, "\321\1\x0B\110", IF_386}, - {I_OR, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\201\15", IF_8086}, - {I_OR, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\201\15", IF_386}, - {I_OR, 2, {REG_AL,IMMEDIATE,0}, "\1\x0C\21", IF_8086|IF_SM}, - {I_OR, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x0D\31", IF_8086|IF_SM}, - {I_OR, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x0D\41", IF_386|IF_SM}, - {I_OR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\201\21", IF_8086|IF_SM}, - {I_OR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\201\131", IF_8086|IF_SM}, - {I_OR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\201\141", IF_386|IF_SM}, - {I_OR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\201\21", IF_8086|IF_SM}, - {I_OR, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\201\131", IF_8086|IF_SM}, - {I_OR, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\201\141", IF_386|IF_SM}, - {I_OUT, 2, {IMMEDIATE,REG_AL,0}, "\1\xE6\24", IF_8086|IF_SB}, - {I_OUT, 2, {IMMEDIATE,REG_AX,0}, "\320\1\xE7\24", IF_8086|IF_SB}, - {I_OUT, 2, {IMMEDIATE,REG_EAX,0}, "\321\1\xE7\24", IF_386|IF_SB}, - {I_OUT, 2, {REG_DX,REG_AL,0}, "\1\xEE", IF_8086}, - {I_OUT, 2, {REG_DX,REG_AX,0}, "\320\1\xEF", IF_8086}, - {I_OUT, 2, {REG_DX,REG_EAX,0}, "\321\1\xEF", IF_386}, - {I_OUTSB, 0, {0,0,0}, "\1\x6E", IF_186}, - {I_OUTSD, 0, {0,0,0}, "\321\1\x6F", IF_386}, - {I_OUTSW, 0, {0,0,0}, "\320\1\x6F", IF_186}, - {I_PACKSSDW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6B\110", IF_PENT|IF_MMX|IF_SM}, - {I_PACKSSDW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6B\110", IF_PENT|IF_MMX}, - {I_PACKSSWB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x63\110", IF_PENT|IF_MMX|IF_SM}, - {I_PACKSSWB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x63\110", IF_PENT|IF_MMX}, - {I_PACKUSWB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x67\110", IF_PENT|IF_MMX|IF_SM}, - {I_PACKUSWB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x67\110", IF_PENT|IF_MMX}, - {I_PADDB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFC\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFC\110", IF_PENT|IF_MMX}, - {I_PADDD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFE\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFE\110", IF_PENT|IF_MMX}, - {I_PADDSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEC\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEC\110", IF_PENT|IF_MMX}, - {I_PADDSIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x51\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PADDSIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x51\110", IF_PENT|IF_MMX|IF_CYRIX}, - {I_PADDSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xED\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xED\110", IF_PENT|IF_MMX}, - {I_PADDUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDC\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDC\110", IF_PENT|IF_MMX}, - {I_PADDUSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDD\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDUSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDD\110", IF_PENT|IF_MMX}, - {I_PADDW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFD\110", IF_PENT|IF_MMX|IF_SM}, - {I_PADDW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFD\110", IF_PENT|IF_MMX}, - {I_PAND, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDB\110", IF_PENT|IF_MMX|IF_SM}, - {I_PAND, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDB\110", IF_PENT|IF_MMX}, - {I_PANDN, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDF\110", IF_PENT|IF_MMX|IF_SM}, - {I_PANDN, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDF\110", IF_PENT|IF_MMX}, - {I_PAVEB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x50\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PAVEB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x50\110", IF_PENT|IF_MMX|IF_CYRIX}, - {I_PAVGUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xBF", IF_PENT|IF_3DNOW|IF_SM}, - {I_PAVGUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xBF", IF_PENT|IF_3DNOW}, - {I_PCMPEQB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x74\110", IF_PENT|IF_MMX|IF_SM}, - {I_PCMPEQB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x74\110", IF_PENT|IF_MMX}, - {I_PCMPEQD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x76\110", IF_PENT|IF_MMX|IF_SM}, - {I_PCMPEQD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x76\110", IF_PENT|IF_MMX}, - {I_PCMPEQW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x75\110", IF_PENT|IF_MMX|IF_SM}, - {I_PCMPEQW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x75\110", IF_PENT|IF_MMX}, - {I_PCMPGTB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x64\110", IF_PENT|IF_MMX|IF_SM}, - {I_PCMPGTB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x64\110", IF_PENT|IF_MMX}, - {I_PCMPGTD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x66\110", IF_PENT|IF_MMX|IF_SM}, - {I_PCMPGTD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x66\110", IF_PENT|IF_MMX}, - {I_PCMPGTW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x65\110", IF_PENT|IF_MMX|IF_SM}, - {I_PCMPGTW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x65\110", IF_PENT|IF_MMX}, - {I_PDISTIB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x54\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PF2ID, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x1D", IF_PENT|IF_3DNOW|IF_SM}, - {I_PF2ID, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x1D", IF_PENT|IF_3DNOW}, - {I_PFACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xAE", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xAE", IF_PENT|IF_3DNOW}, - {I_PFADD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x9E", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFADD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x9E", IF_PENT|IF_3DNOW}, - {I_PFCMPEQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB0", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFCMPEQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB0", IF_PENT|IF_3DNOW}, - {I_PFCMPGE, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x90", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFCMPGE, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x90", IF_PENT|IF_3DNOW}, - {I_PFCMPGT, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA0", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFCMPGT, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA0", IF_PENT|IF_3DNOW}, - {I_PFMAX, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA4", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFMAX, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA4", IF_PENT|IF_3DNOW}, - {I_PFMIN, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x94", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFMIN, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x94", IF_PENT|IF_3DNOW}, - {I_PFMUL, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB4", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFMUL, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB4", IF_PENT|IF_3DNOW}, - {I_PFRCP, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x96", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFRCP, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x96", IF_PENT|IF_3DNOW}, - {I_PFRCPIT1, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA6", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFRCPIT1, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA6", IF_PENT|IF_3DNOW}, - {I_PFRCPIT2, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB6", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFRCPIT2, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB6", IF_PENT|IF_3DNOW}, - {I_PFRSQIT1, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA7", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFRSQIT1, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA7", IF_PENT|IF_3DNOW}, - {I_PFRSQRT, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x97", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFRSQRT, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x97", IF_PENT|IF_3DNOW}, - {I_PFSUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x9A", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFSUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x9A", IF_PENT|IF_3DNOW}, - {I_PFSUBR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xAA", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFSUBR, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xAA", IF_PENT|IF_3DNOW}, - {I_PI2FD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x0D", IF_PENT|IF_3DNOW|IF_SM}, - {I_PI2FD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x0D", IF_PENT|IF_3DNOW}, - {I_PMACHRIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5E\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMADDWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF5\110", IF_PENT|IF_MMX|IF_SM}, - {I_PMADDWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF5\110", IF_PENT|IF_MMX}, - {I_PMAGW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x52\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMAGW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x52\110", IF_PENT|IF_MMX|IF_CYRIX}, - {I_PMULHRIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5D\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMULHRIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x5D\110", IF_PENT|IF_MMX|IF_CYRIX}, - {I_PMULHRWA, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\1\xB7", IF_PENT|IF_3DNOW|IF_SM}, - {I_PMULHRWA, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\1\xB7", IF_PENT|IF_3DNOW}, - {I_PMULHRWC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x59\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMULHRWC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x59\110", IF_PENT|IF_MMX|IF_CYRIX}, - {I_PMULHW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE5\110", IF_PENT|IF_MMX|IF_SM}, - {I_PMULHW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE5\110", IF_PENT|IF_MMX}, - {I_PMULLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD5\110", IF_PENT|IF_MMX|IF_SM}, - {I_PMULLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD5\110", IF_PENT|IF_MMX}, - {I_PMVGEZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5C\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMVLZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5B\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMVNZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5A\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PMVZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x58\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_POP, 1, {REG16,0,0}, "\320\10\x58", IF_8086}, - {I_POP, 1, {REG32,0,0}, "\321\10\x58", IF_386}, - {I_POP, 1, {REGMEM|BITS16,0,0}, "\320\300\1\x8F\200", IF_8086}, - {I_POP, 1, {REGMEM|BITS32,0,0}, "\321\300\1\x8F\200", IF_386}, - {I_POP, 1, {REG_DESS,0,0}, "\4", IF_8086}, - {I_POP, 1, {REG_FSGS,0,0}, "\1\x0F\5", IF_386}, - {I_POPA, 0, {0,0,0}, "\322\1\x61", IF_186}, - {I_POPAD, 0, {0,0,0}, "\321\1\x61", IF_386}, - {I_POPAW, 0, {0,0,0}, "\320\1\x61", IF_186}, - {I_POPF, 0, {0,0,0}, "\322\1\x9D", IF_8086}, - {I_POPFD, 0, {0,0,0}, "\321\1\x9D", IF_386}, - {I_POPFW, 0, {0,0,0}, "\320\1\x9D", IF_8086}, - {I_POR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEB\110", IF_PENT|IF_MMX|IF_SM}, - {I_POR, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEB\110", IF_PENT|IF_MMX}, - {I_PREFETCH, 1, {MEMORY,0,0}, "\2\x0F\x0D\200", IF_PENT|IF_3DNOW|IF_SM}, - {I_PREFETCHW, 1, {MEMORY,0,0}, "\2\x0F\x0D\201", IF_PENT|IF_3DNOW|IF_SM}, - {I_PSLLD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF2\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSLLD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF2\110", IF_PENT|IF_MMX}, - {I_PSLLD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\206\25", IF_PENT|IF_MMX}, - {I_PSLLQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF3\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSLLQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF3\110", IF_PENT|IF_MMX}, - {I_PSLLQ, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x73\206\25", IF_PENT|IF_MMX}, - {I_PSLLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF1\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSLLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF1\110", IF_PENT|IF_MMX}, - {I_PSLLW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\206\25", IF_PENT|IF_MMX}, - {I_PSRAD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE2\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSRAD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE2\110", IF_PENT|IF_MMX}, - {I_PSRAD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\204\25", IF_PENT|IF_MMX}, - {I_PSRAW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE1\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSRAW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE1\110", IF_PENT|IF_MMX}, - {I_PSRAW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\204\25", IF_PENT|IF_MMX}, - {I_PSRLD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD2\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSRLD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD2\110", IF_PENT|IF_MMX}, - {I_PSRLD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\202\25", IF_PENT|IF_MMX}, - {I_PSRLQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD3\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSRLQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD3\110", IF_PENT|IF_MMX}, - {I_PSRLQ, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x73\202\25", IF_PENT|IF_MMX}, - {I_PSRLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD1\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSRLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD1\110", IF_PENT|IF_MMX}, - {I_PSRLW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\202\25", IF_PENT|IF_MMX}, - {I_PSUBB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF8\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF8\110", IF_PENT|IF_MMX}, - {I_PSUBD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFA\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFA\110", IF_PENT|IF_MMX}, - {I_PSUBSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE8\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE8\110", IF_PENT|IF_MMX}, - {I_PSUBSIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x55\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - {I_PSUBSIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x55\110", IF_PENT|IF_MMX|IF_CYRIX}, - {I_PSUBSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE9\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE9\110", IF_PENT|IF_MMX}, - {I_PSUBUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD8\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD8\110", IF_PENT|IF_MMX}, - {I_PSUBUSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD9\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBUSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD9\110", IF_PENT|IF_MMX}, - {I_PSUBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF9\110", IF_PENT|IF_MMX|IF_SM}, - {I_PSUBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF9\110", IF_PENT|IF_MMX}, - {I_PUNPCKHBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x68\110", IF_PENT|IF_MMX|IF_SM}, - {I_PUNPCKHBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x68\110", IF_PENT|IF_MMX}, - {I_PUNPCKHDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6A\110", IF_PENT|IF_MMX|IF_SM}, - {I_PUNPCKHDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6A\110", IF_PENT|IF_MMX}, - {I_PUNPCKHWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x69\110", IF_PENT|IF_MMX|IF_SM}, - {I_PUNPCKHWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x69\110", IF_PENT|IF_MMX}, - {I_PUNPCKLBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x60\110", IF_PENT|IF_MMX|IF_SM}, - {I_PUNPCKLBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x60\110", IF_PENT|IF_MMX}, - {I_PUNPCKLDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x62\110", IF_PENT|IF_MMX|IF_SM}, - {I_PUNPCKLDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x62\110", IF_PENT|IF_MMX}, - {I_PUNPCKLWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x61\110", IF_PENT|IF_MMX|IF_SM}, - {I_PUNPCKLWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x61\110", IF_PENT|IF_MMX}, - {I_PUSH, 1, {REG16,0,0}, "\320\10\x50", IF_8086}, - {I_PUSH, 1, {REG32,0,0}, "\321\10\x50", IF_386}, - {I_PUSH, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\206", IF_8086}, - {I_PUSH, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\206", IF_386}, - {I_PUSH, 1, {REG_CS,0,0}, "\6", IF_8086}, - {I_PUSH, 1, {REG_DESS,0,0}, "\6", IF_8086}, - {I_PUSH, 1, {REG_FSGS,0,0}, "\1\x0F\7", IF_386}, - {I_PUSH, 1, {IMMEDIATE|BITS8,0,0}, "\1\x6A\14", IF_186}, - {I_PUSH, 1, {IMMEDIATE|BITS16,0,0}, "\320\133\1\x68\130", IF_186}, - {I_PUSH, 1, {IMMEDIATE|BITS32,0,0}, "\321\143\1\x68\140", IF_386}, - {I_PUSH, 1, {IMMEDIATE,0,0}, "\1\x68\34", IF_186}, - {I_PUSHA, 0, {0,0,0}, "\322\1\x60", IF_186}, - {I_PUSHAD, 0, {0,0,0}, "\321\1\x60", IF_386}, - {I_PUSHAW, 0, {0,0,0}, "\320\1\x60", IF_186}, - {I_PUSHF, 0, {0,0,0}, "\322\1\x9C", IF_8086}, - {I_PUSHFD, 0, {0,0,0}, "\321\1\x9C", IF_386}, - {I_PUSHFW, 0, {0,0,0}, "\320\1\x9C", IF_8086}, - {I_PXOR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEF\110", IF_PENT|IF_MMX|IF_SM}, - {I_PXOR, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEF\110", IF_PENT|IF_MMX}, - {I_RCL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\202", IF_8086}, - {I_RCL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\202", IF_8086}, - {I_RCL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\202\25", IF_186|IF_SB}, - {I_RCL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\202", IF_8086}, - {I_RCL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\202", IF_8086}, - {I_RCL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\202\25", IF_186|IF_SB}, - {I_RCL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\202", IF_386}, - {I_RCL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\202", IF_386}, - {I_RCL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\202\25", IF_386|IF_SB}, - {I_RCR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\203", IF_8086}, - {I_RCR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\203", IF_8086}, - {I_RCR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\203\25", IF_186|IF_SB}, - {I_RCR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\203", IF_8086}, - {I_RCR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\203", IF_8086}, - {I_RCR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\203\25", IF_186|IF_SB}, - {I_RCR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\203", IF_386}, - {I_RCR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\203", IF_386}, - {I_RCR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\203\25", IF_386|IF_SB}, - {I_RDSHR, 1, {REGMEM|BITS32,0,0}, "\321\300\2\x0F\x36\200", IF_P6|IF_CYRIX|IF_SMM}, - {I_RDMSR, 0, {0,0,0}, "\2\x0F\x32", IF_PENT|IF_PRIV}, - {I_RDPMC, 0, {0,0,0}, "\2\x0F\x33", IF_P6}, - {I_RDTSC, 0, {0,0,0}, "\2\x0F\x31", IF_PENT}, - {I_RESB, 1, {IMMEDIATE,0,0}, "\340", IF_8086}, - {I_RET, 0, {0,0,0}, "\1\xC3", IF_8086}, - {I_RET, 1, {IMMEDIATE,0,0}, "\1\xC2\30", IF_8086|IF_SW}, - {I_RETF, 0, {0,0,0}, "\1\xCB", IF_8086}, - {I_RETF, 1, {IMMEDIATE,0,0}, "\1\xCA\30", IF_8086|IF_SW}, - {I_RETN, 0, {0,0,0}, "\1\xC3", IF_8086}, - {I_RETN, 1, {IMMEDIATE,0,0}, "\1\xC2\30", IF_8086|IF_SW}, - {I_ROL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\200", IF_8086}, - {I_ROL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\200", IF_8086}, - {I_ROL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\200\25", IF_186|IF_SB}, - {I_ROL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\200", IF_8086}, - {I_ROL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\200", IF_8086}, - {I_ROL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\200\25", IF_186|IF_SB}, - {I_ROL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\200", IF_386}, - {I_ROL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\200", IF_386}, - {I_ROL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\200\25", IF_386|IF_SB}, - {I_ROR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\201", IF_8086}, - {I_ROR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\201", IF_8086}, - {I_ROR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\201\25", IF_186|IF_SB}, - {I_ROR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\201", IF_8086}, - {I_ROR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\201", IF_8086}, - {I_ROR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\201\25", IF_186|IF_SB}, - {I_ROR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\201", IF_386}, - {I_ROR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\201", IF_386}, - {I_ROR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\201\25", IF_386|IF_SB}, - {I_RSDC, 2, {REG_SREG,MEMORY|BITS80,0}, "\301\2\x0F\x79\110", IF_486|IF_CYRIX|IF_SMM}, - {I_RSLDT, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7B\200", IF_486|IF_CYRIX|IF_SMM}, - {I_RSM, 0, {0,0,0}, "\2\x0F\xAA", IF_PENT|IF_SMM}, - {I_RSTS, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7D\200", IF_486|IF_CYRIX|IF_SMM}, - {I_SAHF, 0, {0,0,0}, "\1\x9E", IF_8086}, - {I_SALC, 0, {0,0,0}, "\1\xD6", IF_8086|IF_UNDOC}, - {I_SAR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\207", IF_8086}, - {I_SAR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\207", IF_8086}, - {I_SAR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\207\25", IF_186|IF_SB}, - {I_SAR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\207", IF_8086}, - {I_SAR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\207", IF_8086}, - {I_SAR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\207\25", IF_186|IF_SB}, - {I_SAR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\207", IF_386}, - {I_SAR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\207", IF_386}, - {I_SAR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\207\25", IF_386|IF_SB}, - {I_SBB, 2, {MEMORY,REG8,0}, "\300\1\x18\101", IF_8086|IF_SM}, - {I_SBB, 2, {REG8,REG8,0}, "\1\x18\101", IF_8086}, - {I_SBB, 2, {MEMORY,REG16,0}, "\320\300\1\x19\101", IF_8086|IF_SM}, - {I_SBB, 2, {REG16,REG16,0}, "\320\1\x19\101", IF_8086}, - {I_SBB, 2, {MEMORY,REG32,0}, "\321\300\1\x19\101", IF_386|IF_SM}, - {I_SBB, 2, {REG32,REG32,0}, "\321\1\x19\101", IF_386}, - {I_SBB, 2, {REG8,MEMORY,0}, "\301\1\x1A\110", IF_8086|IF_SM}, - {I_SBB, 2, {REG8,REG8,0}, "\1\x1A\110", IF_8086}, - {I_SBB, 2, {REG16,MEMORY,0}, "\320\301\1\x1B\110", IF_8086|IF_SM}, - {I_SBB, 2, {REG16,REG16,0}, "\320\1\x1B\110", IF_8086}, - {I_SBB, 2, {REG32,MEMORY,0}, "\321\301\1\x1B\110", IF_386|IF_SM}, - {I_SBB, 2, {REG32,REG32,0}, "\321\1\x1B\110", IF_386}, - {I_SBB, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\203\15", IF_8086}, - {I_SBB, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\203\15", IF_386}, - {I_SBB, 2, {REG_AL,IMMEDIATE,0}, "\1\x1C\21", IF_8086|IF_SM}, - {I_SBB, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x1D\31", IF_8086|IF_SM}, - {I_SBB, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x1D\41", IF_386|IF_SM}, - {I_SBB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\203\21", IF_8086|IF_SM}, - {I_SBB, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\203\131", IF_8086|IF_SM}, - {I_SBB, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\203\141", IF_386|IF_SM}, - {I_SBB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\203\21", IF_8086|IF_SM}, - {I_SBB, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\203\131", IF_8086|IF_SM}, - {I_SBB, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\203\141", IF_386|IF_SM}, - {I_SCASB, 0, {0,0,0}, "\332\1\xAE", IF_8086}, - {I_SCASD, 0, {0,0,0}, "\332\321\1\xAF", IF_386}, - {I_SCASW, 0, {0,0,0}, "\332\320\1\xAF", IF_8086}, - {I_SGDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\200", IF_286}, - {I_SHL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\204", IF_8086}, - {I_SHL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\204", IF_8086}, - {I_SHL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\204\25", IF_186|IF_SB}, - {I_SHL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\204", IF_8086}, - {I_SHL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\204", IF_8086}, - {I_SHL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\204\25", IF_186|IF_SB}, - {I_SHL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\204", IF_386}, - {I_SHL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\204", IF_386}, - {I_SHL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\204\25", IF_386|IF_SB}, - {I_SHLD, 3, {MEMORY,REG16,IMMEDIATE}, "\300\320\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHLD, 3, {REG16,REG16,IMMEDIATE}, "\320\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHLD, 3, {MEMORY,REG32,IMMEDIATE}, "\300\321\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHLD, 3, {REG32,REG32,IMMEDIATE}, "\321\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHLD, 3, {MEMORY,REG16,REG_CL}, "\300\320\2\x0F\xA5\101", IF_386|IF_SM}, - {I_SHLD, 3, {REG16,REG16,REG_CL}, "\320\2\x0F\xA5\101", IF_386}, - {I_SHLD, 3, {MEMORY,REG32,REG_CL}, "\300\321\2\x0F\xA5\101", IF_386|IF_SM}, - {I_SHLD, 3, {REG32,REG32,REG_CL}, "\321\2\x0F\xA5\101", IF_386}, - {I_SHR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\205", IF_8086}, - {I_SHR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\205", IF_8086}, - {I_SHR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\205\25", IF_186|IF_SB}, - {I_SHR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\205", IF_8086}, - {I_SHR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\205", IF_8086}, - {I_SHR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\205\25", IF_186|IF_SB}, - {I_SHR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\205", IF_386}, - {I_SHR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\205", IF_386}, - {I_SHR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\205\25", IF_386|IF_SB}, - {I_SHRD, 3, {MEMORY,REG16,IMMEDIATE}, "\300\320\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHRD, 3, {REG16,REG16,IMMEDIATE}, "\320\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHRD, 3, {MEMORY,REG32,IMMEDIATE}, "\300\321\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHRD, 3, {REG32,REG32,IMMEDIATE}, "\321\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - {I_SHRD, 3, {MEMORY,REG16,REG_CL}, "\300\320\2\x0F\xAD\101", IF_386|IF_SM}, - {I_SHRD, 3, {REG16,REG16,REG_CL}, "\320\2\x0F\xAD\101", IF_386}, - {I_SHRD, 3, {MEMORY,REG32,REG_CL}, "\300\321\2\x0F\xAD\101", IF_386|IF_SM}, - {I_SHRD, 3, {REG32,REG32,REG_CL}, "\321\2\x0F\xAD\101", IF_386}, - {I_SIDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\201", IF_286}, - {I_SLDT, 1, {MEMORY,0,0}, "\300\1\x0F\17\200", IF_286}, - {I_SLDT, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\200", IF_286}, - {I_SLDT, 1, {REG16,0,0}, "\320\1\x0F\17\200", IF_286}, - {I_SLDT, 1, {REG32,0,0}, "\321\1\x0F\17\200", IF_386}, - {I_SMI, 0, {0,0,0}, "\1\xF1", IF_386|IF_UNDOC}, - {I_SMINT, 0, {0,0,0}, "\2\x0F\x38", IF_P6|IF_CYRIX}, - {I_SMSW, 1, {MEMORY,0,0}, "\300\2\x0F\x01\204", IF_286}, - {I_SMSW, 1, {MEMORY|BITS16,0,0}, "\300\2\x0F\x01\204", IF_286}, - {I_SMSW, 1, {REG16,0,0}, "\320\2\x0F\x01\204", IF_286}, - {I_SMSW, 1, {REG32,0,0}, "\321\2\x0F\x01\204", IF_386}, - {I_STC, 0, {0,0,0}, "\1\xF9", IF_8086}, - {I_STD, 0, {0,0,0}, "\1\xFD", IF_8086}, - {I_STI, 0, {0,0,0}, "\1\xFB", IF_8086}, - {I_STOSB, 0, {0,0,0}, "\1\xAA", IF_8086}, - {I_STOSD, 0, {0,0,0}, "\321\1\xAB", IF_386}, - {I_STOSW, 0, {0,0,0}, "\320\1\xAB", IF_8086}, - {I_STR, 1, {MEMORY,0,0}, "\300\1\x0F\17\201", IF_286|IF_PROT}, - {I_STR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\201", IF_286|IF_PROT}, - {I_STR, 1, {REG16,0,0}, "\320\1\x0F\17\201", IF_286|IF_PROT}, - {I_STR, 1, {REG32,0,0}, "\321\1\x0F\17\201", IF_386|IF_PROT}, - {I_SUB, 2, {MEMORY,REG8,0}, "\300\1\x28\101", IF_8086|IF_SM}, - {I_SUB, 2, {REG8,REG8,0}, "\1\x28\101", IF_8086}, - {I_SUB, 2, {MEMORY,REG16,0}, "\320\300\1\x29\101", IF_8086|IF_SM}, - {I_SUB, 2, {REG16,REG16,0}, "\320\1\x29\101", IF_8086}, - {I_SUB, 2, {MEMORY,REG32,0}, "\321\300\1\x29\101", IF_386|IF_SM}, - {I_SUB, 2, {REG32,REG32,0}, "\321\1\x29\101", IF_386}, - {I_SUB, 2, {REG8,MEMORY,0}, "\301\1\x2A\110", IF_8086|IF_SM}, - {I_SUB, 2, {REG8,REG8,0}, "\1\x2A\110", IF_8086}, - {I_SUB, 2, {REG16,MEMORY,0}, "\320\301\1\x2B\110", IF_8086|IF_SM}, - {I_SUB, 2, {REG16,REG16,0}, "\320\1\x2B\110", IF_8086}, - {I_SUB, 2, {REG32,MEMORY,0}, "\321\301\1\x2B\110", IF_386|IF_SM}, - {I_SUB, 2, {REG32,REG32,0}, "\321\1\x2B\110", IF_386}, - {I_SUB, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\205\15", IF_8086}, - {I_SUB, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\205\15", IF_386}, - {I_SUB, 2, {REG_AL,IMMEDIATE,0}, "\1\x2C\21", IF_8086|IF_SM}, - {I_SUB, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x2D\31", IF_8086|IF_SM}, - {I_SUB, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x2D\41", IF_386|IF_SM}, - {I_SUB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\205\21", IF_8086|IF_SM}, - {I_SUB, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\205\131", IF_8086|IF_SM}, - {I_SUB, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\205\141", IF_386|IF_SM}, - {I_SUB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\205\21", IF_8086|IF_SM}, - {I_SUB, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\205\131", IF_8086|IF_SM}, - {I_SUB, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\205\141", IF_386|IF_SM}, - {I_SVDC, 2, {MEMORY|BITS80,REG_SREG,0}, "\300\2\x0F\x78\101", IF_486|IF_CYRIX|IF_SMM}, - {I_SVLDT, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7A\200", IF_486|IF_CYRIX|IF_SMM}, - {I_SVTS, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7C\200", IF_486|IF_CYRIX|IF_SMM}, - {I_SYSCALL, 0, {0,0,0}, "\2\x0F\x05", IF_P6|IF_AMD}, - {I_SYSENTER, 0, {0,0,0}, "\2\x0F\x34", IF_P6}, - {I_SYSEXIT, 0, {0,0,0}, "\2\x0F\x35", IF_P6|IF_PRIV}, - {I_SYSRET, 0, {0,0,0}, "\2\x0F\x07", IF_P6|IF_PRIV|IF_AMD}, - {I_TEST, 2, {MEMORY,REG8,0}, "\300\1\x84\101", IF_8086|IF_SM}, - {I_TEST, 2, {REG8,REG8,0}, "\1\x84\101", IF_8086}, - {I_TEST, 2, {MEMORY,REG16,0}, "\320\300\1\x85\101", IF_8086|IF_SM}, - {I_TEST, 2, {REG16,REG16,0}, "\320\1\x85\101", IF_8086}, - {I_TEST, 2, {MEMORY,REG32,0}, "\321\300\1\x85\101", IF_386|IF_SM}, - {I_TEST, 2, {REG32,REG32,0}, "\321\1\x85\101", IF_386}, - {I_TEST, 2, {REG8,MEMORY,0}, "\301\1\x84\110", IF_8086|IF_SM}, - {I_TEST, 2, {REG16,MEMORY,0}, "\320\301\1\x85\110", IF_8086|IF_SM}, - {I_TEST, 2, {REG32,MEMORY,0}, "\321\301\1\x85\110", IF_386|IF_SM}, - {I_TEST, 2, {REG_AL,IMMEDIATE,0}, "\1\xA8\21", IF_8086|IF_SM}, - {I_TEST, 2, {REG_AX,IMMEDIATE,0}, "\320\1\xA9\31", IF_8086|IF_SM}, - {I_TEST, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\xA9\41", IF_386|IF_SM}, - {I_TEST, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xF6\200\21", IF_8086|IF_SM}, - {I_TEST, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xF7\200\31", IF_8086|IF_SM}, - {I_TEST, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xF7\200\41", IF_386|IF_SM}, - {I_TEST, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\xF6\200\21", IF_8086|IF_SM}, - {I_TEST, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\1\xF7\200\31", IF_8086|IF_SM}, - {I_TEST, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\1\xF7\200\41", IF_386|IF_SM}, - {I_UD0, 0, {0,0,0}, "\2\x0F\xFF", IF_286|IF_UNDOC}, - {I_UD1, 0, {0,0,0}, "\2\x0F\xB9", IF_286|IF_UNDOC}, - {I_UD2, 0, {0,0,0}, "\2\x0F\x0B", IF_286}, - {I_UMOV, 2, {MEMORY,REG8,0}, "\300\2\x0F\x10\101", IF_386|IF_UNDOC|IF_SM}, - {I_UMOV, 2, {REG8,REG8,0}, "\2\x0F\x10\101", IF_386|IF_UNDOC}, - {I_UMOV, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\x11\101", IF_386|IF_UNDOC|IF_SM}, - {I_UMOV, 2, {REG16,REG16,0}, "\320\2\x0F\x11\101", IF_386|IF_UNDOC}, - {I_UMOV, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\x11\101", IF_386|IF_UNDOC|IF_SM}, - {I_UMOV, 2, {REG32,REG32,0}, "\321\2\x0F\x11\101", IF_386|IF_UNDOC}, - {I_UMOV, 2, {REG8,MEMORY,0}, "\301\2\x0F\x12\110", IF_386|IF_UNDOC|IF_SM}, - {I_UMOV, 2, {REG8,REG8,0}, "\2\x0F\x12\110", IF_386|IF_UNDOC}, - {I_UMOV, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x13\110", IF_386|IF_UNDOC|IF_SM}, - {I_UMOV, 2, {REG16,REG16,0}, "\320\2\x0F\x13\110", IF_386|IF_UNDOC}, - {I_UMOV, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x13\110", IF_386|IF_UNDOC|IF_SM}, - {I_UMOV, 2, {REG32,REG32,0}, "\321\2\x0F\x13\110", IF_386|IF_UNDOC}, - {I_VERR, 1, {MEMORY,0,0}, "\300\1\x0F\17\204", IF_286|IF_PROT}, - {I_VERR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\204", IF_286|IF_PROT}, - {I_VERR, 1, {REG16,0,0}, "\1\x0F\17\204", IF_286|IF_PROT}, - {I_VERW, 1, {MEMORY,0,0}, "\300\1\x0F\17\205", IF_286|IF_PROT}, - {I_VERW, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\205", IF_286|IF_PROT}, - {I_VERW, 1, {REG16,0,0}, "\1\x0F\17\205", IF_286|IF_PROT}, - {I_WAIT, 0, {0,0,0}, "\1\x9B", IF_8086}, - {I_FWAIT, 0, {0,0,0}, "\1\x9B", IF_8086}, - {I_WBINVD, 0, {0,0,0}, "\2\x0F\x09", IF_486|IF_PRIV}, - {I_WRSHR, 1, {REGMEM|BITS32,0,0}, "\321\300\2\x0F\x37\200", IF_P6|IF_CYRIX|IF_SMM}, - {I_WRMSR, 0, {0,0,0}, "\2\x0F\x30", IF_PENT|IF_PRIV}, - {I_XADD, 2, {MEMORY,REG8,0}, "\300\2\x0F\xC0\101", IF_486|IF_SM}, - {I_XADD, 2, {REG8,REG8,0}, "\2\x0F\xC0\101", IF_486}, - {I_XADD, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xC1\101", IF_486|IF_SM}, - {I_XADD, 2, {REG16,REG16,0}, "\320\2\x0F\xC1\101", IF_486}, - {I_XADD, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xC1\101", IF_486|IF_SM}, - {I_XADD, 2, {REG32,REG32,0}, "\321\2\x0F\xC1\101", IF_486}, - {I_XCHG, 2, {REG_AX,REG16,0}, "\320\11\x90", IF_8086}, - {I_XCHG, 2, {REG_EAX,REG32,0}, "\321\11\x90", IF_386}, - {I_XCHG, 2, {REG16,REG_AX,0}, "\320\10\x90", IF_8086}, - {I_XCHG, 2, {REG32,REG_EAX,0}, "\321\10\x90", IF_386}, - {I_XCHG, 2, {REG8,MEMORY,0}, "\301\1\x86\110", IF_8086|IF_SM}, - {I_XCHG, 2, {REG8,REG8,0}, "\1\x86\110", IF_8086}, - {I_XCHG, 2, {REG16,MEMORY,0}, "\320\301\1\x87\110", IF_8086|IF_SM}, - {I_XCHG, 2, {REG16,REG16,0}, "\320\1\x87\110", IF_8086}, - {I_XCHG, 2, {REG32,MEMORY,0}, "\321\301\1\x87\110", IF_386|IF_SM}, - {I_XCHG, 2, {REG32,REG32,0}, "\321\1\x87\110", IF_386}, - {I_XCHG, 2, {MEMORY,REG8,0}, "\300\1\x86\101", IF_8086|IF_SM}, - {I_XCHG, 2, {REG8,REG8,0}, "\1\x86\101", IF_8086}, - {I_XCHG, 2, {MEMORY,REG16,0}, "\320\300\1\x87\101", IF_8086|IF_SM}, - {I_XCHG, 2, {REG16,REG16,0}, "\320\1\x87\101", IF_8086}, - {I_XCHG, 2, {MEMORY,REG32,0}, "\321\300\1\x87\101", IF_386|IF_SM}, - {I_XCHG, 2, {REG32,REG32,0}, "\321\1\x87\101", IF_386}, - {I_XLATB, 0, {0,0,0}, "\1\xD7", IF_8086}, - {I_XLAT, 0, {0,0,0}, "\1\xD7", IF_8086}, - {I_XOR, 2, {MEMORY,REG8,0}, "\300\1\x30\101", IF_8086|IF_SM}, - {I_XOR, 2, {REG8,REG8,0}, "\1\x30\101", IF_8086}, - {I_XOR, 2, {MEMORY,REG16,0}, "\320\300\1\x31\101", IF_8086|IF_SM}, - {I_XOR, 2, {REG16,REG16,0}, "\320\1\x31\101", IF_8086}, - {I_XOR, 2, {MEMORY,REG32,0}, "\321\300\1\x31\101", IF_386|IF_SM}, - {I_XOR, 2, {REG32,REG32,0}, "\321\1\x31\101", IF_386}, - {I_XOR, 2, {REG8,MEMORY,0}, "\301\1\x32\110", IF_8086|IF_SM}, - {I_XOR, 2, {REG8,REG8,0}, "\1\x32\110", IF_8086}, - {I_XOR, 2, {REG16,MEMORY,0}, "\320\301\1\x33\110", IF_8086|IF_SM}, - {I_XOR, 2, {REG16,REG16,0}, "\320\1\x33\110", IF_8086}, - {I_XOR, 2, {REG32,MEMORY,0}, "\321\301\1\x33\110", IF_386|IF_SM}, - {I_XOR, 2, {REG32,REG32,0}, "\321\1\x33\110", IF_386}, - {I_XOR, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\206\15", IF_8086}, - {I_XOR, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\206\15", IF_386}, - {I_XOR, 2, {REG_AL,IMMEDIATE,0}, "\1\x34\21", IF_8086|IF_SM}, - {I_XOR, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x35\31", IF_8086|IF_SM}, - {I_XOR, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x35\41", IF_386|IF_SM}, - {I_XOR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\206\21", IF_8086|IF_SM}, - {I_XOR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\206\131", IF_8086|IF_SM}, - {I_XOR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\206\141", IF_386|IF_SM}, - {I_XOR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\206\21", IF_8086|IF_SM}, - {I_XOR, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\206\131", IF_8086|IF_SM}, - {I_XOR, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\206\141", IF_386|IF_SM}, - {I_XSTORE, 0, {0,0,0}, "\3\x0F\xA7\xC0", IF_P6|IF_CYRIX}, - {I_CMOVcc, 2, {REG16,MEMORY,0}, "\320\301\1\x0F\330\x40\110", IF_P6|IF_SM}, - {I_CMOVcc, 2, {REG16,REG16,0}, "\320\1\x0F\330\x40\110", IF_P6}, - {I_CMOVcc, 2, {REG32,MEMORY,0}, "\321\301\1\x0F\330\x40\110", IF_P6|IF_SM}, - {I_CMOVcc, 2, {REG32,REG32,0}, "\321\1\x0F\330\x40\110", IF_P6}, - {I_Jcc, 1, {IMMEDIATE|NEAR,0,0}, "\322\1\x0F\330\x80\64", IF_386}, - {I_Jcc, 1, {IMMEDIATE|BITS16|NEAR,0,0}, "\320\1\x0F\330\x80\64", IF_386}, - {I_Jcc, 1, {IMMEDIATE|BITS32|NEAR,0,0}, "\321\1\x0F\330\x80\64", IF_386}, - {I_Jcc, 1, {IMMEDIATE,0,0}, "\330\x70\50", IF_8086}, - {I_SETcc, 1, {MEMORY,0,0}, "\300\1\x0F\330\x90\200", IF_386|IF_SB}, - {I_SETcc, 1, {REG8,0,0}, "\300\1\x0F\330\x90\200", IF_386}, - {I_ADDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - {I_ADDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - {I_ADDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - {I_ADDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - {I_ANDNPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x55\110", IF_KATMAI|IF_SSE}, - {I_ANDNPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x55\110", IF_KATMAI|IF_SSE}, - {I_ANDPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x54\110", IF_KATMAI|IF_SSE}, - {I_ANDPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x54\110", IF_KATMAI|IF_SSE}, - {I_CMPEQPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - {I_CMPEQPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - {I_CMPEQSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - {I_CMPEQSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - {I_CMPLEPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - {I_CMPLEPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - {I_CMPLESS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - {I_CMPLESS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - {I_CMPLTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - {I_CMPLTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - {I_CMPLTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - {I_CMPLTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - {I_CMPNEQPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - {I_CMPNEQPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - {I_CMPNEQSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - {I_CMPNEQSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - {I_CMPNLEPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - {I_CMPNLEPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - {I_CMPNLESS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - {I_CMPNLESS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - {I_CMPNLTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - {I_CMPNLTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - {I_CMPNLTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - {I_CMPNLTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - {I_CMPORDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - {I_CMPORDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - {I_CMPORDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - {I_CMPORDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - {I_CMPUNORDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - {I_CMPUNORDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - {I_CMPUNORDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - {I_CMPUNORDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - {I_CMPPS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - {I_CMPPS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - {I_CMPSS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\333\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - {I_CMPSS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\333\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - {I_COMISS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x2F\110", IF_KATMAI|IF_SSE}, - {I_COMISS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x2F\110", IF_KATMAI|IF_SSE}, - {I_CVTPI2PS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_MMX}, - {I_CVTPI2PS, 2, {XMMREG,MMXREG,0}, "\331\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_MMX}, - {I_CVTPS2PI, 2, {MMXREG,MEMORY,0}, "\301\331\2\x0F\x2D\110", IF_KATMAI|IF_SSE|IF_MMX}, - {I_CVTPS2PI, 2, {MMXREG,XMMREG,0}, "\331\2\x0F\x2D\110", IF_KATMAI|IF_SSE|IF_MMX}, - {I_CVTSI2SS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_SD|IF_AR1}, - {I_CVTSI2SS, 2, {XMMREG,REG32,0}, "\333\2\x0F\x2A\110", IF_KATMAI|IF_SSE}, - {I_CVTSS2SI, 2, {REG32,MEMORY,0}, "\301\333\2\x0F\x2D\110", IF_KATMAI|IF_SSE}, - {I_CVTSS2SI, 2, {REG32,XMMREG,0}, "\333\2\x0F\x2D\110", IF_KATMAI|IF_SSE}, - {I_CVTTPS2PI, 2, {MMXREG,MEMORY,0}, "\301\331\2\x0F\x2C\110", IF_KATMAI|IF_SSE|IF_MMX}, - {I_CVTTPS2PI, 2, {MMXREG,XMMREG,0}, "\331\2\x0F\x2C\110", IF_KATMAI|IF_SSE|IF_MMX}, - {I_CVTTSS2SI, 2, {REG32,MEMORY,0}, "\301\333\2\x0F\x2C\110", IF_KATMAI|IF_SSE}, - {I_CVTTSS2SI, 2, {REG32,XMMREG,0}, "\333\2\x0F\x2C\110", IF_KATMAI|IF_SSE}, - {I_DIVPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - {I_DIVPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - {I_DIVSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - {I_DIVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - {I_LDMXCSR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\202", IF_KATMAI|IF_SSE|IF_SD}, - {I_MAXPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - {I_MAXPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - {I_MAXSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - {I_MAXSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - {I_MINPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - {I_MINPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - {I_MINSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - {I_MINSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - {I_MOVAPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x28\110", IF_KATMAI|IF_SSE}, - {I_MOVAPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x29\101", IF_KATMAI|IF_SSE}, - {I_MOVAPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x28\110", IF_KATMAI|IF_SSE}, - {I_MOVAPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x29\101", IF_KATMAI|IF_SSE}, - {I_MOVHPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x16\110", IF_KATMAI|IF_SSE}, - {I_MOVHPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x17\101", IF_KATMAI|IF_SSE}, - {I_MOVLHPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x16\110", IF_KATMAI|IF_SSE}, - {I_MOVLPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x12\110", IF_KATMAI|IF_SSE}, - {I_MOVLPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x13\101", IF_KATMAI|IF_SSE}, - {I_MOVHLPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x12\110", IF_KATMAI|IF_SSE}, - {I_MOVMSKPS, 2, {REG32,XMMREG,0}, "\2\x0F\x50\110", IF_KATMAI|IF_SSE}, - {I_MOVNTPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x2B\101", IF_KATMAI|IF_SSE}, - {I_MOVSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - {I_MOVSS, 2, {MEMORY,XMMREG,0}, "\300\333\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - {I_MOVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - {I_MOVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - {I_MOVUPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - {I_MOVUPS, 2, {MEMORY,XMMREG,0}, "\300\331\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - {I_MOVUPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - {I_MOVUPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - {I_MULPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - {I_MULPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - {I_MULSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - {I_MULSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - {I_ORPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x56\110", IF_KATMAI|IF_SSE}, - {I_ORPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x56\110", IF_KATMAI|IF_SSE}, - {I_RCPPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - {I_RCPPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - {I_RCPSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - {I_RCPSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - {I_RSQRTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - {I_RSQRTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - {I_RSQRTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - {I_RSQRTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - {I_SHUFPS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\2\x0F\xC6\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - {I_SHUFPS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\2\x0F\xC6\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - {I_SQRTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - {I_SQRTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - {I_SQRTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - {I_SQRTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - {I_STMXCSR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\203", IF_KATMAI|IF_SSE|IF_SD}, - {I_SUBPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - {I_SUBPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - {I_SUBSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - {I_SUBSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - {I_UCOMISS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x2E\110", IF_KATMAI|IF_SSE}, - {I_UCOMISS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x2E\110", IF_KATMAI|IF_SSE}, - {I_UNPCKHPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x15\110", IF_KATMAI|IF_SSE}, - {I_UNPCKHPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x15\110", IF_KATMAI|IF_SSE}, - {I_UNPCKLPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x14\110", IF_KATMAI|IF_SSE}, - {I_UNPCKLPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x14\110", IF_KATMAI|IF_SSE}, - {I_XORPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x57\110", IF_KATMAI|IF_SSE}, - {I_XORPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x57\110", IF_KATMAI|IF_SSE}, - {I_FXRSTOR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\201", IF_P6|IF_SSE|IF_FPU}, - {I_FXSAVE, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\200", IF_P6|IF_SSE|IF_FPU}, - {I_PREFETCHNTA, 1, {MEMORY,0,0}, "\300\2\x0F\x18\200", IF_KATMAI}, - {I_PREFETCHT0, 1, {MEMORY,0,0}, "\300\2\x0F\x18\201", IF_KATMAI}, - {I_PREFETCHT1, 1, {MEMORY,0,0}, "\300\2\x0F\x18\202", IF_KATMAI}, - {I_PREFETCHT2, 1, {MEMORY,0,0}, "\300\2\x0F\x18\203", IF_KATMAI}, - {I_SFENCE, 0, {0,0,0}, "\3\x0F\xAE\xF8", IF_KATMAI}, - {I_MASKMOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF7\110", IF_KATMAI|IF_MMX}, - {I_MOVNTQ, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\xE7\101", IF_KATMAI|IF_MMX|IF_SM}, - {I_PAVGB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE0\110", IF_KATMAI|IF_MMX}, - {I_PAVGB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE0\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PAVGW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE3\110", IF_KATMAI|IF_MMX}, - {I_PAVGW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE3\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PEXTRW, 3, {REG32,MMXREG,IMMEDIATE}, "\2\x0F\xC5\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - {I_PINSRW, 3, {MMXREG,REG16,IMMEDIATE}, "\2\x0F\xC4\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - {I_PINSRW, 3, {MMXREG,MEMORY,IMMEDIATE}, "\301\2\x0F\xC4\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - {I_PMAXSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEE\110", IF_KATMAI|IF_MMX}, - {I_PMAXSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEE\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PMAXUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDE\110", IF_KATMAI|IF_MMX}, - {I_PMAXUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDE\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PMINSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEA\110", IF_KATMAI|IF_MMX}, - {I_PMINSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEA\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PMINUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDA\110", IF_KATMAI|IF_MMX}, - {I_PMINUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDA\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PMOVMSKB, 2, {REG32,MMXREG,0}, "\2\x0F\xD7\110", IF_KATMAI|IF_MMX}, - {I_PMULHUW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE4\110", IF_KATMAI|IF_MMX}, - {I_PMULHUW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE4\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PSADBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF6\110", IF_KATMAI|IF_MMX}, - {I_PSADBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF6\110", IF_KATMAI|IF_MMX|IF_SM}, - {I_PSHUFW, 3, {MMXREG,MMXREG,IMMEDIATE}, "\2\x0F\x70\110\22", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - {I_PSHUFW, 3, {MMXREG,MEMORY,IMMEDIATE}, "\301\2\x0F\x70\110\22", IF_KATMAI|IF_MMX|IF_SM2|IF_SB|IF_AR2}, - {I_PF2IW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x1C", IF_PENT|IF_3DNOW|IF_SM}, - {I_PF2IW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x1C", IF_PENT|IF_3DNOW}, - {I_PFNACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x8A", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFNACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x8A", IF_PENT|IF_3DNOW}, - {I_PFPNACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x8E", IF_PENT|IF_3DNOW|IF_SM}, - {I_PFPNACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x8E", IF_PENT|IF_3DNOW}, - {I_PI2FW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x0C", IF_PENT|IF_3DNOW|IF_SM}, - {I_PI2FW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x0C", IF_PENT|IF_3DNOW}, - {I_PSWAPD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xBB", IF_PENT|IF_3DNOW|IF_SM}, - {I_PSWAPD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xBB", IF_PENT|IF_3DNOW}, - {I_MASKMOVDQU, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF7\110", IF_WILLAMETTE|IF_SSE2}, - {I_CLFLUSH, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\207", IF_WILLAMETTE|IF_SSE2}, - {I_MOVNTDQ, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\xE7\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVNTI, 2, {MEMORY,REG32,0}, "\300\2\x0F\xC3\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVNTPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x2B\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PAUSE, 0, {0,0,0}, "\333\1\x90", IF_WILLAMETTE|IF_SSE2}, - {I_LFENCE, 0, {0,0,0}, "\3\x0F\xAE\xE8", IF_WILLAMETTE|IF_SSE2}, - {I_MFENCE, 0, {0,0,0}, "\3\x0F\xAE\xF0", IF_WILLAMETTE|IF_SSE2}, - {I_MOVD, 2, {XMMREG,REG32,0}, "\3\x66\x0F\x6E\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVD, 2, {REG32,XMMREG,0}, "\3\x66\x0F\x7E\101", IF_WILLAMETTE|IF_SSE2}, - {I_MOVD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x7E\101", IF_WILLAMETTE|IF_SSE2}, - {I_MOVD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6E\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVDQA, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVDQA, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x7F\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVDQA, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVDQA, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVDQU, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVDQU, 2, {MEMORY,XMMREG,0}, "\333\300\2\x0F\x7F\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVDQU, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVDQU, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x7F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVDQ2Q, 2, {MMXREG,XMMREG,0}, "\3\xF2\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVQ, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x7E\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVQ, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\xD6\101", IF_WILLAMETTE|IF_SSE2}, - {I_MOVQ, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x7E\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVQ2DQ, 2, {XMMREG,MMXREG,0}, "\333\2\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, - {I_PACKSSWB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x63\110", IF_WILLAMETTE|IF_SSE2}, - {I_PACKSSWB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x63\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PACKSSDW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6B\110", IF_WILLAMETTE|IF_SSE2}, - {I_PACKSSDW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PACKUSWB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x67\110", IF_WILLAMETTE|IF_SSE2}, - {I_PACKUSWB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x67\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFC\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFD\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFD\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFE\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEC\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xED\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xED\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDUSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDUSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDC\110", IF_WILLAMETTE|IF_SSE2}, - {I_PADDUSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDD\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PADDUSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDD\110", IF_WILLAMETTE|IF_SSE2}, - {I_PAND, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDB\110", IF_WILLAMETTE|IF_SSE2}, - {I_PAND, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PANDN, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDF\110", IF_WILLAMETTE|IF_SSE2}, - {I_PANDN, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDF\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PAVGB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE0\110", IF_WILLAMETTE|IF_SSE2}, - {I_PAVGB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE0\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PAVGW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE3\110", IF_WILLAMETTE|IF_SSE2}, - {I_PAVGW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PCMPEQB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x74\110", IF_WILLAMETTE|IF_SSE2}, - {I_PCMPEQB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x74\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PCMPEQW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x75\110", IF_WILLAMETTE|IF_SSE2}, - {I_PCMPEQW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x75\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PCMPEQD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x76\110", IF_WILLAMETTE|IF_SSE2}, - {I_PCMPEQD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x76\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PCMPGTB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x64\110", IF_WILLAMETTE|IF_SSE2}, - {I_PCMPGTB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x64\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PCMPGTW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x65\110", IF_WILLAMETTE|IF_SSE2}, - {I_PCMPGTW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x65\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PCMPGTD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x66\110", IF_WILLAMETTE|IF_SSE2}, - {I_PCMPGTD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x66\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PEXTRW, 3, {REG32,XMMREG,IMMEDIATE}, "\3\x66\x0F\xC5\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_PINSRW, 3, {XMMREG,REG16,IMMEDIATE}, "\3\x66\x0F\xC4\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_PINSRW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\xC4\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_PMADDWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMADDWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF5\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMAXSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEE\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMAXSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMAXUB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDE\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMAXUB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMINSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEA\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMINSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMINUB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDA\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMINUB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMOVMSKB, 2, {REG32,XMMREG,0}, "\3\x66\x0F\xD7\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMULHUW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE4\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMULHUW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMULHW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMULHW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE5\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMULLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMULLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD5\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMULUDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMULUDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PMULUDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2}, - {I_PMULUDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_POR, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_POR, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEB\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSADBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF6\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSADBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSHUFD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\x66\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_PSHUFD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - {I_PSHUFHW, 3, {XMMREG,XMMREG,IMMEDIATE}, "\333\2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_PSHUFHW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\333\2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - {I_PSHUFLW, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\xF2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_PSHUFLW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\xF2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - {I_PSLLDQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\207\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSLLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSLLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF1\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSLLW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSLLD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSLLD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF2\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSLLD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSLLQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSLLQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF3\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSLLQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSRAW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSRAW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE1\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSRAW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\204\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSRAD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSRAD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE2\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSRAD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\204\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSRLDQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\203\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSRLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSRLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD1\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSRLW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSRLD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSRLD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD2\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSRLD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSRLQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSRLQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD3\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSRLQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - {I_PSUBB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF8\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF9\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFA\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE8\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE9\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBUSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBUSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD8\110", IF_WILLAMETTE|IF_SSE2}, - {I_PSUBUSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PSUBUSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD9\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKHBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x68\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKHBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x68\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKHWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x69\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKHWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x69\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKHDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6A\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKHDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6A\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKHQDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6D\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKHQDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6D\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKLBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x60\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKLBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x60\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKLWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x61\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKLWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x61\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKLDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x62\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PUNPCKLDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x62\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKLQDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6C\110", IF_WILLAMETTE|IF_SSE2}, - {I_PUNPCKLQDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6C\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PXOR, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEF\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_PXOR, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEF\110", IF_WILLAMETTE|IF_SSE2}, - {I_ADDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, - {I_ADDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x58\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_ADDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, - {I_ADDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, - {I_ANDNPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x55\110", IF_WILLAMETTE|IF_SSE2}, - {I_ANDNPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x55\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_ANDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x54\110", IF_WILLAMETTE|IF_SSE2}, - {I_ANDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x54\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPEQPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPEQPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, - {I_CMPEQSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, - {I_CMPEQSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, - {I_CMPLEPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPLEPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, - {I_CMPLESD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, - {I_CMPLESD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, - {I_CMPLTPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPLTPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, - {I_CMPLTSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, - {I_CMPLTSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNEQPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPNEQPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNEQSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNEQSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNLEPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPNLEPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNLESD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNLESD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNLTPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPNLTPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNLTSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, - {I_CMPNLTSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, - {I_CMPORDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPORDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, - {I_CMPORDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, - {I_CMPORDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, - {I_CMPUNORDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CMPUNORDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, - {I_CMPUNORDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, - {I_CMPUNORDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, - {I_CMPPD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\3\x66\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_CMPPD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\3\x66\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - {I_CMPSD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\3\xF2\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_CMPSD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\3\xF2\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_COMISD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x2F\110", IF_WILLAMETTE|IF_SSE2}, - {I_COMISD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x2F\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTDQ2PD, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTDQ2PD, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTDQ2PS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTDQ2PS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CVTPD2DQ, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPD2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CVTPD2PI, 2, {MMXREG,XMMREG,0}, "\3\x66\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPD2PI, 2, {MMXREG,MEMORY,0}, "\301\3\x66\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPD2PS, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPD2PS, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CVTPI2PD, 2, {XMMREG,MMXREG,0}, "\3\x66\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPI2PD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPS2DQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPS2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CVTPS2PD, 2, {XMMREG,XMMREG,0}, "\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTPS2PD, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSD2SI, 2, {REG32,XMMREG,0}, "\3\xF2\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSD2SI, 2, {REG32,MEMORY,0}, "\301\3\xF2\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSD2SS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSD2SS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSI2SD, 2, {XMMREG,REG32,0}, "\3\xF2\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSI2SD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSS2SD, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTSS2SD, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTTPD2PI, 2, {MMXREG,XMMREG,0}, "\3\x66\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTTPD2PI, 2, {MMXREG,MEMORY,0}, "\301\3\x66\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTTPD2DQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTTPD2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CVTTPS2DQ, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTTPS2DQ, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_CVTTSD2SI, 2, {REG32,XMMREG,0}, "\3\xF2\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - {I_CVTTSD2SI, 2, {REG32,MEMORY,0}, "\301\3\xF2\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - {I_DIVPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, - {I_DIVPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_DIVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, - {I_DIVSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, - {I_MAXPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MAXPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MAXSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MAXSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, - {I_MINPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, - {I_MINPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MINSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, - {I_MINSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVAPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x28\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVAPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x29\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVAPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x29\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVAPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x28\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVHPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x17\101", IF_WILLAMETTE|IF_SSE2}, - {I_MOVHPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x16\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVLPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x13\101", IF_WILLAMETTE|IF_SSE2}, - {I_MOVLPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x12\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVMSKPD, 2, {REG32,XMMREG,0}, "\3\x66\x0F\x50\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x11\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVSD, 2, {MEMORY,XMMREG,0}, "\300\3\xF2\x0F\x11\101", IF_WILLAMETTE|IF_SSE2}, - {I_MOVSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVUPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVUPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x11\110", IF_WILLAMETTE|IF_SSE2}, - {I_MOVUPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x11\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MOVUPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x10\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MULPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, - {I_MULPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x59\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_MULSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, - {I_MULSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, - {I_ORPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x56\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_ORPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x56\110", IF_WILLAMETTE|IF_SSE2}, - {I_SHUFPD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\x66\x0F\xC6\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - {I_SHUFPD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\xC6\110\26", IF_WILLAMETTE|IF_SSE2|IF_SM|IF_SB|IF_AR2}, - {I_SQRTPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, - {I_SQRTPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x51\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_SQRTSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, - {I_SQRTSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, - {I_SUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, - {I_SUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_SUBSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, - {I_SUBSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, - {I_UCOMISD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x2E\110", IF_WILLAMETTE|IF_SSE2}, - {I_UCOMISD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x2E\110", IF_WILLAMETTE|IF_SSE2}, - {I_UNPCKHPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x15\110", IF_WILLAMETTE|IF_SSE2}, - {I_UNPCKHPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x15\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_UNPCKLPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x14\110", IF_WILLAMETTE|IF_SSE2}, - {I_UNPCKLPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x14\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_XORPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x57\110", IF_WILLAMETTE|IF_SSE2}, - {I_XORPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x57\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - {I_ADDSUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD0\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - {I_ADDSUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD0\110", IF_PRESCOTT|IF_SSE3}, - {I_ADDSUBPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\xD0\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - {I_ADDSUBPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\xD0\110", IF_PRESCOTT|IF_SSE3}, - {I_HADDPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x7C\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - {I_HADDPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7C\110", IF_PRESCOTT|IF_SSE3}, - {I_HADDPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x7C\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - {I_HADDPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x7C\110", IF_PRESCOTT|IF_SSE3}, - {I_HSUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x7D\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - {I_HSUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7D\110", IF_PRESCOTT|IF_SSE3}, - {I_HSUBPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x7D\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - {I_HSUBPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x7D\110", IF_PRESCOTT|IF_SSE3}, - {I_LDDQU, 2, {XMMREG,MEMORY,0}, "\3\xF2\x0F\xF0\110", IF_PRESCOTT|IF_SSE3}, - {I_MOVDDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - {I_MOVDDUP, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - {I_MOVSHDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF3\x0F\x16\110", IF_PRESCOTT|IF_SSE3}, - {I_MOVSHDUP, 2, {XMMREG,XMMREG,0}, "\3\xF3\x0F\x16\110", IF_PRESCOTT|IF_SSE3}, - {I_MOVSLDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF3\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - {I_MOVSLDUP, 2, {XMMREG,XMMREG,0}, "\3\xF3\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - ITEMPLATE_END + /* 0*/ {I_AAA, 0, {0,0,0}, "\1\x37", IF_8086}, + /* 1*/ {I_AAD, 0, {0,0,0}, "\2\xD5\x0A", IF_8086}, + /* 2*/ {I_AAD, 1, {IMMEDIATE,0,0}, "\1\xD5\24", IF_8086|IF_SB}, + /* 3*/ {I_AAM, 0, {0,0,0}, "\2\xD4\x0A", IF_8086}, + /* 4*/ {I_AAM, 1, {IMMEDIATE,0,0}, "\1\xD4\24", IF_8086|IF_SB}, + /* 5*/ {I_AAS, 0, {0,0,0}, "\1\x3F", IF_8086}, + /* 6*/ {I_ADC, 2, {MEMORY,REG8,0}, "\300\1\x10\101", IF_8086|IF_SM}, + /* 7*/ {I_ADC, 2, {REG8,REG8,0}, "\1\x10\101", IF_8086}, + /* 8*/ {I_ADC, 2, {MEMORY,REG16,0}, "\320\300\1\x11\101", IF_8086|IF_SM}, + /* 9*/ {I_ADC, 2, {REG16,REG16,0}, "\320\1\x11\101", IF_8086}, + /* 10*/ {I_ADC, 2, {MEMORY,REG32,0}, "\321\300\1\x11\101", IF_386|IF_SM}, + /* 11*/ {I_ADC, 2, {REG32,REG32,0}, "\321\1\x11\101", IF_386}, + /* 12*/ {I_ADC, 2, {REG8,MEMORY,0}, "\301\1\x12\110", IF_8086|IF_SM}, + /* 13*/ {I_ADC, 2, {REG8,REG8,0}, "\1\x12\110", IF_8086}, + /* 14*/ {I_ADC, 2, {REG16,MEMORY,0}, "\320\301\1\x13\110", IF_8086|IF_SM}, + /* 15*/ {I_ADC, 2, {REG16,REG16,0}, "\320\1\x13\110", IF_8086}, + /* 16*/ {I_ADC, 2, {REG32,MEMORY,0}, "\321\301\1\x13\110", IF_386|IF_SM}, + /* 17*/ {I_ADC, 2, {REG32,REG32,0}, "\321\1\x13\110", IF_386}, + /* 18*/ {I_ADC, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\202\15", IF_8086}, + /* 19*/ {I_ADC, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\202\15", IF_386}, + /* 20*/ {I_ADC, 2, {REG_AL,IMMEDIATE,0}, "\1\x14\21", IF_8086|IF_SM}, + /* 21*/ {I_ADC, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x15\31", IF_8086|IF_SM}, + /* 22*/ {I_ADC, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x15\41", IF_386|IF_SM}, + /* 23*/ {I_ADC, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\202\21", IF_8086|IF_SM}, + /* 24*/ {I_ADC, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\202\131", IF_8086|IF_SM}, + /* 25*/ {I_ADC, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\202\141", IF_386|IF_SM}, + /* 26*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\202\21", IF_8086|IF_SM}, + /* 27*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\202\131", IF_8086|IF_SM}, + /* 28*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\202\141", IF_386|IF_SM}, + /* 29*/ {I_ADD, 2, {MEMORY,REG8,0}, "\300\17\101", IF_8086|IF_SM}, + /* 30*/ {I_ADD, 2, {REG8,REG8,0}, "\17\101", IF_8086}, + /* 31*/ {I_ADD, 2, {MEMORY,REG16,0}, "\320\300\1\x01\101", IF_8086|IF_SM}, + /* 32*/ {I_ADD, 2, {REG16,REG16,0}, "\320\1\x01\101", IF_8086}, + /* 33*/ {I_ADD, 2, {MEMORY,REG32,0}, "\321\300\1\x01\101", IF_386|IF_SM}, + /* 34*/ {I_ADD, 2, {REG32,REG32,0}, "\321\1\x01\101", IF_386}, + /* 35*/ {I_ADD, 2, {REG8,MEMORY,0}, "\301\1\x02\110", IF_8086|IF_SM}, + /* 36*/ {I_ADD, 2, {REG8,REG8,0}, "\1\x02\110", IF_8086}, + /* 37*/ {I_ADD, 2, {REG16,MEMORY,0}, "\320\301\1\x03\110", IF_8086|IF_SM}, + /* 38*/ {I_ADD, 2, {REG16,REG16,0}, "\320\1\x03\110", IF_8086}, + /* 39*/ {I_ADD, 2, {REG32,MEMORY,0}, "\321\301\1\x03\110", IF_386|IF_SM}, + /* 40*/ {I_ADD, 2, {REG32,REG32,0}, "\321\1\x03\110", IF_386}, + /* 41*/ {I_ADD, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\200\15", IF_8086}, + /* 42*/ {I_ADD, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\200\15", IF_386}, + /* 43*/ {I_ADD, 2, {REG_AL,IMMEDIATE,0}, "\1\x04\21", IF_8086|IF_SM}, + /* 44*/ {I_ADD, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x05\31", IF_8086|IF_SM}, + /* 45*/ {I_ADD, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x05\41", IF_386|IF_SM}, + /* 46*/ {I_ADD, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\200\21", IF_8086|IF_SM}, + /* 47*/ {I_ADD, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\200\131", IF_8086|IF_SM}, + /* 48*/ {I_ADD, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\200\141", IF_386|IF_SM}, + /* 49*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\200\21", IF_8086|IF_SM}, + /* 50*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\200\131", IF_8086|IF_SM}, + /* 51*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\200\141", IF_386|IF_SM}, + /* 52*/ {I_AND, 2, {MEMORY,REG8,0}, "\300\1\x20\101", IF_8086|IF_SM}, + /* 53*/ {I_AND, 2, {REG8,REG8,0}, "\1\x20\101", IF_8086}, + /* 54*/ {I_AND, 2, {MEMORY,REG16,0}, "\320\300\1\x21\101", IF_8086|IF_SM}, + /* 55*/ {I_AND, 2, {REG16,REG16,0}, "\320\1\x21\101", IF_8086}, + /* 56*/ {I_AND, 2, {MEMORY,REG32,0}, "\321\300\1\x21\101", IF_386|IF_SM}, + /* 57*/ {I_AND, 2, {REG32,REG32,0}, "\321\1\x21\101", IF_386}, + /* 58*/ {I_AND, 2, {REG8,MEMORY,0}, "\301\1\x22\110", IF_8086|IF_SM}, + /* 59*/ {I_AND, 2, {REG8,REG8,0}, "\1\x22\110", IF_8086}, + /* 60*/ {I_AND, 2, {REG16,MEMORY,0}, "\320\301\1\x23\110", IF_8086|IF_SM}, + /* 61*/ {I_AND, 2, {REG16,REG16,0}, "\320\1\x23\110", IF_8086}, + /* 62*/ {I_AND, 2, {REG32,MEMORY,0}, "\321\301\1\x23\110", IF_386|IF_SM}, + /* 63*/ {I_AND, 2, {REG32,REG32,0}, "\321\1\x23\110", IF_386}, + /* 64*/ {I_AND, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\204\15", IF_8086}, + /* 65*/ {I_AND, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\204\15", IF_386}, + /* 66*/ {I_AND, 2, {REG_AL,IMMEDIATE,0}, "\1\x24\21", IF_8086|IF_SM}, + /* 67*/ {I_AND, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x25\31", IF_8086|IF_SM}, + /* 68*/ {I_AND, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x25\41", IF_386|IF_SM}, + /* 69*/ {I_AND, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\204\21", IF_8086|IF_SM}, + /* 70*/ {I_AND, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\204\131", IF_8086|IF_SM}, + /* 71*/ {I_AND, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\204\141", IF_386|IF_SM}, + /* 72*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\204\21", IF_8086|IF_SM}, + /* 73*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\204\131", IF_8086|IF_SM}, + /* 74*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\204\141", IF_386|IF_SM}, + /* 75*/ {I_ARPL, 2, {MEMORY,REG16,0}, "\300\1\x63\101", IF_286|IF_PROT|IF_SM}, + /* 76*/ {I_ARPL, 2, {REG16,REG16,0}, "\1\x63\101", IF_286|IF_PROT}, + /* 77*/ {I_BOUND, 2, {REG16,MEMORY,0}, "\320\301\1\x62\110", IF_186}, + /* 78*/ {I_BOUND, 2, {REG32,MEMORY,0}, "\321\301\1\x62\110", IF_386}, + /* 79*/ {I_BSF, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBC\110", IF_386|IF_SM}, + /* 80*/ {I_BSF, 2, {REG16,REG16,0}, "\320\2\x0F\xBC\110", IF_386}, + /* 81*/ {I_BSF, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xBC\110", IF_386|IF_SM}, + /* 82*/ {I_BSF, 2, {REG32,REG32,0}, "\321\2\x0F\xBC\110", IF_386}, + /* 83*/ {I_BSR, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBD\110", IF_386|IF_SM}, + /* 84*/ {I_BSR, 2, {REG16,REG16,0}, "\320\2\x0F\xBD\110", IF_386}, + /* 85*/ {I_BSR, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xBD\110", IF_386|IF_SM}, + /* 86*/ {I_BSR, 2, {REG32,REG32,0}, "\321\2\x0F\xBD\110", IF_386}, + /* 87*/ {I_BSWAP, 1, {REG32,0,0}, "\321\1\x0F\10\xC8", IF_486}, + /* 88*/ {I_BT, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xA3\101", IF_386|IF_SM}, + /* 89*/ {I_BT, 2, {REG16,REG16,0}, "\320\2\x0F\xA3\101", IF_386}, + /* 90*/ {I_BT, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xA3\101", IF_386|IF_SM}, + /* 91*/ {I_BT, 2, {REG32,REG32,0}, "\321\2\x0F\xA3\101", IF_386}, + /* 92*/ {I_BT, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\204\25", IF_386|IF_SB}, + /* 93*/ {I_BT, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\204\25", IF_386|IF_SB}, + /* 94*/ {I_BTC, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xBB\101", IF_386|IF_SM}, + /* 95*/ {I_BTC, 2, {REG16,REG16,0}, "\320\2\x0F\xBB\101", IF_386}, + /* 96*/ {I_BTC, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xBB\101", IF_386|IF_SM}, + /* 97*/ {I_BTC, 2, {REG32,REG32,0}, "\321\2\x0F\xBB\101", IF_386}, + /* 98*/ {I_BTC, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\207\25", IF_386|IF_SB}, + /* 99*/ {I_BTC, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\207\25", IF_386|IF_SB}, + /* 100*/ {I_BTR, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xB3\101", IF_386|IF_SM}, + /* 101*/ {I_BTR, 2, {REG16,REG16,0}, "\320\2\x0F\xB3\101", IF_386}, + /* 102*/ {I_BTR, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xB3\101", IF_386|IF_SM}, + /* 103*/ {I_BTR, 2, {REG32,REG32,0}, "\321\2\x0F\xB3\101", IF_386}, + /* 104*/ {I_BTR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\206\25", IF_386|IF_SB}, + /* 105*/ {I_BTR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\206\25", IF_386|IF_SB}, + /* 106*/ {I_BTS, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xAB\101", IF_386|IF_SM}, + /* 107*/ {I_BTS, 2, {REG16,REG16,0}, "\320\2\x0F\xAB\101", IF_386}, + /* 108*/ {I_BTS, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xAB\101", IF_386|IF_SM}, + /* 109*/ {I_BTS, 2, {REG32,REG32,0}, "\321\2\x0F\xAB\101", IF_386}, + /* 110*/ {I_BTS, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\205\25", IF_386|IF_SB}, + /* 111*/ {I_BTS, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\205\25", IF_386|IF_SB}, + /* 112*/ {I_CALL, 1, {IMMEDIATE,0,0}, "\322\1\xE8\64", IF_8086}, + /* 113*/ {I_CALL, 1, {IMMEDIATE|NEAR,0,0}, "\322\1\xE8\64", IF_8086}, + /* 114*/ {I_CALL, 1, {IMMEDIATE|BITS16,0,0}, "\320\1\xE8\64", IF_8086}, + /* 115*/ {I_CALL, 1, {IMMEDIATE|BITS16|NEAR,0,0}, "\320\1\xE8\64", IF_8086}, + /* 116*/ {I_CALL, 1, {IMMEDIATE|BITS32,0,0}, "\321\1\xE8\64", IF_386}, + /* 117*/ {I_CALL, 1, {IMMEDIATE|BITS32|NEAR,0,0}, "\321\1\xE8\64", IF_386}, + /* 118*/ {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\322\1\x9A\35\30", IF_8086}, + /* 119*/ {I_CALL, 2, {IMMEDIATE|BITS16|COLON,IMMEDIATE,0}, "\320\1\x9A\31\30", IF_8086}, + /* 120*/ {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS16,0}, "\320\1\x9A\31\30", IF_8086}, + /* 121*/ {I_CALL, 2, {IMMEDIATE|BITS32|COLON,IMMEDIATE,0}, "\321\1\x9A\41\30", IF_386}, + /* 122*/ {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS32,0}, "\321\1\x9A\41\30", IF_386}, + /* 123*/ {I_CALL, 1, {MEMORY|FAR,0,0}, "\322\300\1\xFF\203", IF_8086}, + /* 124*/ {I_CALL, 1, {MEMORY|BITS16|FAR,0,0}, "\320\300\1\xFF\203", IF_8086}, + /* 125*/ {I_CALL, 1, {MEMORY|BITS32|FAR,0,0}, "\321\300\1\xFF\203", IF_386}, + /* 126*/ {I_CALL, 1, {MEMORY|NEAR,0,0}, "\322\300\1\xFF\202", IF_8086}, + /* 127*/ {I_CALL, 1, {MEMORY|BITS16|NEAR,0,0}, "\320\300\1\xFF\202", IF_8086}, + /* 128*/ {I_CALL, 1, {MEMORY|BITS32|NEAR,0,0}, "\321\300\1\xFF\202", IF_386}, + /* 129*/ {I_CALL, 1, {REG16,0,0}, "\320\300\1\xFF\202", IF_8086}, + /* 130*/ {I_CALL, 1, {REG32,0,0}, "\321\300\1\xFF\202", IF_386}, + /* 131*/ {I_CALL, 1, {MEMORY,0,0}, "\322\300\1\xFF\202", IF_8086}, + /* 132*/ {I_CALL, 1, {MEMORY|BITS16,0,0}, "\320\300\1\xFF\202", IF_8086}, + /* 133*/ {I_CALL, 1, {MEMORY|BITS32,0,0}, "\321\300\1\xFF\202", IF_386}, + /* 134*/ {I_CBW, 0, {0,0,0}, "\320\1\x98", IF_8086}, + /* 135*/ {I_CDQ, 0, {0,0,0}, "\321\1\x99", IF_386}, + /* 136*/ {I_CLC, 0, {0,0,0}, "\1\xF8", IF_8086}, + /* 137*/ {I_CLD, 0, {0,0,0}, "\1\xFC", IF_8086}, + /* 138*/ {I_CLI, 0, {0,0,0}, "\1\xFA", IF_8086}, + /* 139*/ {I_CLTS, 0, {0,0,0}, "\2\x0F\x06", IF_286|IF_PRIV}, + /* 140*/ {I_CMC, 0, {0,0,0}, "\1\xF5", IF_8086}, + /* 141*/ {I_CMP, 2, {MEMORY,REG8,0}, "\300\1\x38\101", IF_8086|IF_SM}, + /* 142*/ {I_CMP, 2, {REG8,REG8,0}, "\1\x38\101", IF_8086}, + /* 143*/ {I_CMP, 2, {MEMORY,REG16,0}, "\320\300\1\x39\101", IF_8086|IF_SM}, + /* 144*/ {I_CMP, 2, {REG16,REG16,0}, "\320\1\x39\101", IF_8086}, + /* 145*/ {I_CMP, 2, {MEMORY,REG32,0}, "\321\300\1\x39\101", IF_386|IF_SM}, + /* 146*/ {I_CMP, 2, {REG32,REG32,0}, "\321\1\x39\101", IF_386}, + /* 147*/ {I_CMP, 2, {REG8,MEMORY,0}, "\301\1\x3A\110", IF_8086|IF_SM}, + /* 148*/ {I_CMP, 2, {REG8,REG8,0}, "\1\x3A\110", IF_8086}, + /* 149*/ {I_CMP, 2, {REG16,MEMORY,0}, "\320\301\1\x3B\110", IF_8086|IF_SM}, + /* 150*/ {I_CMP, 2, {REG16,REG16,0}, "\320\1\x3B\110", IF_8086}, + /* 151*/ {I_CMP, 2, {REG32,MEMORY,0}, "\321\301\1\x3B\110", IF_386|IF_SM}, + /* 152*/ {I_CMP, 2, {REG32,REG32,0}, "\321\1\x3B\110", IF_386}, + /* 153*/ {I_CMP, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\207\15", IF_8086}, + /* 154*/ {I_CMP, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\207\15", IF_386}, + /* 155*/ {I_CMP, 2, {REG_AL,IMMEDIATE,0}, "\1\x3C\21", IF_8086|IF_SM}, + /* 156*/ {I_CMP, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x3D\31", IF_8086|IF_SM}, + /* 157*/ {I_CMP, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x3D\41", IF_386|IF_SM}, + /* 158*/ {I_CMP, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\207\21", IF_8086|IF_SM}, + /* 159*/ {I_CMP, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\207\131", IF_8086|IF_SM}, + /* 160*/ {I_CMP, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\207\141", IF_386|IF_SM}, + /* 161*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\207\21", IF_8086|IF_SM}, + /* 162*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\207\131", IF_8086|IF_SM}, + /* 163*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\207\141", IF_386|IF_SM}, + /* 164*/ {I_CMPSB, 0, {0,0,0}, "\332\1\xA6", IF_8086}, + /* 165*/ {I_CMPSD, 0, {0,0,0}, "\332\321\1\xA7", IF_386}, + /* 166*/ {I_CMPSW, 0, {0,0,0}, "\332\320\1\xA7", IF_8086}, + /* 167*/ {I_CMPXCHG, 2, {MEMORY,REG8,0}, "\300\2\x0F\xB0\101", IF_PENT|IF_SM}, + /* 168*/ {I_CMPXCHG, 2, {REG8,REG8,0}, "\2\x0F\xB0\101", IF_PENT}, + /* 169*/ {I_CMPXCHG, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xB1\101", IF_PENT|IF_SM}, + /* 170*/ {I_CMPXCHG, 2, {REG16,REG16,0}, "\320\2\x0F\xB1\101", IF_PENT}, + /* 171*/ {I_CMPXCHG, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xB1\101", IF_PENT|IF_SM}, + /* 172*/ {I_CMPXCHG, 2, {REG32,REG32,0}, "\321\2\x0F\xB1\101", IF_PENT}, + /* 173*/ {I_CMPXCHG486, 2, {MEMORY,REG8,0}, "\300\2\x0F\xA6\101", IF_486|IF_SM|IF_UNDOC}, + /* 174*/ {I_CMPXCHG486, 2, {REG8,REG8,0}, "\2\x0F\xA6\101", IF_486|IF_UNDOC}, + /* 175*/ {I_CMPXCHG486, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xA7\101", IF_486|IF_SM|IF_UNDOC}, + /* 176*/ {I_CMPXCHG486, 2, {REG16,REG16,0}, "\320\2\x0F\xA7\101", IF_486|IF_UNDOC}, + /* 177*/ {I_CMPXCHG486, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xA7\101", IF_486|IF_SM|IF_UNDOC}, + /* 178*/ {I_CMPXCHG486, 2, {REG32,REG32,0}, "\321\2\x0F\xA7\101", IF_486|IF_UNDOC}, + /* 179*/ {I_CMPXCHG8B, 1, {MEMORY,0,0}, "\300\2\x0F\xC7\201", IF_PENT}, + /* 180*/ {I_CPUID, 0, {0,0,0}, "\2\x0F\xA2", IF_PENT}, + /* 181*/ {I_CWD, 0, {0,0,0}, "\320\1\x99", IF_8086}, + /* 182*/ {I_CWDE, 0, {0,0,0}, "\321\1\x98", IF_386}, + /* 183*/ {I_DAA, 0, {0,0,0}, "\1\x27", IF_8086}, + /* 184*/ {I_DAS, 0, {0,0,0}, "\1\x2F", IF_8086}, + /* 185*/ {I_DEC, 1, {REG16,0,0}, "\320\10\x48", IF_8086}, + /* 186*/ {I_DEC, 1, {REG32,0,0}, "\321\10\x48", IF_386}, + /* 187*/ {I_DEC, 1, {REGMEM|BITS8,0,0}, "\300\1\xFE\201", IF_8086}, + /* 188*/ {I_DEC, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\201", IF_8086}, + /* 189*/ {I_DEC, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\201", IF_386}, + /* 190*/ {I_DIV, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\206", IF_8086}, + /* 191*/ {I_DIV, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\206", IF_8086}, + /* 192*/ {I_DIV, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\206", IF_386}, + /* 193*/ {I_EMMS, 0, {0,0,0}, "\2\x0F\x77", IF_PENT|IF_MMX}, + /* 194*/ {I_ENTER, 2, {IMMEDIATE,IMMEDIATE,0}, "\1\xC8\30\25", IF_186}, + /* 195*/ {I_EQU, 1, {IMMEDIATE,0,0}, "\0", IF_8086}, + /* 196*/ {I_EQU, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\0", IF_8086}, + /* 197*/ {I_F2XM1, 0, {0,0,0}, "\2\xD9\xF0", IF_8086|IF_FPU}, + /* 198*/ {I_FABS, 0, {0,0,0}, "\2\xD9\xE1", IF_8086|IF_FPU}, + /* 199*/ {I_FADD, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\200", IF_8086|IF_FPU}, + /* 200*/ {I_FADD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\200", IF_8086|IF_FPU}, + /* 201*/ {I_FADD, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xC0", IF_8086|IF_FPU}, + /* 202*/ {I_FADD, 1, {FPUREG,0,0}, "\1\xD8\10\xC0", IF_8086|IF_FPU}, + /* 203*/ {I_FADD, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xC0", IF_8086|IF_FPU}, + /* 204*/ {I_FADD, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xC0", IF_8086|IF_FPU}, + /* 205*/ {I_FADDP, 1, {FPUREG,0,0}, "\1\xDE\10\xC0", IF_8086|IF_FPU}, + /* 206*/ {I_FADDP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xC0", IF_8086|IF_FPU}, + /* 207*/ {I_FBLD, 1, {MEMORY|BITS80,0,0}, "\300\1\xDF\204", IF_8086|IF_FPU}, + /* 208*/ {I_FBLD, 1, {MEMORY,0,0}, "\300\1\xDF\204", IF_8086|IF_FPU}, + /* 209*/ {I_FBSTP, 1, {MEMORY|BITS80,0,0}, "\300\1\xDF\206", IF_8086|IF_FPU}, + /* 210*/ {I_FBSTP, 1, {MEMORY,0,0}, "\300\1\xDF\206", IF_8086|IF_FPU}, + /* 211*/ {I_FCHS, 0, {0,0,0}, "\2\xD9\xE0", IF_8086|IF_FPU}, + /* 212*/ {I_FCLEX, 0, {0,0,0}, "\3\x9B\xDB\xE2", IF_8086|IF_FPU}, + /* 213*/ {I_FCMOVB, 1, {FPUREG,0,0}, "\1\xDA\10\xC0", IF_P6|IF_FPU}, + /* 214*/ {I_FCMOVB, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xC0", IF_P6|IF_FPU}, + /* 215*/ {I_FCMOVBE, 1, {FPUREG,0,0}, "\1\xDA\10\xD0", IF_P6|IF_FPU}, + /* 216*/ {I_FCMOVBE, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xD0", IF_P6|IF_FPU}, + /* 217*/ {I_FCMOVE, 1, {FPUREG,0,0}, "\1\xDA\10\xC8", IF_P6|IF_FPU}, + /* 218*/ {I_FCMOVE, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xC8", IF_P6|IF_FPU}, + /* 219*/ {I_FCMOVNB, 1, {FPUREG,0,0}, "\1\xDB\10\xC0", IF_P6|IF_FPU}, + /* 220*/ {I_FCMOVNB, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xC0", IF_P6|IF_FPU}, + /* 221*/ {I_FCMOVNBE, 1, {FPUREG,0,0}, "\1\xDB\10\xD0", IF_P6|IF_FPU}, + /* 222*/ {I_FCMOVNBE, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xD0", IF_P6|IF_FPU}, + /* 223*/ {I_FCMOVNE, 1, {FPUREG,0,0}, "\1\xDB\10\xC8", IF_P6|IF_FPU}, + /* 224*/ {I_FCMOVNE, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xC8", IF_P6|IF_FPU}, + /* 225*/ {I_FCMOVNU, 1, {FPUREG,0,0}, "\1\xDB\10\xD8", IF_P6|IF_FPU}, + /* 226*/ {I_FCMOVNU, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xD8", IF_P6|IF_FPU}, + /* 227*/ {I_FCMOVU, 1, {FPUREG,0,0}, "\1\xDA\10\xD8", IF_P6|IF_FPU}, + /* 228*/ {I_FCMOVU, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xD8", IF_P6|IF_FPU}, + /* 229*/ {I_FCOM, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\202", IF_8086|IF_FPU}, + /* 230*/ {I_FCOM, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\202", IF_8086|IF_FPU}, + /* 231*/ {I_FCOM, 1, {FPUREG,0,0}, "\1\xD8\10\xD0", IF_8086|IF_FPU}, + /* 232*/ {I_FCOM, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xD0", IF_8086|IF_FPU}, + /* 233*/ {I_FCOMI, 1, {FPUREG,0,0}, "\1\xDB\10\xF0", IF_P6|IF_FPU}, + /* 234*/ {I_FCOMI, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xF0", IF_P6|IF_FPU}, + /* 235*/ {I_FCOMIP, 1, {FPUREG,0,0}, "\1\xDF\10\xF0", IF_P6|IF_FPU}, + /* 236*/ {I_FCOMIP, 2, {FPU0,FPUREG,0}, "\1\xDF\11\xF0", IF_P6|IF_FPU}, + /* 237*/ {I_FCOMP, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\203", IF_8086|IF_FPU}, + /* 238*/ {I_FCOMP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\203", IF_8086|IF_FPU}, + /* 239*/ {I_FCOMP, 1, {FPUREG,0,0}, "\1\xD8\10\xD8", IF_8086|IF_FPU}, + /* 240*/ {I_FCOMP, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xD8", IF_8086|IF_FPU}, + /* 241*/ {I_FCOMPP, 0, {0,0,0}, "\2\xDE\xD9", IF_8086|IF_FPU}, + /* 242*/ {I_FCOS, 0, {0,0,0}, "\2\xD9\xFF", IF_386|IF_FPU}, + /* 243*/ {I_FDECSTP, 0, {0,0,0}, "\2\xD9\xF6", IF_8086|IF_FPU}, + /* 244*/ {I_FDISI, 0, {0,0,0}, "\3\x9B\xDB\xE1", IF_8086|IF_FPU}, + /* 245*/ {I_FDIV, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\206", IF_8086|IF_FPU}, + /* 246*/ {I_FDIV, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\206", IF_8086|IF_FPU}, + /* 247*/ {I_FDIV, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xF8", IF_8086|IF_FPU}, + /* 248*/ {I_FDIV, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xF8", IF_8086|IF_FPU}, + /* 249*/ {I_FDIV, 1, {FPUREG,0,0}, "\1\xD8\10\xF0", IF_8086|IF_FPU}, + /* 250*/ {I_FDIV, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xF0", IF_8086|IF_FPU}, + /* 251*/ {I_FDIVP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xF8", IF_8086|IF_FPU}, + /* 252*/ {I_FDIVP, 1, {FPUREG,0,0}, "\1\xDE\10\xF8", IF_8086|IF_FPU}, + /* 253*/ {I_FDIVR, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\207", IF_8086|IF_FPU}, + /* 254*/ {I_FDIVR, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\207", IF_8086|IF_FPU}, + /* 255*/ {I_FDIVR, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xF0", IF_8086|IF_FPU}, + /* 256*/ {I_FDIVR, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xF0", IF_8086|IF_FPU}, + /* 257*/ {I_FDIVR, 1, {FPUREG,0,0}, "\1\xD8\10\xF8", IF_8086|IF_FPU}, + /* 258*/ {I_FDIVR, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xF8", IF_8086|IF_FPU}, + /* 259*/ {I_FDIVRP, 1, {FPUREG,0,0}, "\1\xDE\10\xF0", IF_8086|IF_FPU}, + /* 260*/ {I_FDIVRP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xF0", IF_8086|IF_FPU}, + /* 261*/ {I_FEMMS, 0, {0,0,0}, "\2\x0F\x0E", IF_PENT|IF_3DNOW}, + /* 262*/ {I_FENI, 0, {0,0,0}, "\3\x9B\xDB\xE0", IF_8086|IF_FPU}, + /* 263*/ {I_FFREE, 1, {FPUREG,0,0}, "\1\xDD\10\xC0", IF_8086|IF_FPU}, + /* 264*/ {I_FFREEP, 1, {FPUREG,0,0}, "\1\xDF\10\xC0", IF_286|IF_FPU|IF_UNDOC}, + /* 265*/ {I_FIADD, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\200", IF_8086|IF_FPU}, + /* 266*/ {I_FIADD, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\200", IF_8086|IF_FPU}, + /* 267*/ {I_FICOM, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\202", IF_8086|IF_FPU}, + /* 268*/ {I_FICOM, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\202", IF_8086|IF_FPU}, + /* 269*/ {I_FICOMP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\203", IF_8086|IF_FPU}, + /* 270*/ {I_FICOMP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\203", IF_8086|IF_FPU}, + /* 271*/ {I_FIDIV, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\206", IF_8086|IF_FPU}, + /* 272*/ {I_FIDIV, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\206", IF_8086|IF_FPU}, + /* 273*/ {I_FIDIVR, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\207", IF_8086|IF_FPU}, + /* 274*/ {I_FIDIVR, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\207", IF_8086|IF_FPU}, + /* 275*/ {I_FILD, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\200", IF_8086|IF_FPU}, + /* 276*/ {I_FILD, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\200", IF_8086|IF_FPU}, + /* 277*/ {I_FILD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\205", IF_8086|IF_FPU}, + /* 278*/ {I_FIMUL, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\201", IF_8086|IF_FPU}, + /* 279*/ {I_FIMUL, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\201", IF_8086|IF_FPU}, + /* 280*/ {I_FINCSTP, 0, {0,0,0}, "\2\xD9\xF7", IF_8086|IF_FPU}, + /* 281*/ {I_FINIT, 0, {0,0,0}, "\3\x9B\xDB\xE3", IF_8086|IF_FPU}, + /* 282*/ {I_FIST, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\202", IF_8086|IF_FPU}, + /* 283*/ {I_FIST, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\202", IF_8086|IF_FPU}, + /* 284*/ {I_FISTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\203", IF_8086|IF_FPU}, + /* 285*/ {I_FISTP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\203", IF_8086|IF_FPU}, + /* 286*/ {I_FISTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\207", IF_8086|IF_FPU}, + /* 287*/ {I_FISTTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDD\201", IF_PRESCOTT|IF_FPU}, + /* 288*/ {I_FISTTP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDB\201", IF_PRESCOTT|IF_FPU}, + /* 289*/ {I_FISTTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\201", IF_PRESCOTT|IF_FPU}, + /* 290*/ {I_FISUB, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\204", IF_8086|IF_FPU}, + /* 291*/ {I_FISUB, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\204", IF_8086|IF_FPU}, + /* 292*/ {I_FISUBR, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\205", IF_8086|IF_FPU}, + /* 293*/ {I_FISUBR, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\205", IF_8086|IF_FPU}, + /* 294*/ {I_FLD, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\200", IF_8086|IF_FPU}, + /* 295*/ {I_FLD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\200", IF_8086|IF_FPU}, + /* 296*/ {I_FLD, 1, {MEMORY|BITS80,0,0}, "\300\1\xDB\205", IF_8086|IF_FPU}, + /* 297*/ {I_FLD, 1, {FPUREG,0,0}, "\1\xD9\10\xC0", IF_8086|IF_FPU}, + /* 298*/ {I_FLD1, 0, {0,0,0}, "\2\xD9\xE8", IF_8086|IF_FPU}, + /* 299*/ {I_FLDCW, 1, {MEMORY,0,0}, "\300\1\xD9\205", IF_8086|IF_FPU|IF_SW}, + /* 300*/ {I_FLDENV, 1, {MEMORY,0,0}, "\300\1\xD9\204", IF_8086|IF_FPU}, + /* 301*/ {I_FLDL2E, 0, {0,0,0}, "\2\xD9\xEA", IF_8086|IF_FPU}, + /* 302*/ {I_FLDL2T, 0, {0,0,0}, "\2\xD9\xE9", IF_8086|IF_FPU}, + /* 303*/ {I_FLDLG2, 0, {0,0,0}, "\2\xD9\xEC", IF_8086|IF_FPU}, + /* 304*/ {I_FLDLN2, 0, {0,0,0}, "\2\xD9\xED", IF_8086|IF_FPU}, + /* 305*/ {I_FLDPI, 0, {0,0,0}, "\2\xD9\xEB", IF_8086|IF_FPU}, + /* 306*/ {I_FLDZ, 0, {0,0,0}, "\2\xD9\xEE", IF_8086|IF_FPU}, + /* 307*/ {I_FMUL, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\201", IF_8086|IF_FPU}, + /* 308*/ {I_FMUL, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\201", IF_8086|IF_FPU}, + /* 309*/ {I_FMUL, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xC8", IF_8086|IF_FPU}, + /* 310*/ {I_FMUL, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xC8", IF_8086|IF_FPU}, + /* 311*/ {I_FMUL, 1, {FPUREG,0,0}, "\1\xD8\10\xC8", IF_8086|IF_FPU}, + /* 312*/ {I_FMUL, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xC8", IF_8086|IF_FPU}, + /* 313*/ {I_FMULP, 1, {FPUREG,0,0}, "\1\xDE\10\xC8", IF_8086|IF_FPU}, + /* 314*/ {I_FMULP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xC8", IF_8086|IF_FPU}, + /* 315*/ {I_FNCLEX, 0, {0,0,0}, "\2\xDB\xE2", IF_8086|IF_FPU}, + /* 316*/ {I_FNDISI, 0, {0,0,0}, "\2\xDB\xE1", IF_8086|IF_FPU}, + /* 317*/ {I_FNENI, 0, {0,0,0}, "\2\xDB\xE0", IF_8086|IF_FPU}, + /* 318*/ {I_FNINIT, 0, {0,0,0}, "\2\xDB\xE3", IF_8086|IF_FPU}, + /* 319*/ {I_FNOP, 0, {0,0,0}, "\2\xD9\xD0", IF_8086|IF_FPU}, + /* 320*/ {I_FNSAVE, 1, {MEMORY,0,0}, "\300\1\xDD\206", IF_8086|IF_FPU}, + /* 321*/ {I_FNSTCW, 1, {MEMORY,0,0}, "\300\1\xD9\207", IF_8086|IF_FPU|IF_SW}, + /* 322*/ {I_FNSTENV, 1, {MEMORY,0,0}, "\300\1\xD9\206", IF_8086|IF_FPU}, + /* 323*/ {I_FNSTSW, 1, {MEMORY,0,0}, "\300\1\xDD\207", IF_8086|IF_FPU|IF_SW}, + /* 324*/ {I_FNSTSW, 1, {REG_AX,0,0}, "\2\xDF\xE0", IF_286|IF_FPU}, + /* 325*/ {I_FPATAN, 0, {0,0,0}, "\2\xD9\xF3", IF_8086|IF_FPU}, + /* 326*/ {I_FPREM, 0, {0,0,0}, "\2\xD9\xF8", IF_8086|IF_FPU}, + /* 327*/ {I_FPREM1, 0, {0,0,0}, "\2\xD9\xF5", IF_386|IF_FPU}, + /* 328*/ {I_FPTAN, 0, {0,0,0}, "\2\xD9\xF2", IF_8086|IF_FPU}, + /* 329*/ {I_FRNDINT, 0, {0,0,0}, "\2\xD9\xFC", IF_8086|IF_FPU}, + /* 330*/ {I_FRSTOR, 1, {MEMORY,0,0}, "\300\1\xDD\204", IF_8086|IF_FPU}, + /* 331*/ {I_FSAVE, 1, {MEMORY,0,0}, "\300\2\x9B\xDD\206", IF_8086|IF_FPU}, + /* 332*/ {I_FSCALE, 0, {0,0,0}, "\2\xD9\xFD", IF_8086|IF_FPU}, + /* 333*/ {I_FSETPM, 0, {0,0,0}, "\2\xDB\xE4", IF_286|IF_FPU}, + /* 334*/ {I_FSIN, 0, {0,0,0}, "\2\xD9\xFE", IF_386|IF_FPU}, + /* 335*/ {I_FSINCOS, 0, {0,0,0}, "\2\xD9\xFB", IF_386|IF_FPU}, + /* 336*/ {I_FSQRT, 0, {0,0,0}, "\2\xD9\xFA", IF_8086|IF_FPU}, + /* 337*/ {I_FST, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\202", IF_8086|IF_FPU}, + /* 338*/ {I_FST, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\202", IF_8086|IF_FPU}, + /* 339*/ {I_FST, 1, {FPUREG,0,0}, "\1\xDD\10\xD0", IF_8086|IF_FPU}, + /* 340*/ {I_FSTCW, 1, {MEMORY,0,0}, "\300\2\x9B\xD9\207", IF_8086|IF_FPU|IF_SW}, + /* 341*/ {I_FSTENV, 1, {MEMORY,0,0}, "\300\2\x9B\xD9\206", IF_8086|IF_FPU}, + /* 342*/ {I_FSTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\203", IF_8086|IF_FPU}, + /* 343*/ {I_FSTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\203", IF_8086|IF_FPU}, + /* 344*/ {I_FSTP, 1, {MEMORY|BITS80,0,0}, "\300\1\xDB\207", IF_8086|IF_FPU}, + /* 345*/ {I_FSTP, 1, {FPUREG,0,0}, "\1\xDD\10\xD8", IF_8086|IF_FPU}, + /* 346*/ {I_FSTSW, 1, {MEMORY,0,0}, "\300\2\x9B\xDD\207", IF_8086|IF_FPU|IF_SW}, + /* 347*/ {I_FSTSW, 1, {REG_AX,0,0}, "\3\x9B\xDF\xE0", IF_286|IF_FPU}, + /* 348*/ {I_FSUB, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\204", IF_8086|IF_FPU}, + /* 349*/ {I_FSUB, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\204", IF_8086|IF_FPU}, + /* 350*/ {I_FSUB, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xE8", IF_8086|IF_FPU}, + /* 351*/ {I_FSUB, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xE8", IF_8086|IF_FPU}, + /* 352*/ {I_FSUB, 1, {FPUREG,0,0}, "\1\xD8\10\xE0", IF_8086|IF_FPU}, + /* 353*/ {I_FSUB, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xE0", IF_8086|IF_FPU}, + /* 354*/ {I_FSUBP, 1, {FPUREG,0,0}, "\1\xDE\10\xE8", IF_8086|IF_FPU}, + /* 355*/ {I_FSUBP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xE8", IF_8086|IF_FPU}, + /* 356*/ {I_FSUBR, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\205", IF_8086|IF_FPU}, + /* 357*/ {I_FSUBR, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\205", IF_8086|IF_FPU}, + /* 358*/ {I_FSUBR, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xE0", IF_8086|IF_FPU}, + /* 359*/ {I_FSUBR, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xE0", IF_8086|IF_FPU}, + /* 360*/ {I_FSUBR, 1, {FPUREG,0,0}, "\1\xD8\10\xE8", IF_8086|IF_FPU}, + /* 361*/ {I_FSUBR, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xE8", IF_8086|IF_FPU}, + /* 362*/ {I_FSUBRP, 1, {FPUREG,0,0}, "\1\xDE\10\xE0", IF_8086|IF_FPU}, + /* 363*/ {I_FSUBRP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xE0", IF_8086|IF_FPU}, + /* 364*/ {I_FTST, 0, {0,0,0}, "\2\xD9\xE4", IF_8086|IF_FPU}, + /* 365*/ {I_FUCOM, 1, {FPUREG,0,0}, "\1\xDD\10\xE0", IF_386|IF_FPU}, + /* 366*/ {I_FUCOM, 2, {FPU0,FPUREG,0}, "\1\xDD\11\xE0", IF_386|IF_FPU}, + /* 367*/ {I_FUCOMI, 1, {FPUREG,0,0}, "\1\xDB\10\xE8", IF_P6|IF_FPU}, + /* 368*/ {I_FUCOMI, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xE8", IF_P6|IF_FPU}, + /* 369*/ {I_FUCOMIP, 1, {FPUREG,0,0}, "\1\xDF\10\xE8", IF_P6|IF_FPU}, + /* 370*/ {I_FUCOMIP, 2, {FPU0,FPUREG,0}, "\1\xDF\11\xE8", IF_P6|IF_FPU}, + /* 371*/ {I_FUCOMP, 1, {FPUREG,0,0}, "\1\xDD\10\xE8", IF_386|IF_FPU}, + /* 372*/ {I_FUCOMP, 2, {FPU0,FPUREG,0}, "\1\xDD\11\xE8", IF_386|IF_FPU}, + /* 373*/ {I_FUCOMPP, 0, {0,0,0}, "\2\xDA\xE9", IF_386|IF_FPU}, + /* 374*/ {I_FXAM, 0, {0,0,0}, "\2\xD9\xE5", IF_8086|IF_FPU}, + /* 375*/ {I_FXCH, 0, {0,0,0}, "\2\xD9\xC9", IF_8086|IF_FPU}, + /* 376*/ {I_FXCH, 1, {FPUREG,0,0}, "\1\xD9\10\xC8", IF_8086|IF_FPU}, + /* 377*/ {I_FXCH, 2, {FPUREG,FPU0,0}, "\1\xD9\10\xC8", IF_8086|IF_FPU}, + /* 378*/ {I_FXCH, 2, {FPU0,FPUREG,0}, "\1\xD9\11\xC8", IF_8086|IF_FPU}, + /* 379*/ {I_FXTRACT, 0, {0,0,0}, "\2\xD9\xF4", IF_8086|IF_FPU}, + /* 380*/ {I_FYL2X, 0, {0,0,0}, "\2\xD9\xF1", IF_8086|IF_FPU}, + /* 381*/ {I_FYL2XP1, 0, {0,0,0}, "\2\xD9\xF9", IF_8086|IF_FPU}, + /* 382*/ {I_HLT, 0, {0,0,0}, "\1\xF4", IF_8086|IF_PRIV}, + /* 383*/ {I_IDIV, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\207", IF_8086}, + /* 384*/ {I_IDIV, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\207", IF_8086}, + /* 385*/ {I_IDIV, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\207", IF_386}, + /* 386*/ {I_IMUL, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\205", IF_8086}, + /* 387*/ {I_IMUL, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\205", IF_8086}, + /* 388*/ {I_IMUL, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\205", IF_386}, + /* 389*/ {I_IMUL, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xAF\110", IF_386|IF_SM}, + /* 390*/ {I_IMUL, 2, {REG16,REG16,0}, "\320\2\x0F\xAF\110", IF_386}, + /* 391*/ {I_IMUL, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xAF\110", IF_386|IF_SM}, + /* 392*/ {I_IMUL, 2, {REG32,REG32,0}, "\321\2\x0F\xAF\110", IF_386}, + /* 393*/ {I_IMUL, 3, {REG16,MEMORY,IMMEDIATE|BITS8}, "\320\301\1\x6B\110\16", IF_186|IF_SM}, + /* 394*/ {I_IMUL, 3, {REG16,MEMORY,IMMEDIATE|BITS16}, "\320\301\1\x69\110\32", IF_186|IF_SM}, + /* 395*/ {I_IMUL, 3, {REG16,REG16,IMMEDIATE|BITS8}, "\320\1\x6B\110\16", IF_186}, + /* 396*/ {I_IMUL, 3, {REG16,REG16,IMMEDIATE|BITS16}, "\320\1\x69\110\32", IF_186}, + /* 397*/ {I_IMUL, 3, {REG32,MEMORY,IMMEDIATE|BITS8}, "\321\301\1\x6B\110\16", IF_386|IF_SM}, + /* 398*/ {I_IMUL, 3, {REG32,MEMORY,IMMEDIATE|BITS32}, "\321\301\1\x69\110\42", IF_386|IF_SM}, + /* 399*/ {I_IMUL, 3, {REG32,REG32,IMMEDIATE|BITS8}, "\321\1\x6B\110\16", IF_386}, + /* 400*/ {I_IMUL, 3, {REG32,REG32,IMMEDIATE|BITS32}, "\321\1\x69\110\42", IF_386}, + /* 401*/ {I_IMUL, 2, {REG16,IMMEDIATE|BITS8,0}, "\320\1\x6B\100\15", IF_186}, + /* 402*/ {I_IMUL, 2, {REG16,IMMEDIATE|BITS16,0}, "\320\1\x69\100\31", IF_186}, + /* 403*/ {I_IMUL, 2, {REG32,IMMEDIATE|BITS8,0}, "\321\1\x6B\100\15", IF_386}, + /* 404*/ {I_IMUL, 2, {REG32,IMMEDIATE|BITS32,0}, "\321\1\x69\100\41", IF_386}, + /* 405*/ {I_IN, 2, {REG_AL,IMMEDIATE,0}, "\1\xE4\25", IF_8086|IF_SB}, + /* 406*/ {I_IN, 2, {REG_AX,IMMEDIATE,0}, "\320\1\xE5\25", IF_8086|IF_SB}, + /* 407*/ {I_IN, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\xE5\25", IF_386|IF_SB}, + /* 408*/ {I_IN, 2, {REG_AL,REG_DX,0}, "\1\xEC", IF_8086}, + /* 409*/ {I_IN, 2, {REG_AX,REG_DX,0}, "\320\1\xED", IF_8086}, + /* 410*/ {I_IN, 2, {REG_EAX,REG_DX,0}, "\321\1\xED", IF_386}, + /* 411*/ {I_INC, 1, {REG16,0,0}, "\320\10\x40", IF_8086}, + /* 412*/ {I_INC, 1, {REG32,0,0}, "\321\10\x40", IF_386}, + /* 413*/ {I_INC, 1, {REGMEM|BITS8,0,0}, "\300\1\xFE\200", IF_8086}, + /* 414*/ {I_INC, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\200", IF_8086}, + /* 415*/ {I_INC, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\200", IF_386}, + /* 416*/ {I_INSB, 0, {0,0,0}, "\1\x6C", IF_186}, + /* 417*/ {I_INSD, 0, {0,0,0}, "\321\1\x6D", IF_386}, + /* 418*/ {I_INSW, 0, {0,0,0}, "\320\1\x6D", IF_186}, + /* 419*/ {I_INT, 1, {IMMEDIATE,0,0}, "\1\xCD\24", IF_8086|IF_SB}, + /* 420*/ {I_INT1, 0, {0,0,0}, "\1\xF1", IF_386}, + /* 421*/ {I_INT3, 0, {0,0,0}, "\1\xCC", IF_8086}, + /* 422*/ {I_INTO, 0, {0,0,0}, "\1\xCE", IF_8086}, + /* 423*/ {I_INVD, 0, {0,0,0}, "\2\x0F\x08", IF_486|IF_PRIV}, + /* 424*/ {I_INVLPG, 1, {MEMORY,0,0}, "\300\2\x0F\x01\207", IF_486|IF_PRIV}, + /* 425*/ {I_IRET, 0, {0,0,0}, "\322\1\xCF", IF_8086}, + /* 426*/ {I_IRETD, 0, {0,0,0}, "\321\1\xCF", IF_386}, + /* 427*/ {I_IRETW, 0, {0,0,0}, "\320\1\xCF", IF_8086}, + /* 428*/ {I_JCXZ, 1, {IMMEDIATE,0,0}, "\310\1\xE3\50", IF_8086}, + /* 429*/ {I_JECXZ, 1, {IMMEDIATE,0,0}, "\311\1\xE3\50", IF_386}, + /* 430*/ {I_JMP, 1, {IMMEDIATE|SHORT,0,0}, "\1\xEB\50", IF_8086}, + /* 431*/ {I_JMP, 1, {IMMEDIATE,0,0}, "\322\1\xE9\64", IF_8086}, + /* 432*/ {I_JMP, 1, {IMMEDIATE|BITS16,0,0}, "\320\1\xE9\64", IF_8086}, + /* 433*/ {I_JMP, 1, {IMMEDIATE|BITS32,0,0}, "\321\1\xE9\64", IF_386}, + /* 434*/ {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\322\1\xEA\35\30", IF_8086}, + /* 435*/ {I_JMP, 2, {IMMEDIATE|BITS16|COLON,IMMEDIATE,0}, "\320\1\xEA\31\30", IF_8086}, + /* 436*/ {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS16,0}, "\320\1\xEA\31\30", IF_8086}, + /* 437*/ {I_JMP, 2, {IMMEDIATE|BITS32|COLON,IMMEDIATE,0}, "\321\1\xEA\41\30", IF_386}, + /* 438*/ {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS32,0}, "\321\1\xEA\41\30", IF_386}, + /* 439*/ {I_JMP, 1, {MEMORY|FAR,0,0}, "\322\300\1\xFF\205", IF_8086}, + /* 440*/ {I_JMP, 1, {MEMORY|BITS16|FAR,0,0}, "\320\300\1\xFF\205", IF_8086}, + /* 441*/ {I_JMP, 1, {MEMORY|BITS32|FAR,0,0}, "\321\300\1\xFF\205", IF_386}, + /* 442*/ {I_JMP, 1, {MEMORY|NEAR,0,0}, "\322\300\1\xFF\204", IF_8086}, + /* 443*/ {I_JMP, 1, {MEMORY|BITS16|NEAR,0,0}, "\320\300\1\xFF\204", IF_8086}, + /* 444*/ {I_JMP, 1, {MEMORY|BITS32|NEAR,0,0}, "\321\300\1\xFF\204", IF_386}, + /* 445*/ {I_JMP, 1, {REG16,0,0}, "\320\300\1\xFF\204", IF_8086}, + /* 446*/ {I_JMP, 1, {REG32,0,0}, "\321\300\1\xFF\204", IF_386}, + /* 447*/ {I_JMP, 1, {MEMORY,0,0}, "\322\300\1\xFF\204", IF_8086}, + /* 448*/ {I_JMP, 1, {MEMORY|BITS16,0,0}, "\320\300\1\xFF\204", IF_8086}, + /* 449*/ {I_JMP, 1, {MEMORY|BITS32,0,0}, "\321\300\1\xFF\204", IF_386}, + /* 450*/ {I_JMPE, 1, {IMMEDIATE,0,0}, "\322\2\x0F\xB8\64", IF_IA64}, + /* 451*/ {I_JMPE, 1, {IMMEDIATE|BITS16,0,0}, "\320\2\x0F\xB8\64", IF_IA64}, + /* 452*/ {I_JMPE, 1, {IMMEDIATE|BITS32,0,0}, "\321\2\x0F\xB8\64", IF_IA64}, + /* 453*/ {I_JMPE, 1, {REGMEM|BITS16,0,0}, "\320\2\x0F\x00\206", IF_IA64}, + /* 454*/ {I_JMPE, 1, {REGMEM|BITS32,0,0}, "\321\2\x0F\x00\206", IF_IA64}, + /* 455*/ {I_LAHF, 0, {0,0,0}, "\1\x9F", IF_8086}, + /* 456*/ {I_LAR, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x02\110", IF_286|IF_PROT|IF_SM}, + /* 457*/ {I_LAR, 2, {REG16,REG16,0}, "\320\2\x0F\x02\110", IF_286|IF_PROT}, + /* 458*/ {I_LAR, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x02\110", IF_386|IF_PROT|IF_SM}, + /* 459*/ {I_LAR, 2, {REG32,REG32,0}, "\321\2\x0F\x02\110", IF_386|IF_PROT}, + /* 460*/ {I_LDS, 2, {REG16,MEMORY,0}, "\320\301\1\xC5\110", IF_8086}, + /* 461*/ {I_LDS, 2, {REG32,MEMORY,0}, "\321\301\1\xC5\110", IF_386}, + /* 462*/ {I_LEA, 2, {REG16,MEMORY,0}, "\320\301\1\x8D\110", IF_8086}, + /* 463*/ {I_LEA, 2, {REG32,MEMORY,0}, "\321\301\1\x8D\110", IF_386}, + /* 464*/ {I_LEAVE, 0, {0,0,0}, "\1\xC9", IF_186}, + /* 465*/ {I_LES, 2, {REG16,MEMORY,0}, "\320\301\1\xC4\110", IF_8086}, + /* 466*/ {I_LES, 2, {REG32,MEMORY,0}, "\321\301\1\xC4\110", IF_386}, + /* 467*/ {I_LFS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB4\110", IF_386}, + /* 468*/ {I_LFS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB4\110", IF_386}, + /* 469*/ {I_LGDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\202", IF_286|IF_PRIV}, + /* 470*/ {I_LGS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB5\110", IF_386}, + /* 471*/ {I_LGS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB5\110", IF_386}, + /* 472*/ {I_LIDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\203", IF_286|IF_PRIV}, + /* 473*/ {I_LLDT, 1, {MEMORY,0,0}, "\300\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, + /* 474*/ {I_LLDT, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, + /* 475*/ {I_LLDT, 1, {REG16,0,0}, "\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, + /* 476*/ {I_LMSW, 1, {MEMORY,0,0}, "\300\2\x0F\x01\206", IF_286|IF_PRIV}, + /* 477*/ {I_LMSW, 1, {MEMORY|BITS16,0,0}, "\300\2\x0F\x01\206", IF_286|IF_PRIV}, + /* 478*/ {I_LMSW, 1, {REG16,0,0}, "\2\x0F\x01\206", IF_286|IF_PRIV}, + /* 479*/ {I_LOADALL, 0, {0,0,0}, "\2\x0F\x07", IF_386|IF_UNDOC}, + /* 480*/ {I_LOADALL286, 0, {0,0,0}, "\2\x0F\x05", IF_286|IF_UNDOC}, + /* 481*/ {I_LODSB, 0, {0,0,0}, "\1\xAC", IF_8086}, + /* 482*/ {I_LODSD, 0, {0,0,0}, "\321\1\xAD", IF_386}, + /* 483*/ {I_LODSW, 0, {0,0,0}, "\320\1\xAD", IF_8086}, + /* 484*/ {I_LOOP, 1, {IMMEDIATE,0,0}, "\312\1\xE2\50", IF_8086}, + /* 485*/ {I_LOOP, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE2\50", IF_8086}, + /* 486*/ {I_LOOP, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE2\50", IF_386}, + /* 487*/ {I_LOOPE, 1, {IMMEDIATE,0,0}, "\312\1\xE1\50", IF_8086}, + /* 488*/ {I_LOOPE, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE1\50", IF_8086}, + /* 489*/ {I_LOOPE, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE1\50", IF_386}, + /* 490*/ {I_LOOPNE, 1, {IMMEDIATE,0,0}, "\312\1\xE0\50", IF_8086}, + /* 491*/ {I_LOOPNE, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE0\50", IF_8086}, + /* 492*/ {I_LOOPNE, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE0\50", IF_386}, + /* 493*/ {I_LOOPNZ, 1, {IMMEDIATE,0,0}, "\312\1\xE0\50", IF_8086}, + /* 494*/ {I_LOOPNZ, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE0\50", IF_8086}, + /* 495*/ {I_LOOPNZ, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE0\50", IF_386}, + /* 496*/ {I_LOOPZ, 1, {IMMEDIATE,0,0}, "\312\1\xE1\50", IF_8086}, + /* 497*/ {I_LOOPZ, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE1\50", IF_8086}, + /* 498*/ {I_LOOPZ, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE1\50", IF_386}, + /* 499*/ {I_LSL, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x03\110", IF_286|IF_PROT|IF_SM}, + /* 500*/ {I_LSL, 2, {REG16,REG16,0}, "\320\2\x0F\x03\110", IF_286|IF_PROT}, + /* 501*/ {I_LSL, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x03\110", IF_386|IF_PROT|IF_SM}, + /* 502*/ {I_LSL, 2, {REG32,REG32,0}, "\321\2\x0F\x03\110", IF_386|IF_PROT}, + /* 503*/ {I_LSS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB2\110", IF_386}, + /* 504*/ {I_LSS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB2\110", IF_386}, + /* 505*/ {I_LTR, 1, {MEMORY,0,0}, "\300\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, + /* 506*/ {I_LTR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, + /* 507*/ {I_LTR, 1, {REG16,0,0}, "\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, + /* 508*/ {I_MONITOR, 0, {0,0,0}, "\3\x0F\x01\xC8", IF_PRESCOTT}, + /* 509*/ {I_MOV, 2, {MEMORY,REG_SREG,0}, "\300\1\x8C\101", IF_8086|IF_SM}, + /* 510*/ {I_MOV, 2, {REG16,REG_SREG,0}, "\320\1\x8C\101", IF_8086}, + /* 511*/ {I_MOV, 2, {REG32,REG_SREG,0}, "\321\1\x8C\101", IF_386}, + /* 512*/ {I_MOV, 2, {REG_SREG,MEMORY,0}, "\301\1\x8E\110", IF_8086|IF_SM}, + /* 513*/ {I_MOV, 2, {REG_SREG,REG16,0}, "\1\x8E\110", IF_8086}, + /* 514*/ {I_MOV, 2, {REG_SREG,REG32,0}, "\1\x8E\110", IF_386}, + /* 515*/ {I_MOV, 2, {REG_AL,MEM_OFFS,0}, "\301\1\xA0\45", IF_8086|IF_SM}, + /* 516*/ {I_MOV, 2, {REG_AX,MEM_OFFS,0}, "\301\320\1\xA1\45", IF_8086|IF_SM}, + /* 517*/ {I_MOV, 2, {REG_EAX,MEM_OFFS,0}, "\301\321\1\xA1\45", IF_386|IF_SM}, + /* 518*/ {I_MOV, 2, {MEM_OFFS,REG_AL,0}, "\300\1\xA2\44", IF_8086|IF_SM}, + /* 519*/ {I_MOV, 2, {MEM_OFFS,REG_AX,0}, "\300\320\1\xA3\44", IF_8086|IF_SM}, + /* 520*/ {I_MOV, 2, {MEM_OFFS,REG_EAX,0}, "\300\321\1\xA3\44", IF_386|IF_SM}, + /* 521*/ {I_MOV, 2, {REG32,REG_CREG,0}, "\2\x0F\x20\101", IF_386|IF_PRIV}, + /* 522*/ {I_MOV, 2, {REG32,REG_DREG,0}, "\2\x0F\x21\101", IF_386|IF_PRIV}, + /* 523*/ {I_MOV, 2, {REG32,REG_TREG,0}, "\2\x0F\x24\101", IF_386|IF_PRIV}, + /* 524*/ {I_MOV, 2, {REG_CREG,REG32,0}, "\2\x0F\x22\110", IF_386|IF_PRIV}, + /* 525*/ {I_MOV, 2, {REG_DREG,REG32,0}, "\2\x0F\x23\110", IF_386|IF_PRIV}, + /* 526*/ {I_MOV, 2, {REG_TREG,REG32,0}, "\2\x0F\x26\110", IF_386|IF_PRIV}, + /* 527*/ {I_MOV, 2, {MEMORY,REG8,0}, "\300\1\x88\101", IF_8086|IF_SM}, + /* 528*/ {I_MOV, 2, {REG8,REG8,0}, "\1\x88\101", IF_8086}, + /* 529*/ {I_MOV, 2, {MEMORY,REG16,0}, "\320\300\1\x89\101", IF_8086|IF_SM}, + /* 530*/ {I_MOV, 2, {REG16,REG16,0}, "\320\1\x89\101", IF_8086}, + /* 531*/ {I_MOV, 2, {MEMORY,REG32,0}, "\321\300\1\x89\101", IF_386|IF_SM}, + /* 532*/ {I_MOV, 2, {REG32,REG32,0}, "\321\1\x89\101", IF_386}, + /* 533*/ {I_MOV, 2, {REG8,MEMORY,0}, "\301\1\x8A\110", IF_8086|IF_SM}, + /* 534*/ {I_MOV, 2, {REG8,REG8,0}, "\1\x8A\110", IF_8086}, + /* 535*/ {I_MOV, 2, {REG16,MEMORY,0}, "\320\301\1\x8B\110", IF_8086|IF_SM}, + /* 536*/ {I_MOV, 2, {REG16,REG16,0}, "\320\1\x8B\110", IF_8086}, + /* 537*/ {I_MOV, 2, {REG32,MEMORY,0}, "\321\301\1\x8B\110", IF_386|IF_SM}, + /* 538*/ {I_MOV, 2, {REG32,REG32,0}, "\321\1\x8B\110", IF_386}, + /* 539*/ {I_MOV, 2, {REG8,IMMEDIATE,0}, "\10\xB0\21", IF_8086|IF_SM}, + /* 540*/ {I_MOV, 2, {REG16,IMMEDIATE,0}, "\320\10\xB8\31", IF_8086|IF_SM}, + /* 541*/ {I_MOV, 2, {REG32,IMMEDIATE,0}, "\321\10\xB8\41", IF_386|IF_SM}, + /* 542*/ {I_MOV, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC6\200\21", IF_8086|IF_SM}, + /* 543*/ {I_MOV, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC7\200\31", IF_8086|IF_SM}, + /* 544*/ {I_MOV, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC7\200\41", IF_386|IF_SM}, + /* 545*/ {I_MOV, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\xC6\200\21", IF_8086|IF_SM}, + /* 546*/ {I_MOV, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\1\xC7\200\31", IF_8086|IF_SM}, + /* 547*/ {I_MOV, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\1\xC7\200\41", IF_386|IF_SM}, + /* 548*/ {I_MOVD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6E\110", IF_PENT|IF_MMX|IF_SD}, + /* 549*/ {I_MOVD, 2, {MMXREG,REG32,0}, "\2\x0F\x6E\110", IF_PENT|IF_MMX}, + /* 550*/ {I_MOVD, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\x7E\101", IF_PENT|IF_MMX|IF_SD}, + /* 551*/ {I_MOVD, 2, {REG32,MMXREG,0}, "\2\x0F\x7E\101", IF_PENT|IF_MMX}, + /* 552*/ {I_MOVQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6F\110", IF_PENT|IF_MMX|IF_SM}, + /* 553*/ {I_MOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6F\110", IF_PENT|IF_MMX}, + /* 554*/ {I_MOVQ, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\x7F\101", IF_PENT|IF_MMX|IF_SM}, + /* 555*/ {I_MOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x7F\101", IF_PENT|IF_MMX}, + /* 556*/ {I_MOVSB, 0, {0,0,0}, "\1\xA4", IF_8086}, + /* 557*/ {I_MOVSD, 0, {0,0,0}, "\321\1\xA5", IF_386}, + /* 558*/ {I_MOVSW, 0, {0,0,0}, "\320\1\xA5", IF_8086}, + /* 559*/ {I_MOVSX, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBE\110", IF_386|IF_SB}, + /* 560*/ {I_MOVSX, 2, {REG16,REG8,0}, "\320\2\x0F\xBE\110", IF_386}, + /* 561*/ {I_MOVSX, 2, {REG32,REGMEM|BITS8,0}, "\321\301\2\x0F\xBE\110", IF_386}, + /* 562*/ {I_MOVSX, 2, {REG32,REGMEM|BITS16,0}, "\321\301\2\x0F\xBF\110", IF_386}, + /* 563*/ {I_MOVZX, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB6\110", IF_386|IF_SB}, + /* 564*/ {I_MOVZX, 2, {REG16,REG8,0}, "\320\2\x0F\xB6\110", IF_386}, + /* 565*/ {I_MOVZX, 2, {REG32,REGMEM|BITS8,0}, "\321\301\2\x0F\xB6\110", IF_386}, + /* 566*/ {I_MOVZX, 2, {REG32,REGMEM|BITS16,0}, "\321\301\2\x0F\xB7\110", IF_386}, + /* 567*/ {I_MUL, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\204", IF_8086}, + /* 568*/ {I_MUL, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\204", IF_8086}, + /* 569*/ {I_MUL, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\204", IF_386}, + /* 570*/ {I_MWAIT, 0, {0,0,0}, "\3\x0F\x01\xC9", IF_PRESCOTT}, + /* 571*/ {I_NEG, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\203", IF_8086}, + /* 572*/ {I_NEG, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\203", IF_8086}, + /* 573*/ {I_NEG, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\203", IF_386}, + /* 574*/ {I_NOP, 0, {0,0,0}, "\1\x90", IF_8086}, + /* 575*/ {I_NOT, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\202", IF_8086}, + /* 576*/ {I_NOT, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\202", IF_8086}, + /* 577*/ {I_NOT, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\202", IF_386}, + /* 578*/ {I_OR, 2, {MEMORY,REG8,0}, "\300\1\x08\101", IF_8086|IF_SM}, + /* 579*/ {I_OR, 2, {REG8,REG8,0}, "\1\x08\101", IF_8086}, + /* 580*/ {I_OR, 2, {MEMORY,REG16,0}, "\320\300\1\x09\101", IF_8086|IF_SM}, + /* 581*/ {I_OR, 2, {REG16,REG16,0}, "\320\1\x09\101", IF_8086}, + /* 582*/ {I_OR, 2, {MEMORY,REG32,0}, "\321\300\1\x09\101", IF_386|IF_SM}, + /* 583*/ {I_OR, 2, {REG32,REG32,0}, "\321\1\x09\101", IF_386}, + /* 584*/ {I_OR, 2, {REG8,MEMORY,0}, "\301\1\x0A\110", IF_8086|IF_SM}, + /* 585*/ {I_OR, 2, {REG8,REG8,0}, "\1\x0A\110", IF_8086}, + /* 586*/ {I_OR, 2, {REG16,MEMORY,0}, "\320\301\1\x0B\110", IF_8086|IF_SM}, + /* 587*/ {I_OR, 2, {REG16,REG16,0}, "\320\1\x0B\110", IF_8086}, + /* 588*/ {I_OR, 2, {REG32,MEMORY,0}, "\321\301\1\x0B\110", IF_386|IF_SM}, + /* 589*/ {I_OR, 2, {REG32,REG32,0}, "\321\1\x0B\110", IF_386}, + /* 590*/ {I_OR, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\201\15", IF_8086}, + /* 591*/ {I_OR, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\201\15", IF_386}, + /* 592*/ {I_OR, 2, {REG_AL,IMMEDIATE,0}, "\1\x0C\21", IF_8086|IF_SM}, + /* 593*/ {I_OR, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x0D\31", IF_8086|IF_SM}, + /* 594*/ {I_OR, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x0D\41", IF_386|IF_SM}, + /* 595*/ {I_OR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\201\21", IF_8086|IF_SM}, + /* 596*/ {I_OR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\201\131", IF_8086|IF_SM}, + /* 597*/ {I_OR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\201\141", IF_386|IF_SM}, + /* 598*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\201\21", IF_8086|IF_SM}, + /* 599*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\201\131", IF_8086|IF_SM}, + /* 600*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\201\141", IF_386|IF_SM}, + /* 601*/ {I_OUT, 2, {IMMEDIATE,REG_AL,0}, "\1\xE6\24", IF_8086|IF_SB}, + /* 602*/ {I_OUT, 2, {IMMEDIATE,REG_AX,0}, "\320\1\xE7\24", IF_8086|IF_SB}, + /* 603*/ {I_OUT, 2, {IMMEDIATE,REG_EAX,0}, "\321\1\xE7\24", IF_386|IF_SB}, + /* 604*/ {I_OUT, 2, {REG_DX,REG_AL,0}, "\1\xEE", IF_8086}, + /* 605*/ {I_OUT, 2, {REG_DX,REG_AX,0}, "\320\1\xEF", IF_8086}, + /* 606*/ {I_OUT, 2, {REG_DX,REG_EAX,0}, "\321\1\xEF", IF_386}, + /* 607*/ {I_OUTSB, 0, {0,0,0}, "\1\x6E", IF_186}, + /* 608*/ {I_OUTSD, 0, {0,0,0}, "\321\1\x6F", IF_386}, + /* 609*/ {I_OUTSW, 0, {0,0,0}, "\320\1\x6F", IF_186}, + /* 610*/ {I_PACKSSDW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6B\110", IF_PENT|IF_MMX|IF_SM}, + /* 611*/ {I_PACKSSDW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6B\110", IF_PENT|IF_MMX}, + /* 612*/ {I_PACKSSWB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x63\110", IF_PENT|IF_MMX|IF_SM}, + /* 613*/ {I_PACKSSWB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x63\110", IF_PENT|IF_MMX}, + /* 614*/ {I_PACKUSWB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x67\110", IF_PENT|IF_MMX|IF_SM}, + /* 615*/ {I_PACKUSWB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x67\110", IF_PENT|IF_MMX}, + /* 616*/ {I_PADDB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFC\110", IF_PENT|IF_MMX|IF_SM}, + /* 617*/ {I_PADDB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFC\110", IF_PENT|IF_MMX}, + /* 618*/ {I_PADDD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFE\110", IF_PENT|IF_MMX|IF_SM}, + /* 619*/ {I_PADDD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFE\110", IF_PENT|IF_MMX}, + /* 620*/ {I_PADDSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEC\110", IF_PENT|IF_MMX|IF_SM}, + /* 621*/ {I_PADDSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEC\110", IF_PENT|IF_MMX}, + /* 622*/ {I_PADDSIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x51\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 623*/ {I_PADDSIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x51\110", IF_PENT|IF_MMX|IF_CYRIX}, + /* 624*/ {I_PADDSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xED\110", IF_PENT|IF_MMX|IF_SM}, + /* 625*/ {I_PADDSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xED\110", IF_PENT|IF_MMX}, + /* 626*/ {I_PADDUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDC\110", IF_PENT|IF_MMX|IF_SM}, + /* 627*/ {I_PADDUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDC\110", IF_PENT|IF_MMX}, + /* 628*/ {I_PADDUSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDD\110", IF_PENT|IF_MMX|IF_SM}, + /* 629*/ {I_PADDUSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDD\110", IF_PENT|IF_MMX}, + /* 630*/ {I_PADDW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFD\110", IF_PENT|IF_MMX|IF_SM}, + /* 631*/ {I_PADDW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFD\110", IF_PENT|IF_MMX}, + /* 632*/ {I_PAND, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDB\110", IF_PENT|IF_MMX|IF_SM}, + /* 633*/ {I_PAND, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDB\110", IF_PENT|IF_MMX}, + /* 634*/ {I_PANDN, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDF\110", IF_PENT|IF_MMX|IF_SM}, + /* 635*/ {I_PANDN, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDF\110", IF_PENT|IF_MMX}, + /* 636*/ {I_PAVEB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x50\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 637*/ {I_PAVEB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x50\110", IF_PENT|IF_MMX|IF_CYRIX}, + /* 638*/ {I_PAVGUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xBF", IF_PENT|IF_3DNOW|IF_SM}, + /* 639*/ {I_PAVGUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xBF", IF_PENT|IF_3DNOW}, + /* 640*/ {I_PCMPEQB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x74\110", IF_PENT|IF_MMX|IF_SM}, + /* 641*/ {I_PCMPEQB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x74\110", IF_PENT|IF_MMX}, + /* 642*/ {I_PCMPEQD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x76\110", IF_PENT|IF_MMX|IF_SM}, + /* 643*/ {I_PCMPEQD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x76\110", IF_PENT|IF_MMX}, + /* 644*/ {I_PCMPEQW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x75\110", IF_PENT|IF_MMX|IF_SM}, + /* 645*/ {I_PCMPEQW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x75\110", IF_PENT|IF_MMX}, + /* 646*/ {I_PCMPGTB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x64\110", IF_PENT|IF_MMX|IF_SM}, + /* 647*/ {I_PCMPGTB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x64\110", IF_PENT|IF_MMX}, + /* 648*/ {I_PCMPGTD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x66\110", IF_PENT|IF_MMX|IF_SM}, + /* 649*/ {I_PCMPGTD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x66\110", IF_PENT|IF_MMX}, + /* 650*/ {I_PCMPGTW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x65\110", IF_PENT|IF_MMX|IF_SM}, + /* 651*/ {I_PCMPGTW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x65\110", IF_PENT|IF_MMX}, + /* 652*/ {I_PDISTIB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x54\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 653*/ {I_PF2ID, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x1D", IF_PENT|IF_3DNOW|IF_SM}, + /* 654*/ {I_PF2ID, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x1D", IF_PENT|IF_3DNOW}, + /* 655*/ {I_PFACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xAE", IF_PENT|IF_3DNOW|IF_SM}, + /* 656*/ {I_PFACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xAE", IF_PENT|IF_3DNOW}, + /* 657*/ {I_PFADD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x9E", IF_PENT|IF_3DNOW|IF_SM}, + /* 658*/ {I_PFADD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x9E", IF_PENT|IF_3DNOW}, + /* 659*/ {I_PFCMPEQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB0", IF_PENT|IF_3DNOW|IF_SM}, + /* 660*/ {I_PFCMPEQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB0", IF_PENT|IF_3DNOW}, + /* 661*/ {I_PFCMPGE, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x90", IF_PENT|IF_3DNOW|IF_SM}, + /* 662*/ {I_PFCMPGE, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x90", IF_PENT|IF_3DNOW}, + /* 663*/ {I_PFCMPGT, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA0", IF_PENT|IF_3DNOW|IF_SM}, + /* 664*/ {I_PFCMPGT, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA0", IF_PENT|IF_3DNOW}, + /* 665*/ {I_PFMAX, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA4", IF_PENT|IF_3DNOW|IF_SM}, + /* 666*/ {I_PFMAX, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA4", IF_PENT|IF_3DNOW}, + /* 667*/ {I_PFMIN, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x94", IF_PENT|IF_3DNOW|IF_SM}, + /* 668*/ {I_PFMIN, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x94", IF_PENT|IF_3DNOW}, + /* 669*/ {I_PFMUL, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB4", IF_PENT|IF_3DNOW|IF_SM}, + /* 670*/ {I_PFMUL, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB4", IF_PENT|IF_3DNOW}, + /* 671*/ {I_PFRCP, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x96", IF_PENT|IF_3DNOW|IF_SM}, + /* 672*/ {I_PFRCP, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x96", IF_PENT|IF_3DNOW}, + /* 673*/ {I_PFRCPIT1, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA6", IF_PENT|IF_3DNOW|IF_SM}, + /* 674*/ {I_PFRCPIT1, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA6", IF_PENT|IF_3DNOW}, + /* 675*/ {I_PFRCPIT2, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB6", IF_PENT|IF_3DNOW|IF_SM}, + /* 676*/ {I_PFRCPIT2, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB6", IF_PENT|IF_3DNOW}, + /* 677*/ {I_PFRSQIT1, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA7", IF_PENT|IF_3DNOW|IF_SM}, + /* 678*/ {I_PFRSQIT1, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA7", IF_PENT|IF_3DNOW}, + /* 679*/ {I_PFRSQRT, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x97", IF_PENT|IF_3DNOW|IF_SM}, + /* 680*/ {I_PFRSQRT, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x97", IF_PENT|IF_3DNOW}, + /* 681*/ {I_PFSUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x9A", IF_PENT|IF_3DNOW|IF_SM}, + /* 682*/ {I_PFSUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x9A", IF_PENT|IF_3DNOW}, + /* 683*/ {I_PFSUBR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xAA", IF_PENT|IF_3DNOW|IF_SM}, + /* 684*/ {I_PFSUBR, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xAA", IF_PENT|IF_3DNOW}, + /* 685*/ {I_PI2FD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x0D", IF_PENT|IF_3DNOW|IF_SM}, + /* 686*/ {I_PI2FD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x0D", IF_PENT|IF_3DNOW}, + /* 687*/ {I_PMACHRIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5E\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 688*/ {I_PMADDWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF5\110", IF_PENT|IF_MMX|IF_SM}, + /* 689*/ {I_PMADDWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF5\110", IF_PENT|IF_MMX}, + /* 690*/ {I_PMAGW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x52\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 691*/ {I_PMAGW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x52\110", IF_PENT|IF_MMX|IF_CYRIX}, + /* 692*/ {I_PMULHRIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5D\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 693*/ {I_PMULHRIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x5D\110", IF_PENT|IF_MMX|IF_CYRIX}, + /* 694*/ {I_PMULHRWA, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\1\xB7", IF_PENT|IF_3DNOW|IF_SM}, + /* 695*/ {I_PMULHRWA, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\1\xB7", IF_PENT|IF_3DNOW}, + /* 696*/ {I_PMULHRWC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x59\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 697*/ {I_PMULHRWC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x59\110", IF_PENT|IF_MMX|IF_CYRIX}, + /* 698*/ {I_PMULHW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE5\110", IF_PENT|IF_MMX|IF_SM}, + /* 699*/ {I_PMULHW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE5\110", IF_PENT|IF_MMX}, + /* 700*/ {I_PMULLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD5\110", IF_PENT|IF_MMX|IF_SM}, + /* 701*/ {I_PMULLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD5\110", IF_PENT|IF_MMX}, + /* 702*/ {I_PMVGEZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5C\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 703*/ {I_PMVLZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5B\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 704*/ {I_PMVNZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5A\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 705*/ {I_PMVZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x58\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 706*/ {I_POP, 1, {REG16,0,0}, "\320\10\x58", IF_8086}, + /* 707*/ {I_POP, 1, {REG32,0,0}, "\321\10\x58", IF_386}, + /* 708*/ {I_POP, 1, {REGMEM|BITS16,0,0}, "\320\300\1\x8F\200", IF_8086}, + /* 709*/ {I_POP, 1, {REGMEM|BITS32,0,0}, "\321\300\1\x8F\200", IF_386}, + /* 710*/ {I_POP, 1, {REG_DESS,0,0}, "\4", IF_8086}, + /* 711*/ {I_POP, 1, {REG_FSGS,0,0}, "\1\x0F\5", IF_386}, + /* 712*/ {I_POPA, 0, {0,0,0}, "\322\1\x61", IF_186}, + /* 713*/ {I_POPAD, 0, {0,0,0}, "\321\1\x61", IF_386}, + /* 714*/ {I_POPAW, 0, {0,0,0}, "\320\1\x61", IF_186}, + /* 715*/ {I_POPF, 0, {0,0,0}, "\322\1\x9D", IF_8086}, + /* 716*/ {I_POPFD, 0, {0,0,0}, "\321\1\x9D", IF_386}, + /* 717*/ {I_POPFW, 0, {0,0,0}, "\320\1\x9D", IF_8086}, + /* 718*/ {I_POR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEB\110", IF_PENT|IF_MMX|IF_SM}, + /* 719*/ {I_POR, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEB\110", IF_PENT|IF_MMX}, + /* 720*/ {I_PREFETCH, 1, {MEMORY,0,0}, "\2\x0F\x0D\200", IF_PENT|IF_3DNOW|IF_SM}, + /* 721*/ {I_PREFETCHW, 1, {MEMORY,0,0}, "\2\x0F\x0D\201", IF_PENT|IF_3DNOW|IF_SM}, + /* 722*/ {I_PSLLD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF2\110", IF_PENT|IF_MMX|IF_SM}, + /* 723*/ {I_PSLLD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF2\110", IF_PENT|IF_MMX}, + /* 724*/ {I_PSLLD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\206\25", IF_PENT|IF_MMX}, + /* 725*/ {I_PSLLQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF3\110", IF_PENT|IF_MMX|IF_SM}, + /* 726*/ {I_PSLLQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF3\110", IF_PENT|IF_MMX}, + /* 727*/ {I_PSLLQ, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x73\206\25", IF_PENT|IF_MMX}, + /* 728*/ {I_PSLLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF1\110", IF_PENT|IF_MMX|IF_SM}, + /* 729*/ {I_PSLLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF1\110", IF_PENT|IF_MMX}, + /* 730*/ {I_PSLLW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\206\25", IF_PENT|IF_MMX}, + /* 731*/ {I_PSRAD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE2\110", IF_PENT|IF_MMX|IF_SM}, + /* 732*/ {I_PSRAD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE2\110", IF_PENT|IF_MMX}, + /* 733*/ {I_PSRAD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\204\25", IF_PENT|IF_MMX}, + /* 734*/ {I_PSRAW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE1\110", IF_PENT|IF_MMX|IF_SM}, + /* 735*/ {I_PSRAW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE1\110", IF_PENT|IF_MMX}, + /* 736*/ {I_PSRAW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\204\25", IF_PENT|IF_MMX}, + /* 737*/ {I_PSRLD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD2\110", IF_PENT|IF_MMX|IF_SM}, + /* 738*/ {I_PSRLD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD2\110", IF_PENT|IF_MMX}, + /* 739*/ {I_PSRLD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\202\25", IF_PENT|IF_MMX}, + /* 740*/ {I_PSRLQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD3\110", IF_PENT|IF_MMX|IF_SM}, + /* 741*/ {I_PSRLQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD3\110", IF_PENT|IF_MMX}, + /* 742*/ {I_PSRLQ, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x73\202\25", IF_PENT|IF_MMX}, + /* 743*/ {I_PSRLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD1\110", IF_PENT|IF_MMX|IF_SM}, + /* 744*/ {I_PSRLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD1\110", IF_PENT|IF_MMX}, + /* 745*/ {I_PSRLW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\202\25", IF_PENT|IF_MMX}, + /* 746*/ {I_PSUBB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF8\110", IF_PENT|IF_MMX|IF_SM}, + /* 747*/ {I_PSUBB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF8\110", IF_PENT|IF_MMX}, + /* 748*/ {I_PSUBD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFA\110", IF_PENT|IF_MMX|IF_SM}, + /* 749*/ {I_PSUBD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFA\110", IF_PENT|IF_MMX}, + /* 750*/ {I_PSUBSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE8\110", IF_PENT|IF_MMX|IF_SM}, + /* 751*/ {I_PSUBSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE8\110", IF_PENT|IF_MMX}, + /* 752*/ {I_PSUBSIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x55\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, + /* 753*/ {I_PSUBSIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x55\110", IF_PENT|IF_MMX|IF_CYRIX}, + /* 754*/ {I_PSUBSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE9\110", IF_PENT|IF_MMX|IF_SM}, + /* 755*/ {I_PSUBSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE9\110", IF_PENT|IF_MMX}, + /* 756*/ {I_PSUBUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD8\110", IF_PENT|IF_MMX|IF_SM}, + /* 757*/ {I_PSUBUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD8\110", IF_PENT|IF_MMX}, + /* 758*/ {I_PSUBUSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD9\110", IF_PENT|IF_MMX|IF_SM}, + /* 759*/ {I_PSUBUSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD9\110", IF_PENT|IF_MMX}, + /* 760*/ {I_PSUBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF9\110", IF_PENT|IF_MMX|IF_SM}, + /* 761*/ {I_PSUBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF9\110", IF_PENT|IF_MMX}, + /* 762*/ {I_PUNPCKHBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x68\110", IF_PENT|IF_MMX|IF_SM}, + /* 763*/ {I_PUNPCKHBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x68\110", IF_PENT|IF_MMX}, + /* 764*/ {I_PUNPCKHDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6A\110", IF_PENT|IF_MMX|IF_SM}, + /* 765*/ {I_PUNPCKHDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6A\110", IF_PENT|IF_MMX}, + /* 766*/ {I_PUNPCKHWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x69\110", IF_PENT|IF_MMX|IF_SM}, + /* 767*/ {I_PUNPCKHWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x69\110", IF_PENT|IF_MMX}, + /* 768*/ {I_PUNPCKLBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x60\110", IF_PENT|IF_MMX|IF_SM}, + /* 769*/ {I_PUNPCKLBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x60\110", IF_PENT|IF_MMX}, + /* 770*/ {I_PUNPCKLDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x62\110", IF_PENT|IF_MMX|IF_SM}, + /* 771*/ {I_PUNPCKLDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x62\110", IF_PENT|IF_MMX}, + /* 772*/ {I_PUNPCKLWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x61\110", IF_PENT|IF_MMX|IF_SM}, + /* 773*/ {I_PUNPCKLWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x61\110", IF_PENT|IF_MMX}, + /* 774*/ {I_PUSH, 1, {REG16,0,0}, "\320\10\x50", IF_8086}, + /* 775*/ {I_PUSH, 1, {REG32,0,0}, "\321\10\x50", IF_386}, + /* 776*/ {I_PUSH, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\206", IF_8086}, + /* 777*/ {I_PUSH, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\206", IF_386}, + /* 778*/ {I_PUSH, 1, {REG_CS,0,0}, "\6", IF_8086}, + /* 779*/ {I_PUSH, 1, {REG_DESS,0,0}, "\6", IF_8086}, + /* 780*/ {I_PUSH, 1, {REG_FSGS,0,0}, "\1\x0F\7", IF_386}, + /* 781*/ {I_PUSH, 1, {IMMEDIATE|BITS8,0,0}, "\1\x6A\14", IF_186}, + /* 782*/ {I_PUSH, 1, {IMMEDIATE|BITS16,0,0}, "\320\133\1\x68\130", IF_186}, + /* 783*/ {I_PUSH, 1, {IMMEDIATE|BITS32,0,0}, "\321\143\1\x68\140", IF_386}, + /* 784*/ {I_PUSH, 1, {IMMEDIATE,0,0}, "\1\x68\34", IF_186}, + /* 785*/ {I_PUSHA, 0, {0,0,0}, "\322\1\x60", IF_186}, + /* 786*/ {I_PUSHAD, 0, {0,0,0}, "\321\1\x60", IF_386}, + /* 787*/ {I_PUSHAW, 0, {0,0,0}, "\320\1\x60", IF_186}, + /* 788*/ {I_PUSHF, 0, {0,0,0}, "\322\1\x9C", IF_8086}, + /* 789*/ {I_PUSHFD, 0, {0,0,0}, "\321\1\x9C", IF_386}, + /* 790*/ {I_PUSHFW, 0, {0,0,0}, "\320\1\x9C", IF_8086}, + /* 791*/ {I_PXOR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEF\110", IF_PENT|IF_MMX|IF_SM}, + /* 792*/ {I_PXOR, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEF\110", IF_PENT|IF_MMX}, + /* 793*/ {I_RCL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\202", IF_8086}, + /* 794*/ {I_RCL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\202", IF_8086}, + /* 795*/ {I_RCL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\202\25", IF_186|IF_SB}, + /* 796*/ {I_RCL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\202", IF_8086}, + /* 797*/ {I_RCL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\202", IF_8086}, + /* 798*/ {I_RCL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\202\25", IF_186|IF_SB}, + /* 799*/ {I_RCL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\202", IF_386}, + /* 800*/ {I_RCL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\202", IF_386}, + /* 801*/ {I_RCL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\202\25", IF_386|IF_SB}, + /* 802*/ {I_RCR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\203", IF_8086}, + /* 803*/ {I_RCR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\203", IF_8086}, + /* 804*/ {I_RCR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\203\25", IF_186|IF_SB}, + /* 805*/ {I_RCR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\203", IF_8086}, + /* 806*/ {I_RCR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\203", IF_8086}, + /* 807*/ {I_RCR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\203\25", IF_186|IF_SB}, + /* 808*/ {I_RCR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\203", IF_386}, + /* 809*/ {I_RCR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\203", IF_386}, + /* 810*/ {I_RCR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\203\25", IF_386|IF_SB}, + /* 811*/ {I_RDSHR, 1, {REGMEM|BITS32,0,0}, "\321\300\2\x0F\x36\200", IF_P6|IF_CYRIX|IF_SMM}, + /* 812*/ {I_RDMSR, 0, {0,0,0}, "\2\x0F\x32", IF_PENT|IF_PRIV}, + /* 813*/ {I_RDPMC, 0, {0,0,0}, "\2\x0F\x33", IF_P6}, + /* 814*/ {I_RDTSC, 0, {0,0,0}, "\2\x0F\x31", IF_PENT}, + /* 815*/ {I_RESB, 1, {IMMEDIATE,0,0}, "\340", IF_8086}, + /* 816*/ {I_RET, 0, {0,0,0}, "\1\xC3", IF_8086}, + /* 817*/ {I_RET, 1, {IMMEDIATE,0,0}, "\1\xC2\30", IF_8086|IF_SW}, + /* 818*/ {I_RETF, 0, {0,0,0}, "\1\xCB", IF_8086}, + /* 819*/ {I_RETF, 1, {IMMEDIATE,0,0}, "\1\xCA\30", IF_8086|IF_SW}, + /* 820*/ {I_RETN, 0, {0,0,0}, "\1\xC3", IF_8086}, + /* 821*/ {I_RETN, 1, {IMMEDIATE,0,0}, "\1\xC2\30", IF_8086|IF_SW}, + /* 822*/ {I_ROL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\200", IF_8086}, + /* 823*/ {I_ROL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\200", IF_8086}, + /* 824*/ {I_ROL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\200\25", IF_186|IF_SB}, + /* 825*/ {I_ROL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\200", IF_8086}, + /* 826*/ {I_ROL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\200", IF_8086}, + /* 827*/ {I_ROL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\200\25", IF_186|IF_SB}, + /* 828*/ {I_ROL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\200", IF_386}, + /* 829*/ {I_ROL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\200", IF_386}, + /* 830*/ {I_ROL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\200\25", IF_386|IF_SB}, + /* 831*/ {I_ROR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\201", IF_8086}, + /* 832*/ {I_ROR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\201", IF_8086}, + /* 833*/ {I_ROR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\201\25", IF_186|IF_SB}, + /* 834*/ {I_ROR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\201", IF_8086}, + /* 835*/ {I_ROR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\201", IF_8086}, + /* 836*/ {I_ROR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\201\25", IF_186|IF_SB}, + /* 837*/ {I_ROR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\201", IF_386}, + /* 838*/ {I_ROR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\201", IF_386}, + /* 839*/ {I_ROR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\201\25", IF_386|IF_SB}, + /* 840*/ {I_RSDC, 2, {REG_SREG,MEMORY|BITS80,0}, "\301\2\x0F\x79\110", IF_486|IF_CYRIX|IF_SMM}, + /* 841*/ {I_RSLDT, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7B\200", IF_486|IF_CYRIX|IF_SMM}, + /* 842*/ {I_RSM, 0, {0,0,0}, "\2\x0F\xAA", IF_PENT|IF_SMM}, + /* 843*/ {I_RSTS, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7D\200", IF_486|IF_CYRIX|IF_SMM}, + /* 844*/ {I_SAHF, 0, {0,0,0}, "\1\x9E", IF_8086}, + /* 845*/ {I_SALC, 0, {0,0,0}, "\1\xD6", IF_8086|IF_UNDOC}, + /* 846*/ {I_SAR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\207", IF_8086}, + /* 847*/ {I_SAR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\207", IF_8086}, + /* 848*/ {I_SAR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\207\25", IF_186|IF_SB}, + /* 849*/ {I_SAR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\207", IF_8086}, + /* 850*/ {I_SAR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\207", IF_8086}, + /* 851*/ {I_SAR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\207\25", IF_186|IF_SB}, + /* 852*/ {I_SAR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\207", IF_386}, + /* 853*/ {I_SAR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\207", IF_386}, + /* 854*/ {I_SAR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\207\25", IF_386|IF_SB}, + /* 855*/ {I_SBB, 2, {MEMORY,REG8,0}, "\300\1\x18\101", IF_8086|IF_SM}, + /* 856*/ {I_SBB, 2, {REG8,REG8,0}, "\1\x18\101", IF_8086}, + /* 857*/ {I_SBB, 2, {MEMORY,REG16,0}, "\320\300\1\x19\101", IF_8086|IF_SM}, + /* 858*/ {I_SBB, 2, {REG16,REG16,0}, "\320\1\x19\101", IF_8086}, + /* 859*/ {I_SBB, 2, {MEMORY,REG32,0}, "\321\300\1\x19\101", IF_386|IF_SM}, + /* 860*/ {I_SBB, 2, {REG32,REG32,0}, "\321\1\x19\101", IF_386}, + /* 861*/ {I_SBB, 2, {REG8,MEMORY,0}, "\301\1\x1A\110", IF_8086|IF_SM}, + /* 862*/ {I_SBB, 2, {REG8,REG8,0}, "\1\x1A\110", IF_8086}, + /* 863*/ {I_SBB, 2, {REG16,MEMORY,0}, "\320\301\1\x1B\110", IF_8086|IF_SM}, + /* 864*/ {I_SBB, 2, {REG16,REG16,0}, "\320\1\x1B\110", IF_8086}, + /* 865*/ {I_SBB, 2, {REG32,MEMORY,0}, "\321\301\1\x1B\110", IF_386|IF_SM}, + /* 866*/ {I_SBB, 2, {REG32,REG32,0}, "\321\1\x1B\110", IF_386}, + /* 867*/ {I_SBB, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\203\15", IF_8086}, + /* 868*/ {I_SBB, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\203\15", IF_386}, + /* 869*/ {I_SBB, 2, {REG_AL,IMMEDIATE,0}, "\1\x1C\21", IF_8086|IF_SM}, + /* 870*/ {I_SBB, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x1D\31", IF_8086|IF_SM}, + /* 871*/ {I_SBB, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x1D\41", IF_386|IF_SM}, + /* 872*/ {I_SBB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\203\21", IF_8086|IF_SM}, + /* 873*/ {I_SBB, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\203\131", IF_8086|IF_SM}, + /* 874*/ {I_SBB, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\203\141", IF_386|IF_SM}, + /* 875*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\203\21", IF_8086|IF_SM}, + /* 876*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\203\131", IF_8086|IF_SM}, + /* 877*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\203\141", IF_386|IF_SM}, + /* 878*/ {I_SCASB, 0, {0,0,0}, "\332\1\xAE", IF_8086}, + /* 879*/ {I_SCASD, 0, {0,0,0}, "\332\321\1\xAF", IF_386}, + /* 880*/ {I_SCASW, 0, {0,0,0}, "\332\320\1\xAF", IF_8086}, + /* 881*/ {I_SGDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\200", IF_286}, + /* 882*/ {I_SHL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\204", IF_8086}, + /* 883*/ {I_SHL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\204", IF_8086}, + /* 884*/ {I_SHL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\204\25", IF_186|IF_SB}, + /* 885*/ {I_SHL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\204", IF_8086}, + /* 886*/ {I_SHL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\204", IF_8086}, + /* 887*/ {I_SHL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\204\25", IF_186|IF_SB}, + /* 888*/ {I_SHL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\204", IF_386}, + /* 889*/ {I_SHL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\204", IF_386}, + /* 890*/ {I_SHL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\204\25", IF_386|IF_SB}, + /* 891*/ {I_SHLD, 3, {MEMORY,REG16,IMMEDIATE}, "\300\320\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 892*/ {I_SHLD, 3, {REG16,REG16,IMMEDIATE}, "\320\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 893*/ {I_SHLD, 3, {MEMORY,REG32,IMMEDIATE}, "\300\321\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 894*/ {I_SHLD, 3, {REG32,REG32,IMMEDIATE}, "\321\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 895*/ {I_SHLD, 3, {MEMORY,REG16,REG_CL}, "\300\320\2\x0F\xA5\101", IF_386|IF_SM}, + /* 896*/ {I_SHLD, 3, {REG16,REG16,REG_CL}, "\320\2\x0F\xA5\101", IF_386}, + /* 897*/ {I_SHLD, 3, {MEMORY,REG32,REG_CL}, "\300\321\2\x0F\xA5\101", IF_386|IF_SM}, + /* 898*/ {I_SHLD, 3, {REG32,REG32,REG_CL}, "\321\2\x0F\xA5\101", IF_386}, + /* 899*/ {I_SHR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\205", IF_8086}, + /* 900*/ {I_SHR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\205", IF_8086}, + /* 901*/ {I_SHR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\205\25", IF_186|IF_SB}, + /* 902*/ {I_SHR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\205", IF_8086}, + /* 903*/ {I_SHR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\205", IF_8086}, + /* 904*/ {I_SHR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\205\25", IF_186|IF_SB}, + /* 905*/ {I_SHR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\205", IF_386}, + /* 906*/ {I_SHR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\205", IF_386}, + /* 907*/ {I_SHR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\205\25", IF_386|IF_SB}, + /* 908*/ {I_SHRD, 3, {MEMORY,REG16,IMMEDIATE}, "\300\320\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 909*/ {I_SHRD, 3, {REG16,REG16,IMMEDIATE}, "\320\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 910*/ {I_SHRD, 3, {MEMORY,REG32,IMMEDIATE}, "\300\321\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 911*/ {I_SHRD, 3, {REG32,REG32,IMMEDIATE}, "\321\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, + /* 912*/ {I_SHRD, 3, {MEMORY,REG16,REG_CL}, "\300\320\2\x0F\xAD\101", IF_386|IF_SM}, + /* 913*/ {I_SHRD, 3, {REG16,REG16,REG_CL}, "\320\2\x0F\xAD\101", IF_386}, + /* 914*/ {I_SHRD, 3, {MEMORY,REG32,REG_CL}, "\300\321\2\x0F\xAD\101", IF_386|IF_SM}, + /* 915*/ {I_SHRD, 3, {REG32,REG32,REG_CL}, "\321\2\x0F\xAD\101", IF_386}, + /* 916*/ {I_SIDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\201", IF_286}, + /* 917*/ {I_SLDT, 1, {MEMORY,0,0}, "\300\1\x0F\17\200", IF_286}, + /* 918*/ {I_SLDT, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\200", IF_286}, + /* 919*/ {I_SLDT, 1, {REG16,0,0}, "\320\1\x0F\17\200", IF_286}, + /* 920*/ {I_SLDT, 1, {REG32,0,0}, "\321\1\x0F\17\200", IF_386}, + /* 921*/ {I_SMI, 0, {0,0,0}, "\1\xF1", IF_386|IF_UNDOC}, + /* 922*/ {I_SMINT, 0, {0,0,0}, "\2\x0F\x38", IF_P6|IF_CYRIX}, + /* 923*/ {I_SMSW, 1, {MEMORY,0,0}, "\300\2\x0F\x01\204", IF_286}, + /* 924*/ {I_SMSW, 1, {MEMORY|BITS16,0,0}, "\300\2\x0F\x01\204", IF_286}, + /* 925*/ {I_SMSW, 1, {REG16,0,0}, "\320\2\x0F\x01\204", IF_286}, + /* 926*/ {I_SMSW, 1, {REG32,0,0}, "\321\2\x0F\x01\204", IF_386}, + /* 927*/ {I_STC, 0, {0,0,0}, "\1\xF9", IF_8086}, + /* 928*/ {I_STD, 0, {0,0,0}, "\1\xFD", IF_8086}, + /* 929*/ {I_STI, 0, {0,0,0}, "\1\xFB", IF_8086}, + /* 930*/ {I_STOSB, 0, {0,0,0}, "\1\xAA", IF_8086}, + /* 931*/ {I_STOSD, 0, {0,0,0}, "\321\1\xAB", IF_386}, + /* 932*/ {I_STOSW, 0, {0,0,0}, "\320\1\xAB", IF_8086}, + /* 933*/ {I_STR, 1, {MEMORY,0,0}, "\300\1\x0F\17\201", IF_286|IF_PROT}, + /* 934*/ {I_STR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\201", IF_286|IF_PROT}, + /* 935*/ {I_STR, 1, {REG16,0,0}, "\320\1\x0F\17\201", IF_286|IF_PROT}, + /* 936*/ {I_STR, 1, {REG32,0,0}, "\321\1\x0F\17\201", IF_386|IF_PROT}, + /* 937*/ {I_SUB, 2, {MEMORY,REG8,0}, "\300\1\x28\101", IF_8086|IF_SM}, + /* 938*/ {I_SUB, 2, {REG8,REG8,0}, "\1\x28\101", IF_8086}, + /* 939*/ {I_SUB, 2, {MEMORY,REG16,0}, "\320\300\1\x29\101", IF_8086|IF_SM}, + /* 940*/ {I_SUB, 2, {REG16,REG16,0}, "\320\1\x29\101", IF_8086}, + /* 941*/ {I_SUB, 2, {MEMORY,REG32,0}, "\321\300\1\x29\101", IF_386|IF_SM}, + /* 942*/ {I_SUB, 2, {REG32,REG32,0}, "\321\1\x29\101", IF_386}, + /* 943*/ {I_SUB, 2, {REG8,MEMORY,0}, "\301\1\x2A\110", IF_8086|IF_SM}, + /* 944*/ {I_SUB, 2, {REG8,REG8,0}, "\1\x2A\110", IF_8086}, + /* 945*/ {I_SUB, 2, {REG16,MEMORY,0}, "\320\301\1\x2B\110", IF_8086|IF_SM}, + /* 946*/ {I_SUB, 2, {REG16,REG16,0}, "\320\1\x2B\110", IF_8086}, + /* 947*/ {I_SUB, 2, {REG32,MEMORY,0}, "\321\301\1\x2B\110", IF_386|IF_SM}, + /* 948*/ {I_SUB, 2, {REG32,REG32,0}, "\321\1\x2B\110", IF_386}, + /* 949*/ {I_SUB, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\205\15", IF_8086}, + /* 950*/ {I_SUB, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\205\15", IF_386}, + /* 951*/ {I_SUB, 2, {REG_AL,IMMEDIATE,0}, "\1\x2C\21", IF_8086|IF_SM}, + /* 952*/ {I_SUB, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x2D\31", IF_8086|IF_SM}, + /* 953*/ {I_SUB, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x2D\41", IF_386|IF_SM}, + /* 954*/ {I_SUB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\205\21", IF_8086|IF_SM}, + /* 955*/ {I_SUB, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\205\131", IF_8086|IF_SM}, + /* 956*/ {I_SUB, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\205\141", IF_386|IF_SM}, + /* 957*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\205\21", IF_8086|IF_SM}, + /* 958*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\205\131", IF_8086|IF_SM}, + /* 959*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\205\141", IF_386|IF_SM}, + /* 960*/ {I_SVDC, 2, {MEMORY|BITS80,REG_SREG,0}, "\300\2\x0F\x78\101", IF_486|IF_CYRIX|IF_SMM}, + /* 961*/ {I_SVLDT, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7A\200", IF_486|IF_CYRIX|IF_SMM}, + /* 962*/ {I_SVTS, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7C\200", IF_486|IF_CYRIX|IF_SMM}, + /* 963*/ {I_SYSCALL, 0, {0,0,0}, "\2\x0F\x05", IF_P6|IF_AMD}, + /* 964*/ {I_SYSENTER, 0, {0,0,0}, "\2\x0F\x34", IF_P6}, + /* 965*/ {I_SYSEXIT, 0, {0,0,0}, "\2\x0F\x35", IF_P6|IF_PRIV}, + /* 966*/ {I_SYSRET, 0, {0,0,0}, "\2\x0F\x07", IF_P6|IF_PRIV|IF_AMD}, + /* 967*/ {I_TEST, 2, {MEMORY,REG8,0}, "\300\1\x84\101", IF_8086|IF_SM}, + /* 968*/ {I_TEST, 2, {REG8,REG8,0}, "\1\x84\101", IF_8086}, + /* 969*/ {I_TEST, 2, {MEMORY,REG16,0}, "\320\300\1\x85\101", IF_8086|IF_SM}, + /* 970*/ {I_TEST, 2, {REG16,REG16,0}, "\320\1\x85\101", IF_8086}, + /* 971*/ {I_TEST, 2, {MEMORY,REG32,0}, "\321\300\1\x85\101", IF_386|IF_SM}, + /* 972*/ {I_TEST, 2, {REG32,REG32,0}, "\321\1\x85\101", IF_386}, + /* 973*/ {I_TEST, 2, {REG8,MEMORY,0}, "\301\1\x84\110", IF_8086|IF_SM}, + /* 974*/ {I_TEST, 2, {REG16,MEMORY,0}, "\320\301\1\x85\110", IF_8086|IF_SM}, + /* 975*/ {I_TEST, 2, {REG32,MEMORY,0}, "\321\301\1\x85\110", IF_386|IF_SM}, + /* 976*/ {I_TEST, 2, {REG_AL,IMMEDIATE,0}, "\1\xA8\21", IF_8086|IF_SM}, + /* 977*/ {I_TEST, 2, {REG_AX,IMMEDIATE,0}, "\320\1\xA9\31", IF_8086|IF_SM}, + /* 978*/ {I_TEST, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\xA9\41", IF_386|IF_SM}, + /* 979*/ {I_TEST, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xF6\200\21", IF_8086|IF_SM}, + /* 980*/ {I_TEST, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xF7\200\31", IF_8086|IF_SM}, + /* 981*/ {I_TEST, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xF7\200\41", IF_386|IF_SM}, + /* 982*/ {I_TEST, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\xF6\200\21", IF_8086|IF_SM}, + /* 983*/ {I_TEST, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\1\xF7\200\31", IF_8086|IF_SM}, + /* 984*/ {I_TEST, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\1\xF7\200\41", IF_386|IF_SM}, + /* 985*/ {I_UD0, 0, {0,0,0}, "\2\x0F\xFF", IF_286|IF_UNDOC}, + /* 986*/ {I_UD1, 0, {0,0,0}, "\2\x0F\xB9", IF_286|IF_UNDOC}, + /* 987*/ {I_UD2, 0, {0,0,0}, "\2\x0F\x0B", IF_286}, + /* 988*/ {I_UMOV, 2, {MEMORY,REG8,0}, "\300\2\x0F\x10\101", IF_386|IF_UNDOC|IF_SM}, + /* 989*/ {I_UMOV, 2, {REG8,REG8,0}, "\2\x0F\x10\101", IF_386|IF_UNDOC}, + /* 990*/ {I_UMOV, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\x11\101", IF_386|IF_UNDOC|IF_SM}, + /* 991*/ {I_UMOV, 2, {REG16,REG16,0}, "\320\2\x0F\x11\101", IF_386|IF_UNDOC}, + /* 992*/ {I_UMOV, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\x11\101", IF_386|IF_UNDOC|IF_SM}, + /* 993*/ {I_UMOV, 2, {REG32,REG32,0}, "\321\2\x0F\x11\101", IF_386|IF_UNDOC}, + /* 994*/ {I_UMOV, 2, {REG8,MEMORY,0}, "\301\2\x0F\x12\110", IF_386|IF_UNDOC|IF_SM}, + /* 995*/ {I_UMOV, 2, {REG8,REG8,0}, "\2\x0F\x12\110", IF_386|IF_UNDOC}, + /* 996*/ {I_UMOV, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x13\110", IF_386|IF_UNDOC|IF_SM}, + /* 997*/ {I_UMOV, 2, {REG16,REG16,0}, "\320\2\x0F\x13\110", IF_386|IF_UNDOC}, + /* 998*/ {I_UMOV, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x13\110", IF_386|IF_UNDOC|IF_SM}, + /* 999*/ {I_UMOV, 2, {REG32,REG32,0}, "\321\2\x0F\x13\110", IF_386|IF_UNDOC}, + /*1000*/ {I_VERR, 1, {MEMORY,0,0}, "\300\1\x0F\17\204", IF_286|IF_PROT}, + /*1001*/ {I_VERR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\204", IF_286|IF_PROT}, + /*1002*/ {I_VERR, 1, {REG16,0,0}, "\1\x0F\17\204", IF_286|IF_PROT}, + /*1003*/ {I_VERW, 1, {MEMORY,0,0}, "\300\1\x0F\17\205", IF_286|IF_PROT}, + /*1004*/ {I_VERW, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\205", IF_286|IF_PROT}, + /*1005*/ {I_VERW, 1, {REG16,0,0}, "\1\x0F\17\205", IF_286|IF_PROT}, + /*1006*/ {I_WAIT, 0, {0,0,0}, "\1\x9B", IF_8086}, + /*1007*/ {I_FWAIT, 0, {0,0,0}, "\1\x9B", IF_8086}, + /*1008*/ {I_WBINVD, 0, {0,0,0}, "\2\x0F\x09", IF_486|IF_PRIV}, + /*1009*/ {I_WRSHR, 1, {REGMEM|BITS32,0,0}, "\321\300\2\x0F\x37\200", IF_P6|IF_CYRIX|IF_SMM}, + /*1010*/ {I_WRMSR, 0, {0,0,0}, "\2\x0F\x30", IF_PENT|IF_PRIV}, + /*1011*/ {I_XADD, 2, {MEMORY,REG8,0}, "\300\2\x0F\xC0\101", IF_486|IF_SM}, + /*1012*/ {I_XADD, 2, {REG8,REG8,0}, "\2\x0F\xC0\101", IF_486}, + /*1013*/ {I_XADD, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xC1\101", IF_486|IF_SM}, + /*1014*/ {I_XADD, 2, {REG16,REG16,0}, "\320\2\x0F\xC1\101", IF_486}, + /*1015*/ {I_XADD, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xC1\101", IF_486|IF_SM}, + /*1016*/ {I_XADD, 2, {REG32,REG32,0}, "\321\2\x0F\xC1\101", IF_486}, + /*1017*/ {I_XCHG, 2, {REG_AX,REG16,0}, "\320\11\x90", IF_8086}, + /*1018*/ {I_XCHG, 2, {REG_EAX,REG32,0}, "\321\11\x90", IF_386}, + /*1019*/ {I_XCHG, 2, {REG16,REG_AX,0}, "\320\10\x90", IF_8086}, + /*1020*/ {I_XCHG, 2, {REG32,REG_EAX,0}, "\321\10\x90", IF_386}, + /*1021*/ {I_XCHG, 2, {REG8,MEMORY,0}, "\301\1\x86\110", IF_8086|IF_SM}, + /*1022*/ {I_XCHG, 2, {REG8,REG8,0}, "\1\x86\110", IF_8086}, + /*1023*/ {I_XCHG, 2, {REG16,MEMORY,0}, "\320\301\1\x87\110", IF_8086|IF_SM}, + /*1024*/ {I_XCHG, 2, {REG16,REG16,0}, "\320\1\x87\110", IF_8086}, + /*1025*/ {I_XCHG, 2, {REG32,MEMORY,0}, "\321\301\1\x87\110", IF_386|IF_SM}, + /*1026*/ {I_XCHG, 2, {REG32,REG32,0}, "\321\1\x87\110", IF_386}, + /*1027*/ {I_XCHG, 2, {MEMORY,REG8,0}, "\300\1\x86\101", IF_8086|IF_SM}, + /*1028*/ {I_XCHG, 2, {REG8,REG8,0}, "\1\x86\101", IF_8086}, + /*1029*/ {I_XCHG, 2, {MEMORY,REG16,0}, "\320\300\1\x87\101", IF_8086|IF_SM}, + /*1030*/ {I_XCHG, 2, {REG16,REG16,0}, "\320\1\x87\101", IF_8086}, + /*1031*/ {I_XCHG, 2, {MEMORY,REG32,0}, "\321\300\1\x87\101", IF_386|IF_SM}, + /*1032*/ {I_XCHG, 2, {REG32,REG32,0}, "\321\1\x87\101", IF_386}, + /*1033*/ {I_XLATB, 0, {0,0,0}, "\1\xD7", IF_8086}, + /*1034*/ {I_XLAT, 0, {0,0,0}, "\1\xD7", IF_8086}, + /*1035*/ {I_XOR, 2, {MEMORY,REG8,0}, "\300\1\x30\101", IF_8086|IF_SM}, + /*1036*/ {I_XOR, 2, {REG8,REG8,0}, "\1\x30\101", IF_8086}, + /*1037*/ {I_XOR, 2, {MEMORY,REG16,0}, "\320\300\1\x31\101", IF_8086|IF_SM}, + /*1038*/ {I_XOR, 2, {REG16,REG16,0}, "\320\1\x31\101", IF_8086}, + /*1039*/ {I_XOR, 2, {MEMORY,REG32,0}, "\321\300\1\x31\101", IF_386|IF_SM}, + /*1040*/ {I_XOR, 2, {REG32,REG32,0}, "\321\1\x31\101", IF_386}, + /*1041*/ {I_XOR, 2, {REG8,MEMORY,0}, "\301\1\x32\110", IF_8086|IF_SM}, + /*1042*/ {I_XOR, 2, {REG8,REG8,0}, "\1\x32\110", IF_8086}, + /*1043*/ {I_XOR, 2, {REG16,MEMORY,0}, "\320\301\1\x33\110", IF_8086|IF_SM}, + /*1044*/ {I_XOR, 2, {REG16,REG16,0}, "\320\1\x33\110", IF_8086}, + /*1045*/ {I_XOR, 2, {REG32,MEMORY,0}, "\321\301\1\x33\110", IF_386|IF_SM}, + /*1046*/ {I_XOR, 2, {REG32,REG32,0}, "\321\1\x33\110", IF_386}, + /*1047*/ {I_XOR, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\206\15", IF_8086}, + /*1048*/ {I_XOR, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\206\15", IF_386}, + /*1049*/ {I_XOR, 2, {REG_AL,IMMEDIATE,0}, "\1\x34\21", IF_8086|IF_SM}, + /*1050*/ {I_XOR, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x35\31", IF_8086|IF_SM}, + /*1051*/ {I_XOR, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x35\41", IF_386|IF_SM}, + /*1052*/ {I_XOR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\206\21", IF_8086|IF_SM}, + /*1053*/ {I_XOR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\206\131", IF_8086|IF_SM}, + /*1054*/ {I_XOR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\206\141", IF_386|IF_SM}, + /*1055*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\206\21", IF_8086|IF_SM}, + /*1056*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\206\131", IF_8086|IF_SM}, + /*1057*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\206\141", IF_386|IF_SM}, + /*1058*/ {I_XSTORE, 0, {0,0,0}, "\3\x0F\xA7\xC0", IF_P6|IF_CYRIX}, + /*1059*/ {I_CMOVcc, 2, {REG16,MEMORY,0}, "\320\301\1\x0F\330\x40\110", IF_P6|IF_SM}, + /*1060*/ {I_CMOVcc, 2, {REG16,REG16,0}, "\320\1\x0F\330\x40\110", IF_P6}, + /*1061*/ {I_CMOVcc, 2, {REG32,MEMORY,0}, "\321\301\1\x0F\330\x40\110", IF_P6|IF_SM}, + /*1062*/ {I_CMOVcc, 2, {REG32,REG32,0}, "\321\1\x0F\330\x40\110", IF_P6}, + /*1063*/ {I_Jcc, 1, {IMMEDIATE|NEAR,0,0}, "\322\1\x0F\330\x80\64", IF_386}, + /*1064*/ {I_Jcc, 1, {IMMEDIATE|BITS16|NEAR,0,0}, "\320\1\x0F\330\x80\64", IF_386}, + /*1065*/ {I_Jcc, 1, {IMMEDIATE|BITS32|NEAR,0,0}, "\321\1\x0F\330\x80\64", IF_386}, + /*1066*/ {I_Jcc, 1, {IMMEDIATE,0,0}, "\330\x70\50", IF_8086}, + /*1067*/ {I_SETcc, 1, {MEMORY,0,0}, "\300\1\x0F\330\x90\200", IF_386|IF_SB}, + /*1068*/ {I_SETcc, 1, {REG8,0,0}, "\300\1\x0F\330\x90\200", IF_386}, + /*1069*/ {I_ADDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x58\110", IF_KATMAI|IF_SSE}, + /*1070*/ {I_ADDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x58\110", IF_KATMAI|IF_SSE}, + /*1071*/ {I_ADDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x58\110", IF_KATMAI|IF_SSE}, + /*1072*/ {I_ADDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x58\110", IF_KATMAI|IF_SSE}, + /*1073*/ {I_ANDNPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x55\110", IF_KATMAI|IF_SSE}, + /*1074*/ {I_ANDNPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x55\110", IF_KATMAI|IF_SSE}, + /*1075*/ {I_ANDPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x54\110", IF_KATMAI|IF_SSE}, + /*1076*/ {I_ANDPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x54\110", IF_KATMAI|IF_SSE}, + /*1077*/ {I_CMPEQPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, + /*1078*/ {I_CMPEQPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, + /*1079*/ {I_CMPEQSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, + /*1080*/ {I_CMPEQSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, + /*1081*/ {I_CMPLEPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, + /*1082*/ {I_CMPLEPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, + /*1083*/ {I_CMPLESS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, + /*1084*/ {I_CMPLESS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, + /*1085*/ {I_CMPLTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, + /*1086*/ {I_CMPLTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, + /*1087*/ {I_CMPLTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, + /*1088*/ {I_CMPLTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, + /*1089*/ {I_CMPNEQPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, + /*1090*/ {I_CMPNEQPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, + /*1091*/ {I_CMPNEQSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, + /*1092*/ {I_CMPNEQSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, + /*1093*/ {I_CMPNLEPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, + /*1094*/ {I_CMPNLEPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, + /*1095*/ {I_CMPNLESS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, + /*1096*/ {I_CMPNLESS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, + /*1097*/ {I_CMPNLTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, + /*1098*/ {I_CMPNLTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, + /*1099*/ {I_CMPNLTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, + /*1100*/ {I_CMPNLTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, + /*1101*/ {I_CMPORDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, + /*1102*/ {I_CMPORDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, + /*1103*/ {I_CMPORDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, + /*1104*/ {I_CMPORDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, + /*1105*/ {I_CMPUNORDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, + /*1106*/ {I_CMPUNORDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, + /*1107*/ {I_CMPUNORDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, + /*1108*/ {I_CMPUNORDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, + /*1109*/ {I_CMPPS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, + /*1110*/ {I_CMPPS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, + /*1111*/ {I_CMPSS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\333\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, + /*1112*/ {I_CMPSS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\333\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, + /*1113*/ {I_COMISS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x2F\110", IF_KATMAI|IF_SSE}, + /*1114*/ {I_COMISS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x2F\110", IF_KATMAI|IF_SSE}, + /*1115*/ {I_CVTPI2PS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_MMX}, + /*1116*/ {I_CVTPI2PS, 2, {XMMREG,MMXREG,0}, "\331\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_MMX}, + /*1117*/ {I_CVTPS2PI, 2, {MMXREG,MEMORY,0}, "\301\331\2\x0F\x2D\110", IF_KATMAI|IF_SSE|IF_MMX}, + /*1118*/ {I_CVTPS2PI, 2, {MMXREG,XMMREG,0}, "\331\2\x0F\x2D\110", IF_KATMAI|IF_SSE|IF_MMX}, + /*1119*/ {I_CVTSI2SS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_SD|IF_AR1}, + /*1120*/ {I_CVTSI2SS, 2, {XMMREG,REG32,0}, "\333\2\x0F\x2A\110", IF_KATMAI|IF_SSE}, + /*1121*/ {I_CVTSS2SI, 2, {REG32,MEMORY,0}, "\301\333\2\x0F\x2D\110", IF_KATMAI|IF_SSE}, + /*1122*/ {I_CVTSS2SI, 2, {REG32,XMMREG,0}, "\333\2\x0F\x2D\110", IF_KATMAI|IF_SSE}, + /*1123*/ {I_CVTTPS2PI, 2, {MMXREG,MEMORY,0}, "\301\331\2\x0F\x2C\110", IF_KATMAI|IF_SSE|IF_MMX}, + /*1124*/ {I_CVTTPS2PI, 2, {MMXREG,XMMREG,0}, "\331\2\x0F\x2C\110", IF_KATMAI|IF_SSE|IF_MMX}, + /*1125*/ {I_CVTTSS2SI, 2, {REG32,MEMORY,0}, "\301\333\2\x0F\x2C\110", IF_KATMAI|IF_SSE}, + /*1126*/ {I_CVTTSS2SI, 2, {REG32,XMMREG,0}, "\333\2\x0F\x2C\110", IF_KATMAI|IF_SSE}, + /*1127*/ {I_DIVPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, + /*1128*/ {I_DIVPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, + /*1129*/ {I_DIVSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, + /*1130*/ {I_DIVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, + /*1131*/ {I_LDMXCSR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\202", IF_KATMAI|IF_SSE|IF_SD}, + /*1132*/ {I_MAXPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, + /*1133*/ {I_MAXPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, + /*1134*/ {I_MAXSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, + /*1135*/ {I_MAXSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, + /*1136*/ {I_MINPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, + /*1137*/ {I_MINPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, + /*1138*/ {I_MINSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, + /*1139*/ {I_MINSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, + /*1140*/ {I_MOVAPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x28\110", IF_KATMAI|IF_SSE}, + /*1141*/ {I_MOVAPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x29\101", IF_KATMAI|IF_SSE}, + /*1142*/ {I_MOVAPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x28\110", IF_KATMAI|IF_SSE}, + /*1143*/ {I_MOVAPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x29\101", IF_KATMAI|IF_SSE}, + /*1144*/ {I_MOVHPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x16\110", IF_KATMAI|IF_SSE}, + /*1145*/ {I_MOVHPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x17\101", IF_KATMAI|IF_SSE}, + /*1146*/ {I_MOVLHPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x16\110", IF_KATMAI|IF_SSE}, + /*1147*/ {I_MOVLPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x12\110", IF_KATMAI|IF_SSE}, + /*1148*/ {I_MOVLPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x13\101", IF_KATMAI|IF_SSE}, + /*1149*/ {I_MOVHLPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x12\110", IF_KATMAI|IF_SSE}, + /*1150*/ {I_MOVMSKPS, 2, {REG32,XMMREG,0}, "\2\x0F\x50\110", IF_KATMAI|IF_SSE}, + /*1151*/ {I_MOVNTPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x2B\101", IF_KATMAI|IF_SSE}, + /*1152*/ {I_MOVSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x10\110", IF_KATMAI|IF_SSE}, + /*1153*/ {I_MOVSS, 2, {MEMORY,XMMREG,0}, "\300\333\2\x0F\x11\101", IF_KATMAI|IF_SSE}, + /*1154*/ {I_MOVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x10\110", IF_KATMAI|IF_SSE}, + /*1155*/ {I_MOVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x11\101", IF_KATMAI|IF_SSE}, + /*1156*/ {I_MOVUPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x10\110", IF_KATMAI|IF_SSE}, + /*1157*/ {I_MOVUPS, 2, {MEMORY,XMMREG,0}, "\300\331\2\x0F\x11\101", IF_KATMAI|IF_SSE}, + /*1158*/ {I_MOVUPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x10\110", IF_KATMAI|IF_SSE}, + /*1159*/ {I_MOVUPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x11\101", IF_KATMAI|IF_SSE}, + /*1160*/ {I_MULPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x59\110", IF_KATMAI|IF_SSE}, + /*1161*/ {I_MULPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x59\110", IF_KATMAI|IF_SSE}, + /*1162*/ {I_MULSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x59\110", IF_KATMAI|IF_SSE}, + /*1163*/ {I_MULSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x59\110", IF_KATMAI|IF_SSE}, + /*1164*/ {I_ORPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x56\110", IF_KATMAI|IF_SSE}, + /*1165*/ {I_ORPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x56\110", IF_KATMAI|IF_SSE}, + /*1166*/ {I_RCPPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x53\110", IF_KATMAI|IF_SSE}, + /*1167*/ {I_RCPPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x53\110", IF_KATMAI|IF_SSE}, + /*1168*/ {I_RCPSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x53\110", IF_KATMAI|IF_SSE}, + /*1169*/ {I_RCPSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x53\110", IF_KATMAI|IF_SSE}, + /*1170*/ {I_RSQRTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x52\110", IF_KATMAI|IF_SSE}, + /*1171*/ {I_RSQRTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x52\110", IF_KATMAI|IF_SSE}, + /*1172*/ {I_RSQRTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x52\110", IF_KATMAI|IF_SSE}, + /*1173*/ {I_RSQRTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x52\110", IF_KATMAI|IF_SSE}, + /*1174*/ {I_SHUFPS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\2\x0F\xC6\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, + /*1175*/ {I_SHUFPS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\2\x0F\xC6\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, + /*1176*/ {I_SQRTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x51\110", IF_KATMAI|IF_SSE}, + /*1177*/ {I_SQRTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x51\110", IF_KATMAI|IF_SSE}, + /*1178*/ {I_SQRTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x51\110", IF_KATMAI|IF_SSE}, + /*1179*/ {I_SQRTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x51\110", IF_KATMAI|IF_SSE}, + /*1180*/ {I_STMXCSR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\203", IF_KATMAI|IF_SSE|IF_SD}, + /*1181*/ {I_SUBPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, + /*1182*/ {I_SUBPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, + /*1183*/ {I_SUBSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, + /*1184*/ {I_SUBSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, + /*1185*/ {I_UCOMISS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x2E\110", IF_KATMAI|IF_SSE}, + /*1186*/ {I_UCOMISS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x2E\110", IF_KATMAI|IF_SSE}, + /*1187*/ {I_UNPCKHPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x15\110", IF_KATMAI|IF_SSE}, + /*1188*/ {I_UNPCKHPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x15\110", IF_KATMAI|IF_SSE}, + /*1189*/ {I_UNPCKLPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x14\110", IF_KATMAI|IF_SSE}, + /*1190*/ {I_UNPCKLPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x14\110", IF_KATMAI|IF_SSE}, + /*1191*/ {I_XORPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x57\110", IF_KATMAI|IF_SSE}, + /*1192*/ {I_XORPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x57\110", IF_KATMAI|IF_SSE}, + /*1193*/ {I_FXRSTOR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\201", IF_P6|IF_SSE|IF_FPU}, + /*1194*/ {I_FXSAVE, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\200", IF_P6|IF_SSE|IF_FPU}, + /*1195*/ {I_PREFETCHNTA, 1, {MEMORY,0,0}, "\300\2\x0F\x18\200", IF_KATMAI}, + /*1196*/ {I_PREFETCHT0, 1, {MEMORY,0,0}, "\300\2\x0F\x18\201", IF_KATMAI}, + /*1197*/ {I_PREFETCHT1, 1, {MEMORY,0,0}, "\300\2\x0F\x18\202", IF_KATMAI}, + /*1198*/ {I_PREFETCHT2, 1, {MEMORY,0,0}, "\300\2\x0F\x18\203", IF_KATMAI}, + /*1199*/ {I_SFENCE, 0, {0,0,0}, "\3\x0F\xAE\xF8", IF_KATMAI}, + /*1200*/ {I_MASKMOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF7\110", IF_KATMAI|IF_MMX}, + /*1201*/ {I_MOVNTQ, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\xE7\101", IF_KATMAI|IF_MMX|IF_SM}, + /*1202*/ {I_PAVGB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE0\110", IF_KATMAI|IF_MMX}, + /*1203*/ {I_PAVGB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE0\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1204*/ {I_PAVGW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE3\110", IF_KATMAI|IF_MMX}, + /*1205*/ {I_PAVGW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE3\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1206*/ {I_PEXTRW, 3, {REG32,MMXREG,IMMEDIATE}, "\2\x0F\xC5\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, + /*1207*/ {I_PINSRW, 3, {MMXREG,REG16,IMMEDIATE}, "\2\x0F\xC4\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, + /*1208*/ {I_PINSRW, 3, {MMXREG,MEMORY,IMMEDIATE}, "\301\2\x0F\xC4\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, + /*1209*/ {I_PMAXSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEE\110", IF_KATMAI|IF_MMX}, + /*1210*/ {I_PMAXSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEE\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1211*/ {I_PMAXUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDE\110", IF_KATMAI|IF_MMX}, + /*1212*/ {I_PMAXUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDE\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1213*/ {I_PMINSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEA\110", IF_KATMAI|IF_MMX}, + /*1214*/ {I_PMINSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEA\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1215*/ {I_PMINUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDA\110", IF_KATMAI|IF_MMX}, + /*1216*/ {I_PMINUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDA\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1217*/ {I_PMOVMSKB, 2, {REG32,MMXREG,0}, "\2\x0F\xD7\110", IF_KATMAI|IF_MMX}, + /*1218*/ {I_PMULHUW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE4\110", IF_KATMAI|IF_MMX}, + /*1219*/ {I_PMULHUW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE4\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1220*/ {I_PSADBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF6\110", IF_KATMAI|IF_MMX}, + /*1221*/ {I_PSADBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF6\110", IF_KATMAI|IF_MMX|IF_SM}, + /*1222*/ {I_PSHUFW, 3, {MMXREG,MMXREG,IMMEDIATE}, "\2\x0F\x70\110\22", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, + /*1223*/ {I_PSHUFW, 3, {MMXREG,MEMORY,IMMEDIATE}, "\301\2\x0F\x70\110\22", IF_KATMAI|IF_MMX|IF_SM2|IF_SB|IF_AR2}, + /*1224*/ {I_PF2IW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x1C", IF_PENT|IF_3DNOW|IF_SM}, + /*1225*/ {I_PF2IW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x1C", IF_PENT|IF_3DNOW}, + /*1226*/ {I_PFNACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x8A", IF_PENT|IF_3DNOW|IF_SM}, + /*1227*/ {I_PFNACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x8A", IF_PENT|IF_3DNOW}, + /*1228*/ {I_PFPNACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x8E", IF_PENT|IF_3DNOW|IF_SM}, + /*1229*/ {I_PFPNACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x8E", IF_PENT|IF_3DNOW}, + /*1230*/ {I_PI2FW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x0C", IF_PENT|IF_3DNOW|IF_SM}, + /*1231*/ {I_PI2FW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x0C", IF_PENT|IF_3DNOW}, + /*1232*/ {I_PSWAPD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xBB", IF_PENT|IF_3DNOW|IF_SM}, + /*1233*/ {I_PSWAPD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xBB", IF_PENT|IF_3DNOW}, + /*1234*/ {I_MASKMOVDQU, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF7\110", IF_WILLAMETTE|IF_SSE2}, + /*1235*/ {I_CLFLUSH, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\207", IF_WILLAMETTE|IF_SSE2}, + /*1236*/ {I_MOVNTDQ, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\xE7\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1237*/ {I_MOVNTI, 2, {MEMORY,REG32,0}, "\300\2\x0F\xC3\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1238*/ {I_MOVNTPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x2B\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1239*/ {I_PAUSE, 0, {0,0,0}, "\333\1\x90", IF_WILLAMETTE|IF_SSE2}, + /*1240*/ {I_LFENCE, 0, {0,0,0}, "\3\x0F\xAE\xE8", IF_WILLAMETTE|IF_SSE2}, + /*1241*/ {I_MFENCE, 0, {0,0,0}, "\3\x0F\xAE\xF0", IF_WILLAMETTE|IF_SSE2}, + /*1242*/ {I_MOVD, 2, {XMMREG,REG32,0}, "\3\x66\x0F\x6E\110", IF_WILLAMETTE|IF_SSE2}, + /*1243*/ {I_MOVD, 2, {REG32,XMMREG,0}, "\3\x66\x0F\x7E\101", IF_WILLAMETTE|IF_SSE2}, + /*1244*/ {I_MOVD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x7E\101", IF_WILLAMETTE|IF_SSE2}, + /*1245*/ {I_MOVD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6E\110", IF_WILLAMETTE|IF_SSE2}, + /*1246*/ {I_MOVDQA, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2}, + /*1247*/ {I_MOVDQA, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x7F\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1248*/ {I_MOVDQA, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1249*/ {I_MOVDQA, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7F\110", IF_WILLAMETTE|IF_SSE2}, + /*1250*/ {I_MOVDQU, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2}, + /*1251*/ {I_MOVDQU, 2, {MEMORY,XMMREG,0}, "\333\300\2\x0F\x7F\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1252*/ {I_MOVDQU, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1253*/ {I_MOVDQU, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x7F\110", IF_WILLAMETTE|IF_SSE2}, + /*1254*/ {I_MOVDQ2Q, 2, {MMXREG,XMMREG,0}, "\3\xF2\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, + /*1255*/ {I_MOVQ, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x7E\110", IF_WILLAMETTE|IF_SSE2}, + /*1256*/ {I_MOVQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, + /*1257*/ {I_MOVQ, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\xD6\101", IF_WILLAMETTE|IF_SSE2}, + /*1258*/ {I_MOVQ, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x7E\110", IF_WILLAMETTE|IF_SSE2}, + /*1259*/ {I_MOVQ2DQ, 2, {XMMREG,MMXREG,0}, "\333\2\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, + /*1260*/ {I_PACKSSWB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x63\110", IF_WILLAMETTE|IF_SSE2}, + /*1261*/ {I_PACKSSWB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x63\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1262*/ {I_PACKSSDW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6B\110", IF_WILLAMETTE|IF_SSE2}, + /*1263*/ {I_PACKSSDW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1264*/ {I_PACKUSWB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x67\110", IF_WILLAMETTE|IF_SSE2}, + /*1265*/ {I_PACKUSWB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x67\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1266*/ {I_PADDB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFC\110", IF_WILLAMETTE|IF_SSE2}, + /*1267*/ {I_PADDB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1268*/ {I_PADDW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFD\110", IF_WILLAMETTE|IF_SSE2}, + /*1269*/ {I_PADDW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFD\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1270*/ {I_PADDD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFE\110", IF_WILLAMETTE|IF_SSE2}, + /*1271*/ {I_PADDD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1272*/ {I_PADDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2}, + /*1273*/ {I_PADDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1274*/ {I_PADDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2}, + /*1275*/ {I_PADDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1276*/ {I_PADDSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1277*/ {I_PADDSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEC\110", IF_WILLAMETTE|IF_SSE2}, + /*1278*/ {I_PADDSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xED\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1279*/ {I_PADDSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xED\110", IF_WILLAMETTE|IF_SSE2}, + /*1280*/ {I_PADDUSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1281*/ {I_PADDUSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDC\110", IF_WILLAMETTE|IF_SSE2}, + /*1282*/ {I_PADDUSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDD\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1283*/ {I_PADDUSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDD\110", IF_WILLAMETTE|IF_SSE2}, + /*1284*/ {I_PAND, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDB\110", IF_WILLAMETTE|IF_SSE2}, + /*1285*/ {I_PAND, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1286*/ {I_PANDN, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDF\110", IF_WILLAMETTE|IF_SSE2}, + /*1287*/ {I_PANDN, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDF\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1288*/ {I_PAVGB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE0\110", IF_WILLAMETTE|IF_SSE2}, + /*1289*/ {I_PAVGB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE0\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1290*/ {I_PAVGW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE3\110", IF_WILLAMETTE|IF_SSE2}, + /*1291*/ {I_PAVGW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1292*/ {I_PCMPEQB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x74\110", IF_WILLAMETTE|IF_SSE2}, + /*1293*/ {I_PCMPEQB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x74\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1294*/ {I_PCMPEQW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x75\110", IF_WILLAMETTE|IF_SSE2}, + /*1295*/ {I_PCMPEQW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x75\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1296*/ {I_PCMPEQD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x76\110", IF_WILLAMETTE|IF_SSE2}, + /*1297*/ {I_PCMPEQD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x76\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1298*/ {I_PCMPGTB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x64\110", IF_WILLAMETTE|IF_SSE2}, + /*1299*/ {I_PCMPGTB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x64\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1300*/ {I_PCMPGTW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x65\110", IF_WILLAMETTE|IF_SSE2}, + /*1301*/ {I_PCMPGTW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x65\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1302*/ {I_PCMPGTD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x66\110", IF_WILLAMETTE|IF_SSE2}, + /*1303*/ {I_PCMPGTD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x66\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1304*/ {I_PEXTRW, 3, {REG32,XMMREG,IMMEDIATE}, "\3\x66\x0F\xC5\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1305*/ {I_PINSRW, 3, {XMMREG,REG16,IMMEDIATE}, "\3\x66\x0F\xC4\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1306*/ {I_PINSRW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\xC4\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1307*/ {I_PMADDWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1308*/ {I_PMADDWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF5\110", IF_WILLAMETTE|IF_SSE2}, + /*1309*/ {I_PMAXSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEE\110", IF_WILLAMETTE|IF_SSE2}, + /*1310*/ {I_PMAXSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1311*/ {I_PMAXUB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDE\110", IF_WILLAMETTE|IF_SSE2}, + /*1312*/ {I_PMAXUB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1313*/ {I_PMINSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEA\110", IF_WILLAMETTE|IF_SSE2}, + /*1314*/ {I_PMINSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1315*/ {I_PMINUB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDA\110", IF_WILLAMETTE|IF_SSE2}, + /*1316*/ {I_PMINUB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1317*/ {I_PMOVMSKB, 2, {REG32,XMMREG,0}, "\3\x66\x0F\xD7\110", IF_WILLAMETTE|IF_SSE2}, + /*1318*/ {I_PMULHUW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE4\110", IF_WILLAMETTE|IF_SSE2}, + /*1319*/ {I_PMULHUW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1320*/ {I_PMULHW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1321*/ {I_PMULHW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE5\110", IF_WILLAMETTE|IF_SSE2}, + /*1322*/ {I_PMULLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1323*/ {I_PMULLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD5\110", IF_WILLAMETTE|IF_SSE2}, + /*1324*/ {I_PMULUDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2}, + /*1325*/ {I_PMULUDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1326*/ {I_PMULUDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2}, + /*1327*/ {I_PMULUDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1328*/ {I_POR, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1329*/ {I_POR, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEB\110", IF_WILLAMETTE|IF_SSE2}, + /*1330*/ {I_PSADBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF6\110", IF_WILLAMETTE|IF_SSE2}, + /*1331*/ {I_PSADBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1332*/ {I_PSHUFD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\x66\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1333*/ {I_PSHUFD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, + /*1334*/ {I_PSHUFHW, 3, {XMMREG,XMMREG,IMMEDIATE}, "\333\2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1335*/ {I_PSHUFHW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\333\2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, + /*1336*/ {I_PSHUFLW, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\xF2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1337*/ {I_PSHUFLW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\xF2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, + /*1338*/ {I_PSLLDQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\207\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1339*/ {I_PSLLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1340*/ {I_PSLLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF1\110", IF_WILLAMETTE|IF_SSE2}, + /*1341*/ {I_PSLLW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1342*/ {I_PSLLD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1343*/ {I_PSLLD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF2\110", IF_WILLAMETTE|IF_SSE2}, + /*1344*/ {I_PSLLD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1345*/ {I_PSLLQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1346*/ {I_PSLLQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF3\110", IF_WILLAMETTE|IF_SSE2}, + /*1347*/ {I_PSLLQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1348*/ {I_PSRAW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1349*/ {I_PSRAW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE1\110", IF_WILLAMETTE|IF_SSE2}, + /*1350*/ {I_PSRAW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\204\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1351*/ {I_PSRAD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1352*/ {I_PSRAD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE2\110", IF_WILLAMETTE|IF_SSE2}, + /*1353*/ {I_PSRAD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\204\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1354*/ {I_PSRLDQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\203\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1355*/ {I_PSRLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1356*/ {I_PSRLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD1\110", IF_WILLAMETTE|IF_SSE2}, + /*1357*/ {I_PSRLW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1358*/ {I_PSRLD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1359*/ {I_PSRLD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD2\110", IF_WILLAMETTE|IF_SSE2}, + /*1360*/ {I_PSRLD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1361*/ {I_PSRLQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1362*/ {I_PSRLQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD3\110", IF_WILLAMETTE|IF_SSE2}, + /*1363*/ {I_PSRLQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, + /*1364*/ {I_PSUBB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1365*/ {I_PSUBB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF8\110", IF_WILLAMETTE|IF_SSE2}, + /*1366*/ {I_PSUBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1367*/ {I_PSUBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF9\110", IF_WILLAMETTE|IF_SSE2}, + /*1368*/ {I_PSUBD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1369*/ {I_PSUBD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFA\110", IF_WILLAMETTE|IF_SSE2}, + /*1370*/ {I_PSUBQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2}, + /*1371*/ {I_PSUBQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1372*/ {I_PSUBQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2}, + /*1373*/ {I_PSUBQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1374*/ {I_PSUBSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1375*/ {I_PSUBSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE8\110", IF_WILLAMETTE|IF_SSE2}, + /*1376*/ {I_PSUBSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1377*/ {I_PSUBSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE9\110", IF_WILLAMETTE|IF_SSE2}, + /*1378*/ {I_PSUBUSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1379*/ {I_PSUBUSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD8\110", IF_WILLAMETTE|IF_SSE2}, + /*1380*/ {I_PSUBUSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1381*/ {I_PSUBUSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD9\110", IF_WILLAMETTE|IF_SSE2}, + /*1382*/ {I_PUNPCKHBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x68\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1383*/ {I_PUNPCKHBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x68\110", IF_WILLAMETTE|IF_SSE2}, + /*1384*/ {I_PUNPCKHWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x69\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1385*/ {I_PUNPCKHWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x69\110", IF_WILLAMETTE|IF_SSE2}, + /*1386*/ {I_PUNPCKHDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6A\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1387*/ {I_PUNPCKHDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6A\110", IF_WILLAMETTE|IF_SSE2}, + /*1388*/ {I_PUNPCKHQDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6D\110", IF_WILLAMETTE|IF_SSE2}, + /*1389*/ {I_PUNPCKHQDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6D\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1390*/ {I_PUNPCKLBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x60\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1391*/ {I_PUNPCKLBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x60\110", IF_WILLAMETTE|IF_SSE2}, + /*1392*/ {I_PUNPCKLWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x61\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1393*/ {I_PUNPCKLWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x61\110", IF_WILLAMETTE|IF_SSE2}, + /*1394*/ {I_PUNPCKLDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x62\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1395*/ {I_PUNPCKLDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x62\110", IF_WILLAMETTE|IF_SSE2}, + /*1396*/ {I_PUNPCKLQDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6C\110", IF_WILLAMETTE|IF_SSE2}, + /*1397*/ {I_PUNPCKLQDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6C\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1398*/ {I_PXOR, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEF\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1399*/ {I_PXOR, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEF\110", IF_WILLAMETTE|IF_SSE2}, + /*1400*/ {I_ADDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, + /*1401*/ {I_ADDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x58\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1402*/ {I_ADDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, + /*1403*/ {I_ADDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, + /*1404*/ {I_ANDNPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x55\110", IF_WILLAMETTE|IF_SSE2}, + /*1405*/ {I_ANDNPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x55\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1406*/ {I_ANDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x54\110", IF_WILLAMETTE|IF_SSE2}, + /*1407*/ {I_ANDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x54\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1408*/ {I_CMPEQPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1409*/ {I_CMPEQPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, + /*1410*/ {I_CMPEQSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, + /*1411*/ {I_CMPEQSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, + /*1412*/ {I_CMPLEPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1413*/ {I_CMPLEPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, + /*1414*/ {I_CMPLESD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, + /*1415*/ {I_CMPLESD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, + /*1416*/ {I_CMPLTPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1417*/ {I_CMPLTPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, + /*1418*/ {I_CMPLTSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, + /*1419*/ {I_CMPLTSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, + /*1420*/ {I_CMPNEQPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1421*/ {I_CMPNEQPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, + /*1422*/ {I_CMPNEQSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, + /*1423*/ {I_CMPNEQSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, + /*1424*/ {I_CMPNLEPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1425*/ {I_CMPNLEPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, + /*1426*/ {I_CMPNLESD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, + /*1427*/ {I_CMPNLESD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, + /*1428*/ {I_CMPNLTPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1429*/ {I_CMPNLTPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, + /*1430*/ {I_CMPNLTSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, + /*1431*/ {I_CMPNLTSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, + /*1432*/ {I_CMPORDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1433*/ {I_CMPORDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, + /*1434*/ {I_CMPORDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, + /*1435*/ {I_CMPORDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, + /*1436*/ {I_CMPUNORDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1437*/ {I_CMPUNORDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, + /*1438*/ {I_CMPUNORDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, + /*1439*/ {I_CMPUNORDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, + /*1440*/ {I_CMPPD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\3\x66\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1441*/ {I_CMPPD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\3\x66\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, + /*1442*/ {I_CMPSD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\3\xF2\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1443*/ {I_CMPSD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\3\xF2\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1444*/ {I_COMISD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x2F\110", IF_WILLAMETTE|IF_SSE2}, + /*1445*/ {I_COMISD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x2F\110", IF_WILLAMETTE|IF_SSE2}, + /*1446*/ {I_CVTDQ2PD, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, + /*1447*/ {I_CVTDQ2PD, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, + /*1448*/ {I_CVTDQ2PS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, + /*1449*/ {I_CVTDQ2PS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1450*/ {I_CVTPD2DQ, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, + /*1451*/ {I_CVTPD2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1452*/ {I_CVTPD2PI, 2, {MMXREG,XMMREG,0}, "\3\x66\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, + /*1453*/ {I_CVTPD2PI, 2, {MMXREG,MEMORY,0}, "\301\3\x66\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, + /*1454*/ {I_CVTPD2PS, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1455*/ {I_CVTPD2PS, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1456*/ {I_CVTPI2PD, 2, {XMMREG,MMXREG,0}, "\3\x66\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, + /*1457*/ {I_CVTPI2PD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, + /*1458*/ {I_CVTPS2DQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, + /*1459*/ {I_CVTPS2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1460*/ {I_CVTPS2PD, 2, {XMMREG,XMMREG,0}, "\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1461*/ {I_CVTPS2PD, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1462*/ {I_CVTSD2SI, 2, {REG32,XMMREG,0}, "\3\xF2\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, + /*1463*/ {I_CVTSD2SI, 2, {REG32,MEMORY,0}, "\301\3\xF2\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, + /*1464*/ {I_CVTSD2SS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1465*/ {I_CVTSD2SS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1466*/ {I_CVTSI2SD, 2, {XMMREG,REG32,0}, "\3\xF2\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, + /*1467*/ {I_CVTSI2SD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, + /*1468*/ {I_CVTSS2SD, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1469*/ {I_CVTSS2SD, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, + /*1470*/ {I_CVTTPD2PI, 2, {MMXREG,XMMREG,0}, "\3\x66\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, + /*1471*/ {I_CVTTPD2PI, 2, {MMXREG,MEMORY,0}, "\301\3\x66\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, + /*1472*/ {I_CVTTPD2DQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, + /*1473*/ {I_CVTTPD2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1474*/ {I_CVTTPS2DQ, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, + /*1475*/ {I_CVTTPS2DQ, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1476*/ {I_CVTTSD2SI, 2, {REG32,XMMREG,0}, "\3\xF2\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, + /*1477*/ {I_CVTTSD2SI, 2, {REG32,MEMORY,0}, "\301\3\xF2\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, + /*1478*/ {I_DIVPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, + /*1479*/ {I_DIVPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1480*/ {I_DIVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, + /*1481*/ {I_DIVSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, + /*1482*/ {I_MAXPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, + /*1483*/ {I_MAXPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1484*/ {I_MAXSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, + /*1485*/ {I_MAXSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, + /*1486*/ {I_MINPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, + /*1487*/ {I_MINPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1488*/ {I_MINSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, + /*1489*/ {I_MINSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, + /*1490*/ {I_MOVAPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x28\110", IF_WILLAMETTE|IF_SSE2}, + /*1491*/ {I_MOVAPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x29\110", IF_WILLAMETTE|IF_SSE2}, + /*1492*/ {I_MOVAPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x29\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1493*/ {I_MOVAPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x28\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1494*/ {I_MOVHPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x17\101", IF_WILLAMETTE|IF_SSE2}, + /*1495*/ {I_MOVHPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x16\110", IF_WILLAMETTE|IF_SSE2}, + /*1496*/ {I_MOVLPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x13\101", IF_WILLAMETTE|IF_SSE2}, + /*1497*/ {I_MOVLPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x12\110", IF_WILLAMETTE|IF_SSE2}, + /*1498*/ {I_MOVMSKPD, 2, {REG32,XMMREG,0}, "\3\x66\x0F\x50\110", IF_WILLAMETTE|IF_SSE2}, + /*1499*/ {I_MOVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, + /*1500*/ {I_MOVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x11\110", IF_WILLAMETTE|IF_SSE2}, + /*1501*/ {I_MOVSD, 2, {MEMORY,XMMREG,0}, "\300\3\xF2\x0F\x11\101", IF_WILLAMETTE|IF_SSE2}, + /*1502*/ {I_MOVSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, + /*1503*/ {I_MOVUPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, + /*1504*/ {I_MOVUPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x11\110", IF_WILLAMETTE|IF_SSE2}, + /*1505*/ {I_MOVUPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x11\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1506*/ {I_MOVUPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x10\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1507*/ {I_MULPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, + /*1508*/ {I_MULPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x59\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1509*/ {I_MULSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, + /*1510*/ {I_MULSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, + /*1511*/ {I_ORPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x56\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1512*/ {I_ORPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x56\110", IF_WILLAMETTE|IF_SSE2}, + /*1513*/ {I_SHUFPD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\x66\x0F\xC6\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, + /*1514*/ {I_SHUFPD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\xC6\110\26", IF_WILLAMETTE|IF_SSE2|IF_SM|IF_SB|IF_AR2}, + /*1515*/ {I_SQRTPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, + /*1516*/ {I_SQRTPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x51\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1517*/ {I_SQRTSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, + /*1518*/ {I_SQRTSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, + /*1519*/ {I_SUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, + /*1520*/ {I_SUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1521*/ {I_SUBSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, + /*1522*/ {I_SUBSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, + /*1523*/ {I_UCOMISD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x2E\110", IF_WILLAMETTE|IF_SSE2}, + /*1524*/ {I_UCOMISD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x2E\110", IF_WILLAMETTE|IF_SSE2}, + /*1525*/ {I_UNPCKHPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x15\110", IF_WILLAMETTE|IF_SSE2}, + /*1526*/ {I_UNPCKHPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x15\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1527*/ {I_UNPCKLPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x14\110", IF_WILLAMETTE|IF_SSE2}, + /*1528*/ {I_UNPCKLPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x14\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1529*/ {I_XORPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x57\110", IF_WILLAMETTE|IF_SSE2}, + /*1530*/ {I_XORPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x57\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, + /*1531*/ {I_ADDSUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD0\110", IF_PRESCOTT|IF_SSE3|IF_SM}, + /*1532*/ {I_ADDSUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD0\110", IF_PRESCOTT|IF_SSE3}, + /*1533*/ {I_ADDSUBPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\xD0\110", IF_PRESCOTT|IF_SSE3|IF_SM}, + /*1534*/ {I_ADDSUBPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\xD0\110", IF_PRESCOTT|IF_SSE3}, + /*1535*/ {I_HADDPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x7C\110", IF_PRESCOTT|IF_SSE3|IF_SM}, + /*1536*/ {I_HADDPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7C\110", IF_PRESCOTT|IF_SSE3}, + /*1537*/ {I_HADDPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x7C\110", IF_PRESCOTT|IF_SSE3|IF_SM}, + /*1538*/ {I_HADDPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x7C\110", IF_PRESCOTT|IF_SSE3}, + /*1539*/ {I_HSUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x7D\110", IF_PRESCOTT|IF_SSE3|IF_SM}, + /*1540*/ {I_HSUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7D\110", IF_PRESCOTT|IF_SSE3}, + /*1541*/ {I_HSUBPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x7D\110", IF_PRESCOTT|IF_SSE3|IF_SM}, + /*1542*/ {I_HSUBPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x7D\110", IF_PRESCOTT|IF_SSE3}, + /*1543*/ {I_LDDQU, 2, {XMMREG,MEMORY,0}, "\3\xF2\x0F\xF0\110", IF_PRESCOTT|IF_SSE3}, + /*1544*/ {I_MOVDDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, + /*1545*/ {I_MOVDDUP, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, + /*1546*/ {I_MOVSHDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF3\x0F\x16\110", IF_PRESCOTT|IF_SSE3}, + /*1547*/ {I_MOVSHDUP, 2, {XMMREG,XMMREG,0}, "\3\xF3\x0F\x16\110", IF_PRESCOTT|IF_SSE3}, + /*1548*/ {I_MOVSLDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF3\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, + /*1549*/ {I_MOVSLDUP, 2, {XMMREG,XMMREG,0}, "\3\xF3\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, + + /*1550 23*/ {I_ADC, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\202\21", IF_8086|IF_SM}, + /*1551 26*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\202\21", IF_8086|IF_SM}, + /*1552 46*/ {I_ADD, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\200\21", IF_8086|IF_SM}, + /*1553 49*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\200\21", IF_8086|IF_SM}, + /*1554 69*/ {I_AND, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\204\21", IF_8086|IF_SM}, + /*1555 72*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\204\21", IF_8086|IF_SM}, + /*1556 158*/ {I_CMP, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\207\21", IF_8086|IF_SM}, + /*1557 161*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\207\21", IF_8086|IF_SM}, + /*1558 595*/ {I_OR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\201\21", IF_8086|IF_SM}, + /*1559 598*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\201\21", IF_8086|IF_SM}, + /*1560 872*/ {I_SBB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\203\21", IF_8086|IF_SM}, + /*1561 875*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\203\21", IF_8086|IF_SM}, + /*1562 954*/ {I_SUB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\205\21", IF_8086|IF_SM}, + /*1563 957*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\205\21", IF_8086|IF_SM}, + /*1564 1052*/ {I_XOR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\206\21", IF_8086|IF_SM}, + /*1565 1055*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\206\21", IF_8086|IF_SM}, + + /*1566*/ ITEMPLATE_END }; static struct itemplate *itable_00[] = { @@ -3145,6 +3163,22 @@ static struct itemplate *itable_81[] = { }; static struct itemplate *itable_82[] = { + instrux + 1550, + instrux + 1551, + instrux + 1552, + instrux + 1553, + instrux + 1554, + instrux + 1555, + instrux + 1556, + instrux + 1557, + instrux + 1558, + instrux + 1559, + instrux + 1560, + instrux + 1561, + instrux + 1562, + instrux + 1563, + instrux + 1564, + instrux + 1565, NULL }; diff --git a/AltairZ80/mfdc.c b/AltairZ80/mfdc.c index 6d2379fc..503230e9 100644 --- a/AltairZ80/mfdc.c +++ b/AltairZ80/mfdc.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: mfdc.c 1773 2008-01-11 05:46:19Z hharte $ * + * $Id: mfdc.c 1995 2008-07-15 03:59:13Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -58,12 +58,14 @@ #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define ORDERS_MSG 0x02 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define ORDERS_MSG (1 << 7) extern uint32 PCX; extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); @@ -140,8 +142,6 @@ static uint8 MFDC_Write(const uint32 Addr, uint8 cData); static int32 mdskdev(const int32 Addr, const int32 rw, const int32 data); -static int32 trace_level = 0; - static UNIT mfdc_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MFDC_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MFDC_CAPACITY) }, @@ -150,7 +150,6 @@ static UNIT mfdc_unit[] = { }; static REG mfdc_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, { NULL } }; @@ -165,13 +164,29 @@ static MTAB mfdc_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if(mfdc_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB mfdc_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "ORDERS", ORDERS_MSG }, + { NULL, 0 } +}; + DEVICE mfdc_dev = { "MDSK", mfdc_unit, mfdc_reg, mfdc_mod, MFDC_MAX_DRIVES, 10, 31, 1, MFDC_MAX_DRIVES, MFDC_MAX_DRIVES, NULL, NULL, &mfdc_reset, NULL, &mfdc_attach, &mfdc_detach, - &mfdc_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &mfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + mfdc_dt, NULL, "Micropolis FD Control MDSK" }; /* Micropolis FD Control Boot ROM @@ -293,13 +308,16 @@ t_stat mfdc_detach(UNIT *uptr) } } - if (i >= MFDC_MAX_DRIVES) return SCPE_ARG; + if (i >= MFDC_MAX_DRIVES) + return SCPE_ARG; DBG_PRINT(("Detach MFDC%d\n", i)); - diskClose(mfdc_info->drive[i].imd); + r = diskClose(&mfdc_info->drive[i].imd); + if (r != SCPE_OK) + return r; r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) + if (r != SCPE_OK) return r; return SCPE_OK; @@ -462,7 +480,7 @@ static uint8 MFDC_Read(const uint32 Addr) if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { - fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); #ifdef USE_VGI fread(sdata.raw, MFDC_SECTOR_LEN, 1, (pDrive->uptr)->fileref); #else @@ -583,7 +601,7 @@ static uint8 MFDC_Write(const uint32 Addr, uint8 cData) if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { - fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); #ifdef USE_VGI fwrite(sdata.raw, MFDC_SECTOR_LEN, 1, (pDrive->uptr)->fileref); #else @@ -632,7 +650,7 @@ static void MFDC_Command(uint8 cData) TRACE_PRINT(CMD_MSG, ("MFDC: " ADDRESS_FORMAT " No Op." NLP, PCX)); break; case MFDC_CMD_SELECT: - mfdc_info->sel_drive = cModifier & 3; + mfdc_info->sel_drive = cModifier & 0x03; mfdc_info->head = (cModifier & 0x10) >> 4; mfdc_info->selected = TRUE; diff --git a/AltairZ80/n8vem.c b/AltairZ80/n8vem.c index f9cdf077..7f34c383 100644 --- a/AltairZ80/n8vem.c +++ b/AltairZ80/n8vem.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: n8vem.c 1902 2008-05-11 02:40:41Z hharte $ * + * $Id: n8vem.c 1995 2008-07-15 03:59:13Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -54,18 +54,17 @@ #define DBG_PRINT(args) #endif -#define PIO_MSG 0x01 -#define UART_MSG 0x02 -#define RTC_MSG 0x04 -#define MPCL_MSG 0x08 -#define ROM_MSG 0x10 -#define TRACE_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define PIO_MSG (1 << 1) +#define UART_MSG (1 << 2) +#define RTC_MSG (1 << 3) +#define MPCL_MSG (1 << 4) +#define ROM_MSG (1 << 5) +#define VERBOSE_MSG (1 << 7) #define N8VEM_MAX_DRIVES 2 -#define UNIT_V_N8VEM_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_N8VEM_VERBOSE (1 << UNIT_V_N8VEM_VERBOSE) - typedef struct { PNP_INFO pnp; /* Plug and Play */ uint8 *ram; @@ -101,7 +100,6 @@ static uint8 N8VEM_Write(const uint32 Addr, uint8 cData); static int32 n8vemdev(const int32 port, const int32 io, const int32 data); static int32 n8vem_mem(const int32 port, const int32 io, const int32 data); -static int32 trace_level = 0x00; /* Disable all tracing by default */ static int32 save_rom = 0x00; /* When set to 1, saves ROM back to file on disk at detach time */ static int32 save_ram = 0x00; /* When set to 1, saves RAM back to file on disk at detach time */ static int32 n8vem_pio1a = 0x00; /* 8255 PIO1A IN Port */ @@ -123,7 +121,6 @@ static UNIT n8vem_unit[] = { }; static REG n8vem_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, { HRDATA (SAVEROM, save_rom, 1), }, { HRDATA (SAVERAM, save_ram, 1), }, { HRDATA (PIO1A, n8vem_pio1a, 8), }, @@ -136,20 +133,31 @@ static REG n8vem_reg[] = { static MTAB n8vem_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - /* quiet, no warning messages */ - { UNIT_N8VEM_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_N8VEM_VERBOSE, UNIT_N8VEM_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if(n8vem_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB n8vem_dt[] = { + { "ERROR", ERROR_MSG }, + { "PIO", PIO_MSG }, + { "UART", UART_MSG }, + { "RTC", RTC_MSG }, + { "ROM", ROM_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { NULL, 0 } +}; + DEVICE n8vem_dev = { "N8VEM", n8vem_unit, n8vem_reg, n8vem_mod, N8VEM_MAX_DRIVES, 10, 31, 1, N8VEM_MAX_DRIVES, N8VEM_MAX_DRIVES, NULL, NULL, &n8vem_reset, &n8vem_boot, &n8vem_attach, &n8vem_detach, - &n8vem_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &n8vem_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + n8vem_dt, NULL, "Single-Board Computer N8VEM" }; /* Reset routine */ @@ -157,7 +165,7 @@ static t_stat n8vem_reset(DEVICE *dptr) { PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - TRACE_PRINT(TRACE_MSG, ("N8VEM: Reset." NLP)); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reset." NLP)); if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &n8vemdev, TRUE); @@ -188,7 +196,7 @@ static t_stat n8vem_reset(DEVICE *dptr) static t_stat n8vem_boot(int32 unitno, DEVICE *dptr) { - TRACE_PRINT(TRACE_MSG, ("N8VEM: Boot." NLP)); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Boot." NLP)); /* Clear the RAM and ROM mapping registers */ n8vem_info->mpcl_ram = 0; @@ -218,7 +226,7 @@ static t_stat n8vem_attach(UNIT *uptr, char *cptr) /* Determine length of this disk */ uptr->capac = sim_fsize(uptr->fileref); - TRACE_PRINT(TRACE_MSG, ("N8VEM: Attach %s." NLP, i == 0 ? "ROM" : "RAM")); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Attach %s." NLP, i == 0 ? "ROM" : "RAM")); if(i == 0) { /* Attaching ROM */ n8vem_info->rom_attached = TRUE; @@ -228,9 +236,10 @@ static t_stat n8vem_attach(UNIT *uptr, char *cptr) if(uptr->capac > 0) { /* Only read in enough of the file to fill the ROM. */ - if(uptr->capac > N8VEM_ROM_SIZE) uptr->capac = N8VEM_ROM_SIZE; + if (uptr->capac > N8VEM_ROM_SIZE) + uptr->capac = N8VEM_ROM_SIZE; - printf("Reading %d bytes into ROM.\n", uptr->capac); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reading %d bytes into ROM.\n", uptr->capac)); fread((void *)(n8vem_info->rom), uptr->capac, 1, uptr->fileref); } } else { /* attaching RAM */ @@ -239,9 +248,10 @@ static t_stat n8vem_attach(UNIT *uptr, char *cptr) if(uptr->capac > 0) { /* Only read in enough of the file to fill the RAM. */ - if(uptr->capac > N8VEM_RAM_SIZE) uptr->capac = N8VEM_RAM_SIZE; + if(uptr->capac > N8VEM_RAM_SIZE) + uptr->capac = N8VEM_RAM_SIZE; - printf("Reading %d bytes into RAM.\n", uptr->capac); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reading %d bytes into RAM.\n", uptr->capac)); fread((void *)(n8vem_info->ram), uptr->capac, 1, uptr->fileref); } } @@ -260,21 +270,21 @@ static t_stat n8vem_detach(UNIT *uptr) return (SCPE_IERR); } - TRACE_PRINT(TRACE_MSG, ("N8VEM: Detach %s." NLP, i == 0 ? "ROM" : "RAM")); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Detach %s." NLP, i == 0 ? "ROM" : "RAM")); /* rewind to the beginning of the file. */ - fseek(uptr->fileref, 0, SEEK_SET); + sim_fseek(uptr->fileref, 0, SEEK_SET); if(i == 0) { /* ROM */ /* Save the ROM back to disk if SAVEROM is set. */ if(save_rom == 1) { - printf("Writing %d bytes into ROM image.\n", N8VEM_ROM_SIZE); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Writing %d bytes into ROM image.\n", N8VEM_ROM_SIZE)); fwrite((void *)(n8vem_info->rom), N8VEM_ROM_SIZE, 1, uptr->fileref); } } else { /* RAM */ /* Save the RAM back to disk if SAVERAM is set. */ if(save_ram == 1) { - printf("Writing %d bytes into RAM image.\n", N8VEM_RAM_SIZE); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Writing %d bytes into RAM image.\n", N8VEM_RAM_SIZE)); fwrite((void *)(n8vem_info->ram), N8VEM_RAM_SIZE, 1, uptr->fileref); } } @@ -419,7 +429,7 @@ static uint8 N8VEM_Read(const uint32 Addr) TRACE_PRINT(MPCL_MSG, ("N8VEM: " ADDRESS_FORMAT " RD: MPCL_ROM not Implemented." NLP, PCX)); break; default: - TRACE_PRINT(TRACE_MSG, ("N8VEM: " ADDRESS_FORMAT " RD[%02x]: not Implemented." NLP, PCX, Addr)); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: " ADDRESS_FORMAT " RD[%02x]: not Implemented." NLP, PCX, Addr)); break; } @@ -477,7 +487,7 @@ static uint8 N8VEM_Write(const uint32 Addr, uint8 cData) n8vem_info->mpcl_rom = cData; break; default: - TRACE_PRINT(TRACE_MSG, ("N8VEM: " ADDRESS_FORMAT " WR[0x%02x]=0x%02x: not Implemented." NLP, PCX, Addr, cData)); + TRACE_PRINT(VERBOSE_MSG, ("N8VEM: " ADDRESS_FORMAT " WR[0x%02x]=0x%02x: not Implemented." NLP, PCX, Addr, cData)); break; } diff --git a/AltairZ80/nasm.h b/AltairZ80/nasm.h index 87c2b387..2745189b 100644 --- a/AltairZ80/nasm.h +++ b/AltairZ80/nasm.h @@ -12,13 +12,6 @@ #define NASM_NASM_H #include -#define NASM_VERSION_H -#define NASM_MAJOR_VER 0 -#define NASM_MINOR_VER 98 -#define NASM_SUBMINOR_VER 38 -#define NASM_PATCHLEVEL_VER 0 -#define NASM_VERSION_ID 0x00622600 -#define NASM_VER "0.98.38" #ifndef NULL #define NULL 0 @@ -31,23 +24,6 @@ #define TRUE 1 #endif -#define NO_SEG -1L /* null segment value */ -#define SEG_ABS 0x40000000L /* mask for far-absolute segments */ - -#ifndef FILENAME_MAX -#define FILENAME_MAX 256 -#endif - -#ifndef PREFIX_MAX -#define PREFIX_MAX 10 -#endif - -#ifndef POSTFIX_MAX -#define POSTFIX_MAX 10 -#endif - -#define IDLEN_MAX 4096 - /* * Name pollution problems: on Digital UNIX pulls in some * strange hardware header file which sees fit to define R_SP. We @@ -57,233 +33,6 @@ #undef R_SP #endif -/* - * We must declare the existence of this structure type up here, - * since we have to reference it before we define it... - */ -struct ofmt; - -/* - * ------------------------- - * Error reporting functions - * ------------------------- - */ - -/* - * An error reporting function should look like this. - */ -typedef void (*efunc) (int severity, const char *fmt, ...); - -/* - * These are the error severity codes which get passed as the first - * argument to an efunc. - */ - -#define ERR_DEBUG 0x00000008 /* put out debugging message */ -#define ERR_WARNING 0x00000000 /* warn only: no further action */ -#define ERR_NONFATAL 0x00000001 /* terminate assembly after phase */ -#define ERR_FATAL 0x00000002 /* instantly fatal: exit with error */ -#define ERR_PANIC 0x00000003 /* internal error: panic instantly - * and dump core for reference */ -#define ERR_MASK 0x0000000F /* mask off the above codes */ -#define ERR_NOFILE 0x00000010 /* don't give source file name/line */ -#define ERR_USAGE 0x00000020 /* print a usage message */ -#define ERR_PASS1 0x00000040 /* only print this error on pass one */ - -/* - * These codes define specific types of suppressible warning. - */ - -#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */ -#define ERR_WARN_SHR 8 /* how far to shift right */ - -#define ERR_WARN_MNP 0x00000100 /* macro-num-parameters warning */ -#define ERR_WARN_MSR 0x00000200 /* macro self-reference */ -#define ERR_WARN_OL 0x00000300 /* orphan label (no colon, and - * alone on line) */ -#define ERR_WARN_NOV 0x00000400 /* numeric overflow */ -#define ERR_WARN_GNUELF 0x00000500 /* using GNU ELF extensions */ -#define ERR_WARN_MAX 5 /* the highest numbered one */ - -/* - * ----------------------- - * Other function typedefs - * ----------------------- - */ - -/* - * A label-lookup function should look like this. - */ -typedef int (*lfunc) (char *label, long *segment, long *offset); - -/* - * And a label-definition function like this. The boolean parameter - * `is_norm' states whether the label is a `normal' label (which - * should affect the local-label system), or something odder like - * an EQU or a segment-base symbol, which shouldn't. - */ -typedef void (*ldfunc) (char *label, long segment, long offset, char *special, - int is_norm, int isextrn, struct ofmt *ofmt, - efunc error); - -/* - * List-file generators should look like this: - */ -typedef struct { - /* - * Called to initialise the listing file generator. Before this - * is called, the other routines will silently do nothing when - * called. The `char *' parameter is the file name to write the - * listing to. - */ - void (*init) (char *, efunc); - - /* - * Called to clear stuff up and close the listing file. - */ - void (*cleanup) (void); - - /* - * Called to output binary data. Parameters are: the offset; - * the data; the data type. Data types are similar to the - * output-format interface, only OUT_ADDRESS will _always_ be - * displayed as if it's relocatable, so ensure that any non- - * relocatable address has been converted to OUT_RAWDATA by - * then. Note that OUT_RAWDATA+0 is a valid data type, and is a - * dummy call used to give the listing generator an offset to - * work with when doing things like uplevel(LIST_TIMES) or - * uplevel(LIST_INCBIN). - */ - void (*output) (long, const void *, unsigned long); - - /* - * Called to send a text line to the listing generator. The - * `int' parameter is LIST_READ or LIST_MACRO depending on - * whether the line came directly from an input file or is the - * result of a multi-line macro expansion. - */ - void (*line) (int, char *); - - /* - * Called to change one of the various levelled mechanisms in - * the listing generator. LIST_INCLUDE and LIST_MACRO can be - * used to increase the nesting level of include files and - * macro expansions; LIST_TIMES and LIST_INCBIN switch on the - * two binary-output-suppression mechanisms for large-scale - * pseudo-instructions. - * - * LIST_MACRO_NOLIST is synonymous with LIST_MACRO except that - * it indicates the beginning of the expansion of a `nolist' - * macro, so anything under that level won't be expanded unless - * it includes another file. - */ - void (*uplevel) (int); - - /* - * Reverse the effects of uplevel. - */ - void (*downlevel) (int); -} ListGen; - -/* - * The expression evaluator must be passed a scanner function; a - * standard scanner is provided as part of nasmlib.c. The - * preprocessor will use a different one. Scanners, and the - * token-value structures they return, look like this. - * - * The return value from the scanner is always a copy of the - * `t_type' field in the structure. - */ -struct tokenval { - int t_type; - long t_integer, t_inttwo; - char *t_charptr; -}; -typedef int (*scanner) (void *private_data, struct tokenval *tv); - -/* - * Token types returned by the scanner, in addition to ordinary - * ASCII character values, and zero for end-of-string. - */ -enum { /* token types, other than chars */ - TOKEN_INVALID = -1, /* a placeholder value */ - TOKEN_EOS = 0, /* end of string */ - TOKEN_EQ = '=', TOKEN_GT = '>', TOKEN_LT = '<', /* aliases */ - TOKEN_ID = 256, TOKEN_NUM, TOKEN_REG, TOKEN_INSN, /* major token types */ - TOKEN_ERRNUM, /* numeric constant with error in */ - TOKEN_HERE, TOKEN_BASE, /* $ and $$ */ - TOKEN_SPECIAL, /* BYTE, WORD, DWORD, FAR, NEAR, etc */ - TOKEN_PREFIX, /* A32, O16, LOCK, REPNZ, TIMES, etc */ - TOKEN_SHL, TOKEN_SHR, /* << and >> */ - TOKEN_SDIV, TOKEN_SMOD, /* // and %% */ - TOKEN_GE, TOKEN_LE, TOKEN_NE, /* >=, <= and <> (!= is same as <>) */ - TOKEN_DBL_AND, TOKEN_DBL_OR, TOKEN_DBL_XOR, /* &&, || and ^^ */ - TOKEN_SEG, TOKEN_WRT, /* SEG and WRT */ - TOKEN_FLOAT /* floating-point constant */ -}; - -typedef struct { - long segment; - long offset; - int known; -} loc_t; - -/* - * Expression-evaluator datatype. Expressions, within the - * evaluator, are stored as an array of these beasts, terminated by - * a record with type==0. Mostly, it's a vector type: each type - * denotes some kind of a component, and the value denotes the - * multiple of that component present in the expression. The - * exception is the WRT type, whose `value' field denotes the - * segment to which the expression is relative. These segments will - * be segment-base types, i.e. either odd segment values or SEG_ABS - * types. So it is still valid to assume that anything with a - * `value' field of zero is insignificant. - */ -typedef struct { - long type; /* a register, or EXPR_xxx */ - long value; /* must be >= 32 bits */ -} expr; - -/* - * The evaluator can also return hints about which of two registers - * used in an expression should be the base register. See also the - * `operand' structure. - */ -struct eval_hints { - int base; - int type; -}; - -/* - * The actual expression evaluator function looks like this. When - * called, it expects the first token of its expression to already - * be in `*tv'; if it is not, set tv->t_type to TOKEN_INVALID and - * it will start by calling the scanner. - * - * If a forward reference happens during evaluation, the evaluator - * must set `*fwref' to TRUE if `fwref' is non-NULL. - * - * `critical' is non-zero if the expression may not contain forward - * references. The evaluator will report its own error if this - * occurs; if `critical' is 1, the error will be "symbol not - * defined before use", whereas if `critical' is 2, the error will - * be "symbol undefined". - * - * If `critical' has bit 8 set (in addition to its main value: 0x101 - * and 0x102 correspond to 1 and 2) then an extended expression - * syntax is recognised, in which relational operators such as =, < - * and >= are accepted, as well as low-precedence logical operators - * &&, ^^ and ||. - * - * If `hints' is non-NULL, it gets filled in with some hints as to - * the base register in complex effective addresses. - */ -#define CRITICAL 0x100 -typedef expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv, - int *fwref, int critical, efunc error, - struct eval_hints *hints); - /* * Special values for expr->type. ASSUMPTION MADE HERE: the number * of distinct register names (i.e. possible "type" fields for an @@ -291,79 +40,6 @@ typedef expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv, * EXPR_REG_END). */ #define EXPR_REG_START 1 -#define EXPR_REG_END 124 -#define EXPR_UNKNOWN 125L /* for forward references */ -#define EXPR_SIMPLE 126L -#define EXPR_WRT 127L -#define EXPR_SEGBASE 128L - -/* - * Preprocessors ought to look like this: - */ -typedef struct { - /* - * Called at the start of a pass; given a file name, the number - * of the pass, an error reporting function, an evaluator - * function, and a listing generator to talk to. - */ - void (*reset) (char *, int, efunc, evalfunc, ListGen *); - - /* - * Called to fetch a line of preprocessed source. The line - * returned has been malloc'ed, and so should be freed after - * use. - */ - char *(*getline) (void); - - /* - * Called at the end of a pass. - */ - void (*cleanup) (int); -} Preproc; - -/* - * ---------------------------------------------------------------- - * Some lexical properties of the NASM source language, included - * here because they are shared between the parser and preprocessor - * ---------------------------------------------------------------- - */ - -/* - * isidstart matches any character that may start an identifier, and isidchar - * matches any character that may appear at places other than the start of an - * identifier. E.g. a period may only appear at the start of an identifier - * (for local labels), whereas a number may appear anywhere *but* at the - * start. - */ - -#define isidstart(c) ( isalpha(c) || (c)=='_' || (c)=='.' || (c)=='?' \ - || (c)=='@' ) -#define isidchar(c) ( isidstart(c) || isdigit(c) || (c)=='$' || (c)=='#' \ - || (c)=='~' ) - -/* Ditto for numeric constants. */ - -#define isnumstart(c) ( isdigit(c) || (c)=='$' ) -#define isnumchar(c) ( isalnum(c) ) - -/* This returns the numeric value of a given 'digit'. */ - -#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0') - -/* - * Data-type flags that get passed to listing-file routines. - */ -enum { - LIST_READ, LIST_MACRO, LIST_MACRO_NOLIST, LIST_INCLUDE, - LIST_INCBIN, LIST_TIMES -}; - -/* - * ----------------------------------------------------------- - * Format of the `insn' structure returned from `parser.c' and - * passed into `assemble.c' - * ----------------------------------------------------------- - */ /* * Here we define the operand types. These are implemented as bit @@ -389,7 +65,6 @@ enum { #define TO 0x00000100L /* reverse effect in FADD, FSUB &c */ #define COLON 0x00000200L /* operand is followed by a colon */ -#define STRICT 0x00000400L /* do not optimize this operand */ /* type of operand: memory reference, register, etc. */ #define MEMORY 0x00204000L @@ -545,249 +220,61 @@ enum { /* extended operand types */ EOT_NOTHING, EOT_DB_STRING, EOT_DB_NUMBER }; -enum { /* special EA flags */ - EAF_BYTEOFFS = 1, /* force offset part to byte size */ - EAF_WORDOFFS = 2, /* force offset part to [d]word size */ - EAF_TIMESTWO = 4 /* really do EAX*2 not EAX+EAX */ +enum { /* special EA flags */ + EAF_BYTEOFFS = 1, /* force offset part to byte size */ + EAF_WORDOFFS = 2, /* force offset part to [d]word size */ + EAF_TIMESTWO = 4 /* really do EAX*2 not EAX+EAX */ }; -enum { /* values for `hinttype' */ - EAH_NOHINT = 0, /* no hint at all - our discretion */ - EAH_MAKEBASE = 1, /* try to make given reg the base */ - EAH_NOTBASE = 2 /* try _not_ to make reg the base */ +enum { /* values for `hinttype' */ + EAH_NOHINT = 0, /* no hint at all - our discretion */ + EAH_MAKEBASE = 1, /* try to make given reg the base */ + EAH_NOTBASE = 2 /* try _not_ to make reg the base */ }; -typedef struct { /* operand to an instruction */ - long type; /* type of operand */ - int addr_size; /* 0 means default; 16; 32 */ - int basereg, indexreg, scale; /* registers and scale involved */ - int hintbase, hinttype; /* hint as to real base register */ - long segment; /* immediate segment, if needed */ - long offset; /* any immediate number */ - long wrt; /* segment base it's relative to */ - int eaflags; /* special EA flags */ - int opflags; /* see OPFLAG_* defines below */ +typedef struct { /* operand to an instruction */ + long type; /* type of operand */ + int addr_size; /* 0 means default; 16; 32 */ + int basereg, indexreg, scale; /* registers and scale involved */ + int hintbase, hinttype; /* hint as to real base register */ + long segment; /* immediate segment, if needed */ + long offset; /* any immediate number */ + long wrt; /* segment base it's relative to */ + int eaflags; /* special EA flags */ + int opflags; /* see OPFLAG_* defines below */ } operand; -#define OPFLAG_FORWARD 1 /* operand is a forward reference */ -#define OPFLAG_EXTERN 2 /* operand is an external reference */ +#define OPFLAG_FORWARD 1 /* operand is a forward reference */ +#define OPFLAG_EXTERN 2 /* operand is an external reference */ -typedef struct extop { /* extended operand */ - struct extop *next; /* linked list */ - long type; /* defined above */ - char *stringval; /* if it's a string, then here it is */ - int stringlen; /* ... and here's how long it is */ - long segment; /* if it's a number/address, then... */ - long offset; /* ... it's given here ... */ - long wrt; /* ... and here */ +typedef struct extop { /* extended operand */ + struct extop *next; /* linked list */ + long type; /* defined above */ + char *stringval; /* if it's a string, then here it is */ + int stringlen; /* ... and here's how long it is */ + long segment; /* if it's a number/address, then... */ + long offset; /* ... it's given here ... */ + long wrt; /* ... and here */ } extop; #define MAXPREFIX 4 -typedef struct { /* an instruction itself */ - char *label; /* the label defined, or NULL */ - int prefixes[MAXPREFIX]; /* instruction prefixes, if any */ - int nprefix; /* number of entries in above */ - int opcode; /* the opcode - not just the string */ - int condition; /* the condition code, if Jcc/SETcc */ - int operands; /* how many operands? 0-3 - * (more if db et al) */ - operand oprs[3]; /* the operands, defined as above */ - extop *eops; /* extended operands */ - int eops_float; /* true if DD and floating */ - long times; /* repeat count (TIMES prefix) */ - int forw_ref; /* is there a forward reference? */ +typedef struct { /* an instruction itself */ + char *label; /* the label defined, or NULL */ + int prefixes[MAXPREFIX]; /* instruction prefixes, if any */ + int nprefix; /* number of entries in above */ + int opcode; /* the opcode - not just the string */ + int condition; /* the condition code, if Jcc/SETcc */ + int operands; /* how many operands? 0-3 + * (more if db et al) */ + operand oprs[3]; /* the operands, defined as above */ + extop *eops; /* extended operands */ + int eops_float; /* true if DD and floating */ + long times; /* repeat count (TIMES prefix) */ + int forw_ref; /* is there a forward reference? */ } insn; enum geninfo { GI_SWITCH }; -/* - * ------------------------------------------------------------ - * The data structure defining an output format driver, and the - * interfaces to the functions therein. - * ------------------------------------------------------------ - */ - -struct ofmt { - /* - * This is a short (one-liner) description of the type of - * output generated by the driver. - */ - const char *fullname; - - /* - * This is a single keyword used to select the driver. - */ - const char *shortname; - - /* - * this is reserved for out module specific help. - * It is set to NULL in all the out modules but is not implemented - * in the main program - */ - const char *helpstring; - - /* - * this is a pointer to the first element of the debug information - */ - struct dfmt **debug_formats; - - /* - * and a pointer to the element that is being used - * note: this is set to the default at compile time and changed if the - * -F option is selected. If developing a set of new debug formats for - * an output format, be sure to set this to whatever default you want - * - */ - struct dfmt *current_dfmt; - - /* - * This, if non-NULL, is a NULL-terminated list of `char *'s - * pointing to extra standard macros supplied by the object - * format (e.g. a sensible initial default value of __SECT__, - * and user-level equivalents for any format-specific - * directives). - */ - const char **stdmac; - - /* - * This procedure is called at the start of an output session. - * It tells the output format what file it will be writing to, - * what routine to report errors through, and how to interface - * to the label manager and expression evaluator if necessary. - * It also gives it a chance to do other initialisation. - */ - void (*init) (FILE *fp, efunc error, ldfunc ldef, evalfunc eval); - - /* - * This procedure is called to pass generic information to the - * object file. The first parameter gives the information type - * (currently only command line switches) - * and the second parameter gives the value. This function returns - * 1 if recognized, 0 if unrecognized - */ - int (*setinfo)(enum geninfo type, char **string); - - /* - * This procedure is called by assemble() to write actual - * generated code or data to the object file. Typically it - * doesn't have to actually _write_ it, just store it for - * later. - * - * The `type' argument specifies the type of output data, and - * usually the size as well: its contents are described below. - */ - void (*output) (long segto, const void *data, unsigned long type, - long segment, long wrt); - - /* - * This procedure is called once for every symbol defined in - * the module being assembled. It gives the name and value of - * the symbol, in NASM's terms, and indicates whether it has - * been declared to be global. Note that the parameter "name", - * when passed, will point to a piece of static storage - * allocated inside the label manager - it's safe to keep using - * that pointer, because the label manager doesn't clean up - * until after the output driver has. - * - * Values of `is_global' are: 0 means the symbol is local; 1 - * means the symbol is global; 2 means the symbol is common (in - * which case `offset' holds the _size_ of the variable). - * Anything else is available for the output driver to use - * internally. - * - * This routine explicitly _is_ allowed to call the label - * manager to define further symbols, if it wants to, even - * though it's been called _from_ the label manager. That much - * re-entrancy is guaranteed in the label manager. However, the - * label manager will in turn call this routine, so it should - * be prepared to be re-entrant itself. - * - * The `special' parameter contains special information passed - * through from the command that defined the label: it may have - * been an EXTERN, a COMMON or a GLOBAL. The distinction should - * be obvious to the output format from the other parameters. - */ - void (*symdef) (char *name, long segment, long offset, int is_global, - char *special); - - /* - * This procedure is called when the source code requests a - * segment change. It should return the corresponding segment - * _number_ for the name, or NO_SEG if the name is not a valid - * segment name. - * - * It may also be called with NULL, in which case it is to - * return the _default_ section number for starting assembly in. - * - * It is allowed to modify the string it is given a pointer to. - * - * It is also allowed to specify a default instruction size for - * the segment, by setting `*bits' to 16 or 32. Or, if it - * doesn't wish to define a default, it can leave `bits' alone. - */ - long (*section) (char *name, int pass, int *bits); - - /* - * This procedure is called to modify the segment base values - * returned from the SEG operator. It is given a segment base - * value (i.e. a segment value with the low bit set), and is - * required to produce in return a segment value which may be - * different. It can map segment bases to absolute numbers by - * means of returning SEG_ABS types. - * - * It should return NO_SEG if the segment base cannot be - * determined; the evaluator (which calls this routine) is - * responsible for throwing an error condition if that occurs - * in pass two or in a critical expression. - */ - long (*segbase) (long segment); - - /* - * This procedure is called to allow the output driver to - * process its own specific directives. When called, it has the - * directive word in `directive' and the parameter string in - * `value'. It is called in both assembly passes, and `pass' - * will be either 1 or 2. - * - * This procedure should return zero if it does not _recognise_ - * the directive, so that the main program can report an error. - * If it recognises the directive but then has its own errors, - * it should report them itself and then return non-zero. It - * should also return non-zero if it correctly processes the - * directive. - */ - int (*directive) (char *directive, char *value, int pass); - - /* - * This procedure is called before anything else - even before - * the "init" routine - and is passed the name of the input - * file from which this output file is being generated. It - * should return its preferred name for the output file in - * `outname', if outname[0] is not '\0', and do nothing to - * `outname' otherwise. Since it is called before the driver is - * properly initialised, it has to be passed its error handler - * separately. - * - * This procedure may also take its own copy of the input file - * name for use in writing the output file: it is _guaranteed_ - * that it will be called before the "init" routine. - * - * The parameter `outname' points to an area of storage - * guaranteed to be at least FILENAME_MAX in size. - */ - void (*filename) (char *inname, char *outname, efunc error); - - /* - * This procedure is called after assembly finishes, to allow - * the output driver to clean itself up and free its memory. - * Typically, it will also be the point at which the object - * file actually gets _written_. - * - * One thing the cleanup routine should always do is to close - * the output file pointer. - */ - void (*cleanup) (int debuginfo); -}; /* * values for the `type' parameter to an output function. Each one @@ -815,77 +302,6 @@ struct ofmt { #define OUT_TYPMASK 0xF0000000UL #define OUT_SIZMASK 0x0FFFFFFFUL -/* - * ------------------------------------------------------------ - * The data structure defining a debug format driver, and the - * interfaces to the functions therein. - * ------------------------------------------------------------ - */ - -struct dfmt { - - /* - * This is a short (one-liner) description of the type of - * output generated by the driver. - */ - const char *fullname; - - /* - * This is a single keyword used to select the driver. - */ - const char *shortname; - - - /* - * init - called initially to set up local pointer to object format, - * void pointer to implementation defined data, file pointer (which - * probably won't be used, but who knows?), and error function. - */ - void (*init) (struct ofmt * of, void * id, FILE * fp, efunc error); - - /* - * linenum - called any time there is output with a change of - * line number or file. - */ - void (*linenum) (const char * filename, long linenumber, long segto); - - /* - * debug_deflabel - called whenever a label is defined. Parameters - * are the same as to 'symdef()' in the output format. This function - * would be called before the output format version. - */ - - void (*debug_deflabel) (char * name, long segment, long offset, - int is_global, char * special); - /* - * debug_directive - called whenever a DEBUG directive other than 'LINE' - * is encountered. 'directive' contains the first parameter to the - * DEBUG directive, and params contains the rest. For example, - * 'DEBUG VAR _somevar:int' would translate to a call to this - * function with 'directive' equal to "VAR" and 'params' equal to - * "_somevar:int". - */ - void (*debug_directive) (const char * directive, const char * params); - - /* - * typevalue - called whenever the assembler wishes to register a type - * for the last defined label. This routine MUST detect if a type was - * already registered and not re-register it. - */ - void (*debug_typevalue) (long type); - - /* - * debug_output - called whenever output is required - * 'type' is the type of info required, and this is format-specific - */ - void (*debug_output) (int type, void *param); - - /* - * cleanup - called after processing of file is complete - */ - void (*cleanup) (void); - -}; /* * The type definition macros * for debugging diff --git a/AltairZ80/s100_64fdc.c b/AltairZ80/s100_64fdc.c index c9d1104f..86b7d0e7 100644 --- a/AltairZ80/s100_64fdc.c +++ b/AltairZ80/s100_64fdc.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: s100_64fdc.c 1907 2008-05-21 07:04:17Z hharte $ * + * $Id: s100_64fdc.c 1999 2008-07-22 04:25:28Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -42,7 +42,7 @@ *************************************************************************/ /*#define DBG_MSG */ -#define DBG_MSG + #include "altairz80_defs.h" #if defined (_WIN32) @@ -58,18 +58,23 @@ #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 -#define DRIVE_MSG 0x40 -#define VERBOSE_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define DRIVE_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) +#define IRQ_MSG (1 << 8) #define CROMFDC_MAX_DRIVES 4 #define CROMFDC_ROM_SIZE (8 * 1024) #define CROMFDC_ADDR_MASK (CROMFDC_ROM_SIZE - 1) +#define CROMFDC_SIM_64US 186 /* Number of "ticks" in 64uS, where does this come from? */ + typedef struct { PNP_INFO pnp; /* Plug and Play */ uint32 dma_addr; /* DMA Transfer Address */ @@ -77,6 +82,8 @@ typedef struct { uint8 motor_on; uint8 autowait; uint8 rtc; + uint8 imask; /* Interrupt Mask Register */ + uint8 ipend; /* Interrupt Pending Register */ } CROMFDC_INFO; extern WD179X_INFO_PUB *wd179x_info; @@ -91,50 +98,48 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -t_stat cromfdc_svc (UNIT *uptr); +static t_stat cromfdc_svc (UNIT *uptr); extern REG *sim_PC; extern uint32 PCX; /* external view of PC */ -#define UNIT_V_CROMFDC_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_CROMFDC_WLK (1 << UNIT_V_CROMFDC_WLK) -#define UNIT_V_CROMFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_CROMFDC_VERBOSE (1 << UNIT_V_CROMFDC_VERBOSE) -#define UNIT_V_CROMFDC_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ -#define UNIT_CROMFDC_ROM (1 << UNIT_V_CROMFDC_ROM) -#define CROMFDC_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ +#define UNIT_V_CROMFDC_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_CROMFDC_WLK (1 << UNIT_V_CROMFDC_WLK) +#define UNIT_V_CROMFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_CROMFDC_VERBOSE (1 << UNIT_V_CROMFDC_VERBOSE) +#define UNIT_V_CROMFDC_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ +#define UNIT_CROMFDC_ROM (1 << UNIT_V_CROMFDC_ROM) +#define CROMFDC_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */ #define MOTOR_TO_LIMIT 128 static t_stat cromfdc_reset(DEVICE *cromfdc_dev); static t_stat cromfdc_boot(int32 unitno, DEVICE *dptr); -static t_stat cromfdc_attach(UNIT *uptr, char *cptr); -static t_stat cromfdc_detach(UNIT *uptr); static int32 cromfdc_ext(const int32 port, const int32 io, const int32 data); static int32 cromfdc_timer(const int32 port, const int32 io, const int32 data); static int32 cromfdc_control(const int32 port, const int32 io, const int32 data); static int32 cromfdc_banksel(const int32 port, const int32 io, const int32 data); static int32 cromfdcrom(const int32 port, const int32 io, const int32 data); +static int32 ccs2810_uart_status(const int32 port, const int32 io, const int32 data); -static int32 dipswitch = 0; /* 5-position DIP switch on 64FDC card */ -static int32 trace_level = 0; /* Disable all tracing by default */ +static int32 dipswitch = 0; /* 5-position DIP switch on 64FDC card */ static int32 bootstrap = 0; /* 0 for RDOS 2.52, 1 for RDOS 3.12. */ -static int32 crofdc_type = 64; /* controller type, either 4, 16, or 64. */ +static int32 crofdc_type = 64; /* controller type, either 4, 16, or 64 for Cromemco, 50 for CCS-2422. */ static int32 crofdc_boot = 1; /* BOOT jumper setting, default is auto-boot */ static int32 crofdc_inh_init = 0; /* Inhibit Init (Format) switch, default is not inhibited */ -/* Disk Control/Flags Register, 0x34 (IN) */ +/* Disk Control/Flags Register, 0x34 (IN) / CCS Status Register 1 */ #define CROMFDC_FLAG_DRQ (1 << 7) /* DRQ (All controllers) */ #define CROMFDC_FLAG_BOOT (1 << 6) /* boot# jumper (active low) (All controllers) */ -#define CROMFDC_FLAG_SEL_REQ (1 << 5) /* Head Load (4FDC, 16FDC) / Select Request (64FDC) */ -#define CROMFDC_FLAG_INH_INIT (1 << 4) /* Unassigned (4FDC) / Inhibit_Init# (16FDC, 64FDC) */ -#define CROMFDC_FLAG_MTRON (1 << 3) /* Unassigned (4FDC) / Motor On (16FDC, 64FDC) */ -#define CROMFDC_FLAG_MTO (1 << 2) /* Unassigned (4FDC) / Motor Timeout (16FDC, 64FDC) */ -#define CROMFDC_FLAG_ATO (1 << 1) /* Unassigned (4FDC) / Autowait Timeout (16FDC, 64FDC) */ +#define CROMFDC_FLAG_SEL_REQ (1 << 5) /* Head Load (4FDC, 16FDC) / Select Request (64FDC) / CCS2422 HLD */ +#define CROMFDC_FLAG_INH_INIT (1 << 4) /* Unassigned (4FDC) / Inhibit_Init# (16FDC, 64FDC) / CCS2422 DS4 */ +#define CROMFDC_FLAG_MTRON (1 << 3) /* Unassigned (4FDC) / Motor On (16FDC, 64FDC) / CCS2422 DS3 */ +#define CROMFDC_FLAG_MTO (1 << 2) /* Unassigned (4FDC) / Motor Timeout (16FDC, 64FDC) / CCS2422 DS2 */ +#define CROMFDC_FLAG_ATO (1 << 1) /* Unassigned (4FDC) / Autowait Timeout (16FDC, 64FDC) / CCS2422 DS1 */ #define CROMFDC_FLAG_EOJ (1 << 0) /* End of Job (INTRQ) (All Controllers) (16FDC, 64FDC) */ -/* Disk Control/Flags Register, 0x34 (OUT) */ +/* Disk Control/Flags Register, 0x34 (OUT) / CCS Control Register 1 */ #define CROMFDC_CTRL_AUTOWAIT (1 << 7) /* Auto Wait Enable (All controllers) */ #define CROMFDC_CTRL_DDENS (1 << 6) /* Unassigned (4FDC) / Double Density (16FDC, 64FDC) */ #define CROMFDC_CTRL_MTRON (1 << 5) /* Motor On (All controllers) */ @@ -144,17 +149,68 @@ static int32 crofdc_inh_init = 0; /* Inhibit Init (Format) switch, default #define CROMFDC_CTRL_DS2 (1 << 1) /* Drive Select 2 (All controllers) */ #define CROMFDC_CTRL_DS1 (1 << 0) /* Drive Select 1 (All controllers) */ -/* 64FDC Auxiliary Disk Command, 0x04 (OUT) */ -#define CROMFDC_AUX_RESERVED0 (1 << 0) /* Unused (All Controllers) */ -#define CROMFDC_AUX_CMD_SIDE (1 << 1) /* 16FDC, 64FDC: Side Select* Low=Side 1, High=Side 0. */ -#define CROMFDC_AUX_CTRL_OUT (1 << 2) /* Control Out* (All Controllers) */ -#define CROMFDC_AUX_RESTORE (1 << 3) /* 4FDC, 16FDC Restore* / 64FDC Unused */ -#define CROMFDC_AUX_FAST_SEEK (1 << 4) /* 4FDC, 16FDC Fast Seek* / 64FDC Unused */ -#define CROMFDC_AUX_SEL_OVERRIDE (1 << 5) /* 4FDC Eject Right* / 16FDC, 64FDC Drive Select Override */ -#define CROMFDC_AUX_EJECT (1 << 6) /* 4FDC Eject Left* / 16FDC Eject*, 64FDC Unused */ +/* 64FDC Auxiliary Disk Command, 0x04 (OUT) / CCS Control Register 2 */ #define CROMFDC_AUX_RESERVED7 (1 << 7) /* Unused (All Controllers) */ +#define CROMFDC_AUX_EJECT (1 << 6) /* 4FDC Eject Left* / 16FDC Eject*, 64FDC Unused / CCS2422 - Side Select# */ +#define CCSFDC_CMD_SIDE (1 << 6) /* CCS2422 - Side Select# */ +#define CROMFDC_AUX_SEL_OVERRIDE (1 << 5) /* 4FDC Eject Right* / 16FDC, 64FDC Drive Select Override */ +#define CROMFDC_AUX_FAST_SEEK (1 << 4) /* 4FDC, 16FDC Fast Seek* / 64FDC Unused */ +#define CROMFDC_AUX_RESTORE (1 << 3) /* 4FDC, 16FDC Restore* / 64FDC Unused */ +#define CROMFDC_AUX_CTRL_OUT (1 << 2) /* Control Out* (All Controllers) */ +#define CROMFDC_AUX_CMD_SIDE (1 << 1) /* 16FDC, 64FDC: Side Select* Low=Side 1, High=Side 0. */ +#define CROMFDC_AUX_RESERVED0 (1 << 0) /* Unused (All Controllers) */ +/* 64FDC Interrupt Mask Register, 0x03 (OUT) */ +#define CROMFDC_IRQ_TIMER5 (1 << 7) /* Timer5 Interrupt Mask */ +#define CROMFDC_IRQ_TIMER4 (1 << 6) /* Timer4 Interrupt Mask */ +#define CROMFDC_IRQ_TBE (1 << 5) /* Transmit Buffer Empty Interrupt Mask */ +#define CROMFDC_IRQ_RDA (1 << 4) /* Read Data Available Interrupt Mask */ +#define CROMFDC_IRQ_TIMER3 (1 << 3) /* Timer3 Interrupt Mask */ +#define CROMFDC_IRQ_EOJ (1 << 2) /* End of Job Interrupt Mask */ +#define CROMFDC_IRQ_TIMER2 (1 << 1) /* Timer2 Interrupt Mask */ +#define CROMFDC_IRQ_TIMER1 (1 << 0) /* Timer1 Interrupt Mask */ + +/* 64FDC interrupt "restart" instruction opcodes */ +#define CROMFDC_TIMER1_RST 0xC7 /* RST0 - 0xC7 */ +#define CROMFDC_TIMER2_RST 0xCF /* RST8 - 0xCF */ +#define CROMFDC_EOJ_RST 0xD7 /* RST10 - 0xD7 */ +#define CROMFDC_TIMER3_RST 0xDF /* RST18 - 0xDF */ +#define CROMFDC_RDA_RST 0xE7 /* RST20 - 0xE7 */ +#define CROMFDC_TBE_RST 0xEF /* RST28 - 0xEF */ +#define CROMFDC_TIMER4_RST 0xF7 /* RST30 - 0xF7 */ +#define CROMFDC_TIMER5_RST 0xFF /* RST38 - 0xFF */ + +#define RST_OPCODE_TO_VECTOR(x) (x & 0x38) + +static unsigned char cromfdc_irq_table[8] = { + CROMFDC_TIMER1_RST, + CROMFDC_TIMER2_RST, + CROMFDC_EOJ_RST, + CROMFDC_TIMER3_RST, + CROMFDC_RDA_RST, + CROMFDC_TBE_RST, + CROMFDC_TIMER4_RST, + CROMFDC_TIMER5_RST }; + +static uint8 ipend_to_rst_opcode(uint8 ipend) +{ + uint8 active_intr; + uint8 i,j = 0; + + active_intr = cromfdc_info->imask & cromfdc_info->ipend; + + for(i=1;i != 0;i <<= 1) { +/* printf("%d: %d" NLP, i, active_intr & i); */ + if (active_intr & i) { + return(cromfdc_irq_table[j]); + } + j++; + } + + return (0); +} + /* The CROMFDC does not really have RAM associated with it, but for ease of integration with the * SIMH/AltairZ80 Resource Mapping Scheme, rather than Map and Unmap the ROM, simply implement our @@ -170,10 +226,9 @@ static UNIT cromfdc_unit[] = { }; static REG cromfdc_reg[] = { - { HRDATA (DIPSW, dipswitch, 16), }, - { HRDATA (TRACELEVEL, trace_level, 16), }, - { DRDATA (BOOTSTRAP, bootstrap, 10), }, - { DRDATA (FDCTYPE, crofdc_type, 10), }, + { HRDATA (DIPSW, dipswitch, 8), }, + { DRDATA (BOOTSTRAP, bootstrap, 2), }, + { DRDATA (FDCTYPE, crofdc_type, 8), }, { DRDATA (BOOT, crofdc_boot, 10), }, { DRDATA (INHINIT, crofdc_inh_init, 10), }, { NULL } @@ -182,24 +237,42 @@ static REG cromfdc_reg[] = { static MTAB cromfdc_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_CROMFDC_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_CROMFDC_WLK, UNIT_CROMFDC_WLK, "WRTLCK", "WRTLCK", NULL }, + { UNIT_CROMFDC_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_CROMFDC_WLK, UNIT_CROMFDC_WLK, "WRTLCK", "WRTLCK", NULL }, /* quiet, no warning messages */ - { UNIT_CROMFDC_VERBOSE, 0, "QUIET", "QUIET", NULL }, + { UNIT_CROMFDC_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* verbose, show warning messages */ - { UNIT_CROMFDC_VERBOSE, UNIT_CROMFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM", NULL }, - { UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM", NULL }, + { UNIT_CROMFDC_VERBOSE, UNIT_CROMFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL }, + { UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM", NULL }, + { UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM", NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if(cromfdc_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB cromfdc_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "DRIVE", DRIVE_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "IRQ", IRQ_MSG }, + { NULL, 0 } +}; + DEVICE cromfdc_dev = { "CROMFDC", cromfdc_unit, cromfdc_reg, cromfdc_mod, CROMFDC_MAX_DRIVES, 10, 31, 1, CROMFDC_MAX_DRIVES, CROMFDC_MAX_DRIVES, NULL, NULL, &cromfdc_reset, - &cromfdc_boot, &cromfdc_attach, &cromfdc_detach, - &cromfdc_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &cromfdc_boot, &wd179x_attach, &wd179x_detach, + &cromfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + cromfdc_dt, NULL, "Cromemco 4/16/64 FDC CROMFDC" }; /* This is the CROMFDC RDOS-II ROM. @@ -1240,22 +1313,152 @@ static uint8 cromfdc_rom[2][CROMFDC_ROM_SIZE] = { } }; +unsigned char ccs2422_rom[2048] = { + 0xC3, 0x5B, 0xF0, 0xC3, 0x46, 0xF6, 0xC3, 0x56, 0xF6, 0xC3, 0x00, 0xF6, 0xC3, 0x7C, 0xF6, 0xC3, + 0x10, 0xF6, 0xC3, 0x23, 0xF6, 0xC3, 0x6A, 0xF1, 0xC3, 0x65, 0xF1, 0xC3, 0x8A, 0xF0, 0xC3, 0x94, + 0xF6, 0xC3, 0x94, 0xF6, 0xC3, 0xCF, 0xF3, 0xF8, 0xF0, 0x5E, 0xF5, 0x09, 0xF1, 0xAC, 0xF1, 0x09, + 0xF1, 0x3C, 0xF1, 0xFD, 0xF1, 0xD0, 0xF5, 0x4D, 0xF2, 0x09, 0xF1, 0x09, 0xF1, 0x09, 0xF1, 0x5D, + 0xF2, 0x09, 0xF1, 0x55, 0xF2, 0xA7, 0xF5, 0xBD, 0xF5, 0xF6, 0xF4, 0x67, 0xF2, 0x8F, 0xF2, 0x09, + 0xF1, 0x91, 0xF1, 0xF7, 0xF4, 0xEC, 0xF2, 0x9F, 0xF4, 0x82, 0xF1, 0xF3, 0x31, 0x3F, 0x00, 0x21, + 0x00, 0xC3, 0x11, 0xB2, 0xF6, 0x06, 0x10, 0xD5, 0xE5, 0x10, 0xFC, 0x31, 0x95, 0xF0, 0x3E, 0xC5, + 0x01, 0x00, 0xF0, 0x21, 0xFF, 0xFF, 0x24, 0x7E, 0x2F, 0x77, 0xBE, 0x2F, 0x77, 0x20, 0x04, 0x7C, + 0xB8, 0x20, 0xF3, 0x25, 0x01, 0xDE, 0xFF, 0x09, 0xC1, 0xC9, 0xE5, 0xCD, 0x6F, 0xF0, 0x7D, 0xD6, + 0x3C, 0x30, 0x01, 0x25, 0x44, 0xE1, 0xC9, 0x99, 0xF0, 0xF9, 0x11, 0x45, 0xF4, 0xEB, 0x01, 0x1D, + 0x00, 0xED, 0xB0, 0x01, 0x06, 0x00, 0xD5, 0xE1, 0x2B, 0xED, 0xB0, 0x21, 0xE8, 0xFF, 0x39, 0xE5, + 0x23, 0x23, 0x22, 0x06, 0x00, 0x16, 0x0A, 0xC5, 0x15, 0x20, 0xFC, 0xCD, 0x59, 0xF5, 0xCD, 0x9F, + 0xF4, 0xCD, 0x94, 0xF6, 0x21, 0x90, 0xF4, 0xCD, 0x95, 0xF6, 0x18, 0x43, 0x06, 0x01, 0x21, 0x00, + 0x00, 0x18, 0x0C, 0x10, 0x79, 0x20, 0x32, 0x05, 0xC8, 0x21, 0x00, 0x00, 0xCD, 0x7B, 0xF3, 0x4F, + 0xCD, 0xB0, 0xF3, 0x38, 0x08, 0x29, 0x29, 0x29, 0x29, 0xB5, 0x6F, 0x18, 0xEF, 0xE3, 0xE5, 0x79, + 0xCD, 0xC3, 0xF3, 0x30, 0xE0, 0x10, 0x12, 0xC9, 0xCD, 0x7B, 0xF3, 0x21, 0x6E, 0xF1, 0x11, 0x05, + 0x00, 0x06, 0x04, 0xBE, 0x28, 0x42, 0x19, 0x10, 0xFA, 0x21, 0x8C, 0xF4, 0xCD, 0x98, 0xF6, 0x2A, + 0x06, 0x00, 0xF9, 0x21, 0x0F, 0xF1, 0xE5, 0x22, 0x01, 0x00, 0x3E, 0xC3, 0x32, 0x00, 0x00, 0xCD, + 0xA9, 0xF6, 0xCD, 0x78, 0xF3, 0xD6, 0x41, 0x38, 0xE0, 0xFE, 0x1A, 0x30, 0xDC, 0x87, 0x5F, 0x16, + 0x00, 0x06, 0x02, 0x21, 0x27, 0xF0, 0x19, 0x7E, 0x23, 0x66, 0x6F, 0xE9, 0xCD, 0x86, 0xF3, 0x71, + 0xCD, 0x8F, 0xF3, 0x30, 0xFA, 0xD1, 0x18, 0xC7, 0x50, 0x06, 0x04, 0xCD, 0x78, 0xF3, 0x23, 0xBE, + 0x20, 0x81, 0x68, 0x2D, 0x42, 0x26, 0x03, 0x05, 0x28, 0x04, 0x29, 0x29, 0x10, 0xFC, 0x3A, 0x03, + 0x00, 0xB4, 0xAC, 0xB5, 0x4F, 0x79, 0x32, 0x03, 0x00, 0xC9, 0x3A, 0x03, 0x00, 0xC9, 0x4C, 0x32, + 0x31, 0x4C, 0x54, 0x50, 0x32, 0x31, 0x50, 0x54, 0x52, 0x32, 0x31, 0x50, 0x54, 0x43, 0x31, 0x42, + 0x43, 0x54, 0x06, 0x02, 0xCD, 0x8F, 0xF6, 0xFE, 0x07, 0x20, 0xF7, 0xCD, 0x7E, 0xF3, 0x10, 0xF4, + 0xC9, 0xCD, 0x86, 0xF3, 0x0A, 0xC5, 0x46, 0xB8, 0x28, 0x0C, 0xF5, 0xCD, 0xFB, 0xF5, 0x78, 0xCD, + 0xF4, 0xF5, 0xF1, 0xCD, 0xE6, 0xF5, 0xC1, 0xCD, 0x9B, 0xF3, 0x18, 0xE8, 0xCD, 0xA4, 0xF6, 0xCD, + 0xFB, 0xF5, 0x7D, 0xCD, 0xF0, 0xF1, 0xE5, 0x7E, 0xCD, 0xE6, 0xF5, 0xCD, 0x8F, 0xF3, 0x38, 0x2A, + 0xCD, 0xFE, 0xF5, 0x7D, 0xE6, 0x0F, 0x20, 0xEF, 0xE1, 0x7D, 0xE6, 0x0F, 0xCD, 0xF5, 0xF1, 0x7E, + 0xE6, 0x7F, 0x4F, 0xFE, 0x20, 0x38, 0x04, 0xFE, 0x7E, 0x38, 0x02, 0x0E, 0x2E, 0xCD, 0x09, 0xF0, + 0xCD, 0x9C, 0xF3, 0x7D, 0xE6, 0x0F, 0x20, 0xE7, 0x18, 0xC5, 0x93, 0xCD, 0xF0, 0xF1, 0x18, 0xD8, + 0xE6, 0x0F, 0x47, 0x87, 0x80, 0x47, 0x04, 0xCD, 0xFE, 0xF5, 0x10, 0xFB, 0xC9, 0xCD, 0xC0, 0xF3, + 0x38, 0x37, 0x28, 0x10, 0xCD, 0xCC, 0xF0, 0xD1, 0x21, 0x34, 0x00, 0x39, 0x72, 0x2B, 0x73, 0x79, + 0xFE, 0x0D, 0x28, 0x25, 0x06, 0x02, 0x21, 0x35, 0x00, 0x39, 0xC5, 0xE5, 0x06, 0x02, 0xCD, 0xD7, + 0xF0, 0xD1, 0xE1, 0x7A, 0xB3, 0x28, 0x0A, 0x73, 0x23, 0x72, 0x23, 0x1A, 0x77, 0x23, 0x3E, 0xCF, + 0x12, 0x79, 0xFE, 0x0D, 0xC1, 0x28, 0x02, 0x10, 0xE1, 0xCD, 0xA9, 0xF6, 0xE1, 0x21, 0x43, 0xF4, + 0xE5, 0x21, 0xCF, 0xF3, 0x22, 0x09, 0x00, 0x21, 0x18, 0x00, 0x39, 0xD1, 0xE9, 0xCD, 0xD7, 0xF0, + 0xC1, 0xED, 0x58, 0x18, 0x51, 0xCD, 0xD9, 0xF0, 0xD1, 0xC1, 0xED, 0x59, 0xC9, 0xCD, 0x86, 0xF3, + 0x7E, 0x02, 0xCD, 0x9B, 0xF3, 0x18, 0xF9, 0xCD, 0xD7, 0xF0, 0xE1, 0x7E, 0xCD, 0xF4, 0xF5, 0xCD, + 0xC0, 0xF3, 0xD8, 0x28, 0x0F, 0xFE, 0x0A, 0x28, 0x0D, 0xE5, 0xCD, 0xCC, 0xF0, 0xD1, 0xE1, 0x73, + 0x79, 0xFE, 0x0D, 0xC8, 0x23, 0x23, 0x2B, 0x7D, 0xE6, 0x07, 0xCC, 0xFB, 0xF5, 0x18, 0xDC, 0xCD, + 0xA4, 0xF6, 0x7E, 0xF5, 0x2F, 0x77, 0xAE, 0xC4, 0xA1, 0xF2, 0xF1, 0x77, 0xCD, 0x9C, 0xF3, 0x18, + 0xF1, 0xD5, 0x5F, 0xCD, 0xFB, 0xF5, 0x06, 0x08, 0x7B, 0x07, 0x5F, 0x3E, 0x18, 0x17, 0x4F, 0xCD, + 0x09, 0xF0, 0x10, 0xF4, 0xD1, 0xC9, 0x23, 0x23, 0x34, 0xC8, 0xF2, 0xC1, 0xF2, 0xF6, 0x80, 0x18, + 0x02, 0xE6, 0x7F, 0x35, 0xBE, 0x20, 0xEF, 0xCD, 0xFE, 0xF5, 0xCD, 0x15, 0xF3, 0xCD, 0xF7, 0xF5, + 0xCD, 0xC0, 0xF3, 0xD8, 0x28, 0x12, 0xE5, 0xCD, 0xCC, 0xF0, 0xE1, 0x7D, 0x13, 0x12, 0xE3, 0x7E, + 0xE3, 0x07, 0x30, 0x03, 0x13, 0x7C, 0x12, 0xE1, 0x79, 0xFE, 0x0D, 0xC8, 0x21, 0x3D, 0xF3, 0xCD, + 0xC0, 0xF3, 0x38, 0x0B, 0x28, 0xF9, 0xFE, 0x27, 0x20, 0xBE, 0x21, 0x55, 0xF3, 0x18, 0xF0, 0x7E, + 0x4F, 0x3C, 0xC8, 0xFC, 0xA9, 0xF6, 0xCD, 0x09, 0xF0, 0xCD, 0xF7, 0xF5, 0xCD, 0x15, 0xF3, 0xCD, + 0xFE, 0xF5, 0x23, 0x18, 0xEA, 0x23, 0x7E, 0xE6, 0x3F, 0xC6, 0x02, 0xEB, 0x6F, 0x26, 0x00, 0x39, + 0xEB, 0x7E, 0x06, 0x01, 0x07, 0x30, 0x0E, 0x04, 0x07, 0x30, 0x0A, 0xE5, 0x1A, 0x67, 0x1B, 0x1A, + 0x6F, 0x7E, 0xE1, 0x10, 0x01, 0x1A, 0xCD, 0xE6, 0xF5, 0x1B, 0x10, 0xF9, 0xC9, 0xC1, 0x15, 0x42, + 0x13, 0x43, 0x12, 0x44, 0x11, 0x45, 0x10, 0x46, 0x14, 0x48, 0x31, 0x4C, 0x30, 0xCD, 0xF1, 0x50, + 0xB4, 0x53, 0x97, 0x49, 0x03, 0xC1, 0x09, 0x42, 0x0B, 0x43, 0x0A, 0x44, 0x0D, 0x45, 0x0C, 0x46, + 0x08, 0x48, 0x0F, 0x4C, 0x0E, 0xCD, 0xCF, 0x58, 0x87, 0x59, 0x85, 0x52, 0x02, 0xFF, 0xE6, 0x0F, + 0xC6, 0x90, 0x27, 0xCE, 0x40, 0x27, 0x4F, 0xC9, 0xCD, 0xF7, 0xF5, 0xCD, 0x8F, 0xF6, 0xC5, 0x4F, + 0xCD, 0x09, 0xF0, 0x79, 0xC1, 0xC9, 0x04, 0xCD, 0xD9, 0xF0, 0xC1, 0xD1, 0xC3, 0xAA, 0xF6, 0x23, + 0x7C, 0xB5, 0x37, 0xC8, 0x7B, 0x95, 0x7A, 0x9C, 0xC9, 0xD1, 0xC9, 0x03, 0xCD, 0x8F, 0xF3, 0x38, + 0xF8, 0xCD, 0x12, 0xF0, 0xB7, 0xC8, 0xCD, 0x8F, 0xF6, 0xFE, 0x13, 0x20, 0xEC, 0xC3, 0x8F, 0xF6, + 0xD6, 0x30, 0xD8, 0xFE, 0x17, 0x3F, 0xD8, 0xFE, 0x0A, 0x3F, 0xD0, 0xD6, 0x07, 0xFE, 0x0A, 0xC9, + 0xCD, 0x7B, 0xF3, 0xFE, 0x20, 0xC8, 0xFE, 0x2C, 0xC8, 0xFE, 0x0D, 0x37, 0xC8, 0x3F, 0xC9, 0xE5, + 0xD5, 0xC5, 0xF5, 0xCD, 0x6F, 0xF0, 0xEB, 0x21, 0x0A, 0x00, 0x39, 0x06, 0x04, 0xEB, 0x2B, 0x72, + 0x2B, 0x73, 0xD1, 0x10, 0xF9, 0xC1, 0x0B, 0xF9, 0x21, 0x25, 0x00, 0x39, 0xD5, 0x16, 0x02, 0x7E, + 0x91, 0x23, 0x7E, 0x98, 0x28, 0x06, 0x23, 0x23, 0x15, 0x20, 0xF4, 0x03, 0x21, 0x20, 0x00, 0xD1, + 0x39, 0x73, 0x23, 0x72, 0xC5, 0x0E, 0x2A, 0xCD, 0x09, 0xF0, 0xD1, 0x3E, 0xF4, 0xBA, 0x28, 0x09, + 0x23, 0x23, 0x73, 0x23, 0x72, 0xEB, 0xCD, 0xE1, 0xF5, 0x21, 0x25, 0x00, 0x39, 0x01, 0x00, 0x02, + 0x5E, 0x71, 0x23, 0x56, 0x71, 0x23, 0x7B, 0xB2, 0x28, 0x02, 0x7E, 0x12, 0x23, 0x10, 0xF1, 0x08, + 0xD9, 0xE5, 0xD5, 0xC5, 0xF5, 0xDD, 0xE5, 0xFD, 0xE5, 0xED, 0x57, 0x47, 0xED, 0x5F, 0x4F, 0xC5, + 0xC3, 0x13, 0xF1, 0xE5, 0xCF, 0xC1, 0x79, 0xED, 0x4F, 0x78, 0xED, 0x47, 0xDD, 0xE1, 0xFD, 0xE1, + 0xF1, 0xC1, 0xD1, 0xE1, 0x08, 0xD9, 0xD1, 0xC1, 0xF1, 0xE1, 0xF9, 0x00, 0x21, 0x00, 0x00, 0xC3, + 0x00, 0x00, 0xAF, 0x32, 0x03, 0x00, 0x21, 0x6C, 0xF4, 0xC3, 0xB5, 0xF6, 0x49, 0x2F, 0x4F, 0x20, + 0x45, 0x52, 0xD2, 0x44, 0x53, 0x4B, 0x20, 0x45, 0x52, 0x52, 0x3A, 0x20, 0x55, 0xAD, 0x20, 0x54, + 0xAD, 0x20, 0x53, 0xAD, 0x20, 0x43, 0xAD, 0x20, 0x45, 0xAD, 0x0D, 0x8A, 0x3F, 0x3F, 0x3F, 0xBF, + 0x4D, 0x4F, 0x53, 0x53, 0x20, 0x56, 0x45, 0x52, 0x53, 0x20, 0x32, 0x2E, 0x32, 0x0D, 0x8A, 0x3E, + 0x0F, 0xD3, 0x24, 0x11, 0x40, 0x00, 0x62, 0x6A, 0xDB, 0x26, 0xA3, 0x28, 0xFB, 0xDB, 0x26, 0x23, + 0xA3, 0xA3, 0xC2, 0xAD, 0xF4, 0xE5, 0x29, 0x5C, 0x19, 0x19, 0xE5, 0x29, 0x29, 0xDB, 0x20, 0x2B, + 0x7D, 0xB4, 0xC2, 0xBD, 0xF4, 0xE1, 0x3E, 0x83, 0xD3, 0x23, 0x7C, 0xD3, 0x21, 0x7D, 0xD3, 0x20, + 0x3E, 0x03, 0xD3, 0x23, 0xAF, 0xD3, 0x21, 0xD3, 0x25, 0xCD, 0xCE, 0xF6, 0xE6, 0x7F, 0xFE, 0x0D, + 0xE1, 0xC8, 0x5D, 0x54, 0xCD, 0xEE, 0xF4, 0xCD, 0xEE, 0xF4, 0x19, 0xE5, 0x18, 0xD8, 0xB7, 0x7C, + 0x1F, 0x67, 0x7D, 0x1F, 0x6F, 0xC9, 0x3E, 0xAF, 0x32, 0x4B, 0x00, 0x21, 0x80, 0x00, 0x22, 0x49, + 0x00, 0xCD, 0xA4, 0xF6, 0xD5, 0x3A, 0x4B, 0x00, 0xB7, 0x20, 0x08, 0x22, 0x4C, 0x00, 0xCD, 0xEB, + 0xF6, 0x18, 0x03, 0xCD, 0xE7, 0xF6, 0xD1, 0x20, 0x67, 0x3A, 0x44, 0x00, 0x47, 0xDB, 0x31, 0xB7, + 0x20, 0x0B, 0x06, 0x1A, 0x3A, 0x4A, 0x00, 0xE6, 0x10, 0x20, 0x02, 0x06, 0x12, 0xE5, 0x21, 0x42, + 0x00, 0x7E, 0xB8, 0x38, 0x1B, 0x3A, 0x45, 0x00, 0xB7, 0x28, 0x0B, 0x3A, 0x43, 0x00, 0xFE, 0xD0, + 0x20, 0x04, 0x3E, 0x90, 0x18, 0x05, 0x3E, 0xD0, 0x2B, 0x34, 0x23, 0x32, 0x43, 0x00, 0x36, 0x00, + 0x34, 0xE1, 0x2B, 0xCD, 0x9C, 0xF3, 0xD5, 0x18, 0xAC, 0xDB, 0x34, 0xE6, 0x40, 0xC0, 0x21, 0x00, + 0x00, 0x22, 0x40, 0x00, 0x21, 0x01, 0xD0, 0x22, 0x42, 0x00, 0x21, 0x80, 0x00, 0x22, 0x49, 0x00, + 0xCD, 0xE7, 0xF6, 0x20, 0x0B, 0x3E, 0x02, 0x32, 0x42, 0x00, 0xCD, 0xE7, 0xF6, 0xCA, 0x80, 0x00, + 0x21, 0x73, 0xF4, 0xCD, 0x95, 0xF6, 0x3A, 0x40, 0x00, 0xCD, 0xA1, 0xF5, 0x3A, 0x41, 0x00, 0xCD, + 0xA1, 0xF5, 0x3A, 0x42, 0x00, 0xCD, 0xA1, 0xF5, 0x3A, 0x48, 0x00, 0xCD, 0xA1, 0xF5, 0x3A, 0x47, + 0x00, 0xCD, 0xE6, 0xF5, 0xC3, 0x98, 0xF6, 0xCD, 0x86, 0xF3, 0x7D, 0xB7, 0xFA, 0x09, 0xF1, 0xFE, + 0x04, 0xD2, 0x09, 0xF1, 0x32, 0x40, 0x00, 0x6B, 0x61, 0x22, 0x44, 0x00, 0xC9, 0xCD, 0x86, 0xF3, + 0x61, 0x22, 0x41, 0x00, 0x7B, 0xB7, 0x3E, 0xD0, 0x28, 0x02, 0x3E, 0x90, 0x32, 0x43, 0x00, 0xC9, + 0xCD, 0xA4, 0xF6, 0xE5, 0x19, 0xCD, 0xFB, 0xF5, 0xE1, 0xB7, 0xED, 0x52, 0x18, 0x03, 0xCD, 0xA9, + 0xF6, 0x7C, 0xCD, 0xE6, 0xF5, 0x7D, 0xF5, 0x0F, 0x0F, 0x0F, 0x0F, 0xCD, 0xEF, 0xF5, 0xF1, 0xCD, + 0x6E, 0xF3, 0x18, 0x0C, 0xCD, 0xE6, 0xF5, 0x0E, 0x2D, 0x18, 0x05, 0xCD, 0xDE, 0xF5, 0x0E, 0x20, + 0x3A, 0x03, 0x00, 0xE6, 0x03, 0xCA, 0xDE, 0xF6, 0xFE, 0x02, 0xFA, 0x62, 0xF4, 0xC2, 0x62, 0xF4, + 0x3A, 0x03, 0x00, 0xE6, 0xC0, 0xCA, 0xDE, 0xF6, 0xFE, 0x80, 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, + 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x03, 0xCA, 0xC6, 0xF6, 0xFE, 0x02, 0xFA, 0x62, 0xF4, + 0xC2, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x0C, 0xCA, 0xC6, 0xF6, 0xFE, 0x08, 0xFA, 0x62, 0xF4, + 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x03, 0xCA, 0xCE, 0xF6, 0xFE, 0x02, + 0xFA, 0x62, 0xF4, 0xC2, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x0C, 0xCA, 0xCE, 0xF6, 0xFE, 0x08, + 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0xC0, 0xCA, 0xD6, + 0xF6, 0xFE, 0x80, 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, + 0x30, 0xCA, 0xDE, 0xF6, 0xFE, 0x20, 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0xCD, + 0x46, 0xF6, 0xE6, 0x7F, 0xC9, 0xCD, 0xA9, 0xF6, 0xC5, 0x4E, 0xCD, 0x00, 0xF6, 0x23, 0x79, 0x07, + 0x30, 0xF7, 0xC1, 0xC9, 0xCD, 0xD9, 0xF0, 0xD1, 0xE1, 0xE5, 0x21, 0xC2, 0xF6, 0xCD, 0x98, 0xF6, + 0xE1, 0xC9, 0x21, 0xBB, 0xF6, 0xCD, 0x95, 0xF6, 0xC3, 0x00, 0x00, 0x52, 0x53, 0x54, 0x20, 0x45, + 0x52, 0xD2, 0x0D, 0x0A, 0x00, 0x80, 0xDB, 0x25, 0xE6, 0x01, 0xC8, 0xC6, 0xFE, 0xC9, 0xDB, 0x25, + 0x1F, 0x30, 0xFB, 0xDB, 0x20, 0xC9, 0xDB, 0x25, 0xE6, 0x20, 0xC8, 0xC6, 0xBF, 0xC9, 0xCD, 0xD6, + 0xF6, 0x28, 0xFB, 0x79, 0xD3, 0x20, 0xC9, 0x22, 0x4C, 0x00, 0x3E, 0xAF, 0x32, 0x4B, 0x00, 0x06, + 0x0A, 0xC5, 0xCD, 0x3B, 0xF7, 0xCC, 0xFD, 0xF6, 0xC1, 0xC8, 0x10, 0xF5, 0xC9, 0x5F, 0x3A, 0x4B, + 0x00, 0xB7, 0x7B, 0x28, 0x10, 0x32, 0x48, 0x00, 0xD3, 0x30, 0xED, 0xB2, 0x15, 0x20, 0xFB, 0xCD, + 0x2E, 0xF7, 0xE6, 0x9C, 0xC9, 0xF6, 0x20, 0x32, 0x48, 0x00, 0xD3, 0x30, 0xED, 0xB3, 0x15, 0x20, + 0xFB, 0x18, 0x0B, 0x06, 0x08, 0x3A, 0x46, 0x00, 0xB0, 0x32, 0x48, 0x00, 0xD3, 0x30, 0xDB, 0x34, + 0x1F, 0x30, 0xFB, 0xDB, 0x30, 0x32, 0x47, 0x00, 0xE6, 0xFC, 0xC9, 0xCD, 0x8E, 0xF7, 0xC4, 0x23, + 0xF7, 0xF8, 0x3A, 0x42, 0x00, 0xD3, 0x32, 0xDB, 0x31, 0x4F, 0x3A, 0x41, 0x00, 0xB9, 0x28, 0x0C, + 0xD3, 0x33, 0x06, 0x1C, 0xCD, 0x25, 0xF7, 0xE6, 0x98, 0xC0, 0xDB, 0x31, 0xB7, 0x21, 0x40, 0x00, + 0x28, 0x03, 0x3A, 0x51, 0x00, 0x29, 0x3D, 0xF2, 0x65, 0xF7, 0xE5, 0x0E, 0x80, 0xCD, 0xC3, 0xF7, + 0xDB, 0x34, 0xE6, 0x20, 0x3E, 0x04, 0x28, 0x01, 0xAF, 0xC6, 0x88, 0x2A, 0x4C, 0x00, 0xD1, 0x43, + 0x15, 0x14, 0x20, 0x01, 0x14, 0x0E, 0x33, 0xBF, 0xC9, 0x06, 0x58, 0xCD, 0x25, 0xF7, 0x2A, 0x49, + 0x00, 0x7C, 0xBD, 0xC8, 0x0E, 0x80, 0xCD, 0xC3, 0xF7, 0xCD, 0x33, 0xF7, 0xF8, 0xE5, 0x21, 0x4E, + 0x00, 0x01, 0x33, 0x06, 0x16, 0x01, 0x3E, 0xC4, 0xCD, 0x05, 0xF7, 0xE1, 0x28, 0x08, 0x3E, 0x40, + 0xBE, 0xD8, 0xB6, 0x77, 0x18, 0xD8, 0xDB, 0x32, 0xD3, 0x31, 0xB7, 0x28, 0xCC, 0x7E, 0x32, 0x49, + 0x00, 0xAF, 0xC9, 0x21, 0x4A, 0x00, 0x7E, 0xB7, 0x20, 0x25, 0x3A, 0x40, 0x00, 0x47, 0x04, 0xAF, + 0x37, 0x17, 0x10, 0xFD, 0xF6, 0x20, 0x77, 0xD3, 0x34, 0x11, 0x46, 0x00, 0x3E, 0x03, 0x12, 0xCD, + 0x23, 0xF7, 0xF8, 0xDB, 0x04, 0x1F, 0x30, 0x07, 0x3E, 0x10, 0xB6, 0x77, 0x3E, 0x02, 0x12, 0xDB, + 0x31, 0xB7, 0x7E, 0x20, 0x02, 0xE6, 0xBF, 0xB1, 0xD3, 0x34, 0x3A, 0x43, 0x00, 0xD3, 0x04, 0xC9 +}; - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 cromfdc_hasProperty(uint32 property) { +/* returns TRUE iff there exists a disk with 'property' */ +static int32 cromfdc_hasProperty(uint32 property) +{ int32 i; for (i = 0; i < CROMFDC_MAX_DRIVES; i++) - if (cromfdc_dev.units[i].flags & property) return TRUE; + if (cromfdc_dev.units[i].flags & property) + return TRUE; return FALSE; } static uint8 motor_timeout = 0; /* Unit service routine */ -t_stat cromfdc_svc (UNIT *uptr) +static t_stat cromfdc_svc (UNIT *uptr) { - if(cromfdc_info->motor_on == 1) { motor_timeout ++; if(motor_timeout == MOTOR_TO_LIMIT) { @@ -1266,7 +1469,10 @@ t_stat cromfdc_svc (UNIT *uptr) cromfdc_info->rtc ++; - sim_activate (cromfdc_unit, cromfdc_unit->wait); /* requeue! */ + TRACE_PRINT(VERBOSE_MSG, ("CROMFDC: " ADDRESS_FORMAT " Timer IRQ" NLP, PCX)); + cromfdc_info->ipend |= CROMFDC_IRQ_TIMER3; + +/* sim_activate (cromfdc_unit, cromfdc_unit->wait); */ /* requeue! */ return SCPE_OK; } @@ -1285,13 +1491,16 @@ static t_stat cromfdc_reset(DEVICE *dptr) sim_map_resource(0x03, 2, RESOURCE_TYPE_IO, &cromfdc_ext, TRUE); sim_map_resource(0x05, 5, RESOURCE_TYPE_IO, &cromfdc_timer, TRUE); sim_map_resource(0x34, 1, RESOURCE_TYPE_IO, &cromfdc_control, TRUE); -/* sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &cromfdc_banksel, TRUE);*/ + sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &cromfdc_banksel, TRUE); + if(crofdc_type == 50) { /* CCS2422 */ + sim_map_resource(0x26, 1, RESOURCE_TYPE_IO, &ccs2810_uart_status, TRUE); + } } else { /* Connect CROMFDC ROM at base address */ if (cromfdc_hasProperty(UNIT_CROMFDC_ROM)) { - TRACE_PRINT(VERBOSE_MSG, ("CROMFDC: ROM Enabled." NLP)) + TRACE_PRINT(VERBOSE_MSG, ("CROMFDC: ROM Enabled." NLP)); if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &cromfdcrom, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + printf("%s: error mapping MEM resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); return SCPE_ARG; } } else { @@ -1299,71 +1508,61 @@ static t_stat cromfdc_reset(DEVICE *dptr) } /* Connect CROMFDC Interrupt, and Aux Disk Registers */ if(sim_map_resource(0x03, 0x02, RESOURCE_TYPE_IO, &cromfdc_ext, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); return SCPE_ARG; } /* Connect CROMFDC Timer Registers */ if(sim_map_resource(0x05, 0x05, RESOURCE_TYPE_IO, &cromfdc_timer, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); return SCPE_ARG; } /* Connect CROMFDC Disk Flags and Control Register */ if(sim_map_resource(0x34, 0x01, RESOURCE_TYPE_IO, &cromfdc_control, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); return SCPE_ARG; } /* Connect CROMFDC Bank Select Register */ -/* if(sim_map_resource(0x40, 0x1, RESOURCE_TYPE_IO, &cromfdc_banksel, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + if(sim_map_resource(0x40, 0x1, RESOURCE_TYPE_IO, &cromfdc_banksel, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); return SCPE_ARG; } -*/ + + /* Connect CCS 2810 UART Status Register (needed by MOSS 2.2 Monitor */ + if(sim_map_resource(0x26, 0x01, RESOURCE_TYPE_IO, &ccs2810_uart_status, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } else { + TRACE_PRINT(VERBOSE_MSG, ("Mapped CCS2810 UART Status at 0x26" NLP)); + } + } cromfdc_info->rom_disabled = FALSE; - sim_activate (cromfdc_unit, cromfdc_unit->wait); /* requeue! */ +/* sim_activate (cromfdc_unit, cromfdc_unit->wait); */ /* requeue! */ return SCPE_OK; } static t_stat cromfdc_boot(int32 unitno, DEVICE *dptr) { - if((crofdc_type != 4) && (crofdc_type != 16) && (crofdc_type != 64)) { - printf("Invalid fdc_type: %d, must be 4, 16, or 64." NLP, crofdc_type); + if((crofdc_type != 4) && (crofdc_type != 16) && (crofdc_type != 64) && (crofdc_type != 50)) { + printf("Invalid fdc_type: %d, must be 4, 16, or 64 (or 50 for CCS2422.)" NLP, crofdc_type); return SCPE_ARG; } + bootstrap &= 0x01; DBG_PRINT(("Booting %dFDC Controller, bootstrap=%d" NLP, crofdc_type, bootstrap)); /* Re-enable the ROM in case it was disabled */ cromfdc_info->rom_disabled = FALSE; - /* Set the PC to 0, and go. */ + /* Set the PC to C000, and go. */ *((int32 *) sim_PC->loc) = 0xC000; return SCPE_OK; } -/* Attach routine */ -static t_stat cromfdc_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - r = wd179x_attach(uptr, cptr); - - return r; -} - -/* Detach routine */ -static t_stat cromfdc_detach(UNIT *uptr) -{ - t_stat r; - - r = wd179x_detach(uptr); - - return r; -} - static int32 cromfdcrom(const int32 Addr, const int32 write, const int32 data) { /* DBG_PRINT(("CROMFDC: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ @@ -1372,14 +1571,14 @@ static int32 cromfdcrom(const int32 Addr, const int32 write, const int32 data) return 0; } else { if(cromfdc_info->rom_disabled == FALSE) { - return(cromfdc_rom[bootstrap][Addr & CROMFDC_ADDR_MASK]); + return(cromfdc_rom[bootstrap & 0x01][Addr & CROMFDC_ADDR_MASK]); } else { return(cromfdcram[Addr & CROMFDC_ADDR_MASK]); } } } -/* Disk Control/Flags Register, 0x34 */ +/* Disk Control/Flags Register, 0x34 / CCS2422 Control1/Status1 */ static int32 cromfdc_control(const int32 port, const int32 io, const int32 data) { int32 result = 0; @@ -1439,51 +1638,88 @@ static int32 cromfdc_control(const int32 port, const int32 io, const int32 data) result = (crofdc_boot) ? 0 : CROMFDC_FLAG_BOOT; result |= (wd179x_info->intrq) ? CROMFDC_FLAG_EOJ : 0; result |= (wd179x_info->drq) ? CROMFDC_FLAG_DRQ : 0; - result |= (motor_timeout < MOTOR_TO_LIMIT) ? CROMFDC_FLAG_SEL_REQ : 0; - if(crofdc_type > 4) { /* 16, 64FDC */ - result |= (cromfdc_info->motor_on) ? CROMFDC_FLAG_MTRON : 0; - result |= (motor_timeout == MOTOR_TO_LIMIT) ? CROMFDC_FLAG_MTO : 0; - result |= (crofdc_inh_init) ? 0 : CROMFDC_FLAG_INH_INIT; + if(crofdc_type != 50) { /* Cromemco Controller */ + result |= (motor_timeout < MOTOR_TO_LIMIT) ? CROMFDC_FLAG_SEL_REQ : 0; + if(crofdc_type > 4) { /* 16, 64FDC */ + result |= (cromfdc_info->motor_on) ? CROMFDC_FLAG_MTRON : 0; + result |= (motor_timeout == MOTOR_TO_LIMIT) ? CROMFDC_FLAG_MTO : 0; + result |= (crofdc_inh_init) ? 0 : CROMFDC_FLAG_INH_INIT; + } else { + result |= 0x1E; /* Make unused bits '1' on 4FDC */ + } + } else { /* CCS 2422 Controller */ + switch(wd179x_info->sel_drive) { + case 1: + result |= 0x02; + break; + case 2: + result |= 0x04; + break; + case 3: + result |= 0x08; + break; + case 4: + result |= 0x10; + break; + } + +/* printf("CCS2422FDC: " ADDRESS_FORMAT " Read STATUS1=0x%02x" NLP, PCX, result); */ } - TRACE_PRINT(VERBOSE_MSG, + TRACE_PRINT(STATUS_MSG, ("CROMFDC: " ADDRESS_FORMAT " Read DISK FLAGS, Port 0x%02x Result 0x%02x" NLP, PCX, port, result)) } return result; } -/* 64FDC Interrupt and Auxiliary Disk Status */ -/* 0x03-04 */ +/* + * 64FDC Interrupt and Auxiliary Disk Status 0x03-04 + * For CCS2422, this is the Control2/Status2 Register (0x04 only) + */ static int32 cromfdc_ext(const int32 port, const int32 io, const int32 data) { int32 result; if(io) { /* I/O Write */ if(port == 0x4) { - if((data & CROMFDC_AUX_CMD_SIDE) == 0) { - if(crofdc_type == 4) { /* 4FDC */ - TRACE_PRINT(DRIVE_MSG, - ("CROMFDC: " ADDRESS_FORMAT " WR CTRL: Cannot set side 1 on 4FDC" NLP, PCX)); + if(crofdc_type != 50) { /* Cromemco Controller */ + if((data & CROMFDC_AUX_CMD_SIDE) == 0) { + if(crofdc_type == 4) { /* 4FDC */ + TRACE_PRINT(DRIVE_MSG, + ("CROMFDC: " ADDRESS_FORMAT " WR CTRL: Cannot set side 1 on 4FDC" NLP, PCX)); + } else { + wd179x_info->fdc_head = 1; + } } else { - wd179x_info->fdc_head = 1; + wd179x_info->fdc_head = 0; } - } else { - wd179x_info->fdc_head = 0; - } #if 0 /* hharte - nothing implemented for these */ - if((data & CROMFDC_AUX_EJECT) == 0) { - printf("CROMFDC: Eject\n"); - } - if((data & CROMFDC_AUX_SEL_OVERRIDE) == 0) { - printf("CROMFDC: Sel Override\n"); - } - if((data & CROMFDC_AUX_CTRL_OUT) == 0) { - printf("CROMFDC: Ctrl Out\n"); - } + if((data & CROMFDC_AUX_EJECT) == 0) { + printf("CROMFDC: Eject" NLP); + } + if((data & CROMFDC_AUX_SEL_OVERRIDE) == 0) { + printf("CROMFDC: Sel Override" NLP); + } + if((data & CROMFDC_AUX_CTRL_OUT) == 0) { + printf("CROMFDC: Ctrl Out" NLP); + } #endif /* 0 */ - if((data & CROMFDC_AUX_RESTORE) == 0) { - wd179x_external_restore(); + if(crofdc_type < 64) { + if((data & CROMFDC_AUX_RESTORE) == 0) { + wd179x_external_restore(); + } + } + } else { /* CCS 2422 Controller */ + if((data & CCSFDC_CMD_SIDE) == 0) { + wd179x_info->fdc_head = 1; + } else { + wd179x_info->fdc_head = 0; + } + } } else if (port == 0x3) { /* Interrupt Address */ + TRACE_PRINT(IRQ_MSG, + ("CROMFDC: " ADDRESS_FORMAT " IRQ Mask=0x%02x" NLP, PCX, data)); + cromfdc_info->imask = data; } else { } @@ -1495,12 +1731,20 @@ static int32 cromfdc_ext(const int32 port, const int32 io, const int32 data) result = dipswitch & 0x1F; result |= 0x00; /* Bit 6 is Seek in Progress for Persci drives. */ result |= (cromfdc_info->rtc & 1) ? 0x80 : 0; + if(crofdc_type == 50) { + TRACE_PRINT(STATUS_MSG, + ("CCS2422FDC: " ADDRESS_FORMAT " Read STATUS2=0x%02x" NLP, PCX, result)); + } } else if (port == 0x3) { /* Interrupt Address */ - result = 0xD7; /* end of job */ + result = ipend_to_rst_opcode(cromfdc_info->ipend); + if(result != 0) { + TRACE_PRINT(IRQ_MSG, + ("CROMFDC: " ADDRESS_FORMAT " RST Opcode=%x, Vector=%04x" NLP, PCX, result, RST_OPCODE_TO_VECTOR(result))); + } } else { result = 0xFF; } - TRACE_PRINT(VERBOSE_MSG, + TRACE_PRINT(STATUS_MSG, ("CROMFDC: " ADDRESS_FORMAT " AUX IN, Port 0x%02x Result 0x%02x" NLP, PCX, port, result)) } return result; @@ -1512,12 +1756,13 @@ static int32 cromfdc_timer(const int32 port, const int32 io, const int32 data) static int32 result = 0; if(io) { TRACE_PRINT(VERBOSE_MSG, - ("CROMFDC: " ADDRESS_FORMAT " TIMER OUT, Port 0x%02x Data 0x%02x" NLP, PCX, port, data)) + ("CROMFDC: " ADDRESS_FORMAT " TIMER%d OUT, Port 0x%02x Data 0x%02x" NLP, PCX, (port-4), port, data)) result = 0; + sim_activate(cromfdc_unit, (CROMFDC_SIM_64US * data)); } else { result++; TRACE_PRINT(VERBOSE_MSG, - ("CROMFDC: " ADDRESS_FORMAT " TIMER IN, Port 0x%02x Result 0x%02x" NLP, PCX, port, result)) + ("CROMFDC: " ADDRESS_FORMAT " TIMER%d IN, Port 0x%02x Result 0x%02x" NLP, PCX, (port-4), port, result)) } return result; } @@ -1539,3 +1784,16 @@ static int32 cromfdc_banksel(const int32 port, const int32 io, const int32 data) } return result; } + +static uint8 ccs2810_uart_status_reg = 0x00; + +/* CCS 2810 UART Status Register, needed by MOSS 2.2 Monitor */ +static int32 ccs2810_uart_status(const int32 port, const int32 io, const int32 data) +{ + if(io) { /* I/O Write */ + return (0x00); + } else { /* I/O Read */ + ccs2810_uart_status_reg = ~ccs2810_uart_status_reg; + return (ccs2810_uart_status_reg); + } +} diff --git a/AltairZ80/s100_adcs6.c b/AltairZ80/s100_adcs6.c new file mode 100644 index 00000000..7c6b14bd --- /dev/null +++ b/AltairZ80/s100_adcs6.c @@ -0,0 +1,716 @@ +/************************************************************************* + * * + * $Id: s100_adcs6.c 1970 2008-06-26 06:01:27Z hharte $ * + * * + * Copyright (c) 2007-2008 Howard M. Harte. * + * http://www.hartetec.com * + * * + * Permission is hereby granted, free of charge, to any person obtaining * + * a copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to * + * the following conditions: * + * * + * The above copyright notice and this permission notice shall be * + * included in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * + * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE 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 Howard M. Harte shall * + * not be used in advertising or otherwise to promote the sale, use or * + * other dealings in this Software without prior written authorization * + * Howard M. Harte. * + * * + * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * + * * + * Module Description: * + * Advanced Digital Corporation (ADC) Super-Six CPU Board * + * module for SIMH. * + * * + * This module is a wrapper around the wd179x FDC module, and adds the * + * ADC-specific registers as well as the Digitex Monitor Boot ROM. * + * * + * Environment: * + * User mode only * + * * + *************************************************************************/ + +/*#define DBG_MSG */ +#define DBG_MSG +#include "altairz80_defs.h" + +#if defined (_WIN32) +#include +#endif + +#include "sim_defs.h" /* simulator definitions */ +#include "wd179x.h" + +#ifdef DBG_MSG +#define DBG_PRINT(args) printf args +#else +#define DBG_PRINT(args) +#endif + +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define DRIVE_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) +#define IRQ_MSG (1 << 8) +#define DMA_MSG (1 << 9) + +#define ADCS6_MAX_DRIVES 4 +#define ADCS6_ROM_SIZE (2 * 1024) +#define ADCS6_ADDR_MASK (ADCS6_ROM_SIZE - 1) + +typedef struct { + PNP_INFO pnp; /* Plug and Play */ + uint32 dma_addr; /* DMA Transfer Address */ + uint8 rom_disabled; /* TRUE if ROM has been disabled */ + uint8 head_sel; + uint8 autowait; + uint8 rtc; + uint8 imask; /* Interrupt Mask Register */ + uint8 ipend; /* Interrupt Pending Register */ + uint8 s100_addr_u; /* A23:16 of S-100 bus */ +} ADCS6_INFO; + +extern WD179X_INFO_PUB *wd179x_info; + +static ADCS6_INFO adcs6_info_data = { { 0xF000, ADCS6_ROM_SIZE, 0x3, 2 } }; +static ADCS6_INFO *adcs6_info = &adcs6_info_data; + +extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); +extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); + +static t_stat adcs6_svc (UNIT *uptr); + +extern REG *sim_PC; +extern uint32 PCX; /* external view of PC */ + +#define UNIT_V_ADCS6_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_ADCS6_WLK (1 << UNIT_V_ADCS6_WLK) +#define UNIT_V_ADCS6_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_ADCS6_VERBOSE (1 << UNIT_V_ADCS6_VERBOSE) +#define UNIT_V_ADCS6_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ +#define UNIT_ADCS6_ROM (1 << UNIT_V_ADCS6_ROM) +#define ADCS6_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ + +#define MOTOR_TO_LIMIT 128 + +static t_stat adcs6_reset(DEVICE *adcs6_dev); +static t_stat adcs6_boot(int32 unitno, DEVICE *dptr); +static t_stat adcs6_attach(UNIT *uptr, char *cptr); +static t_stat adcs6_detach(UNIT *uptr); + +static int32 adcs6_dma(const int32 port, const int32 io, const int32 data); +static int32 adcs6_timer(const int32 port, const int32 io, const int32 data); +static int32 adcs6_control(const int32 port, const int32 io, const int32 data); +static int32 adcs6_banksel(const int32 port, const int32 io, const int32 data); +static int32 adcs6rom(const int32 port, const int32 io, const int32 data); + +static int32 dipswitch = 0x00; /* 5-position DIP switch on 64FDC card */ + +/* Disk Control/Flags Register, 0x34 (IN) */ +#define ADCS6_FLAG_DRQ (1 << 7) /* DRQ (All controllers) */ +#define ADCS6_FLAG_BOOT (1 << 6) /* boot# jumper (active low) (All controllers) */ +#define ADCS6_FLAG_SEL_REQ (1 << 5) /* Head Load (4FDC, 16FDC) / Select Request (64FDC) */ +#define ADCS6_FLAG_INH_INIT (1 << 4) /* Unassigned (4FDC) / Inhibit_Init# (16FDC, 64FDC) */ +#define ADCS6_FLAG_MTRON (1 << 3) /* Unassigned (4FDC) / Motor On (16FDC, 64FDC) */ +#define ADCS6_FLAG_MTO (1 << 2) /* Unassigned (4FDC) / Motor Timeout (16FDC, 64FDC) */ +#define ADCS6_FLAG_ATO (1 << 1) /* Unassigned (4FDC) / Autowait Timeout (16FDC, 64FDC) */ +#define ADCS6_FLAG_EOJ (1 << 0) /* End of Job (INTRQ) (All Controllers) (16FDC, 64FDC) */ + +/* Disk Control/Flags Register, 0x34 (OUT) */ +#define ADCS6_CTRL_AUTOWAIT (1 << 7) /* Auto Wait Enable (All controllers) */ +#define ADCS6_CTRL_DDENS (1 << 3) /* Unassigned (4FDC) / Double Density (16FDC, 64FDC) */ +#define ADCS6_CTRL_HDS (1 << 2) /* Motor On (All controllers) */ +#define ADCS6_CTRL_MINI (1 << 4) /* Mini (5.25") (All controllers) */ + +/* 64FDC Auxiliary Disk Command, 0x04 (OUT) */ +#define ADCS6_AUX_RESERVED0 (1 << 0) /* Unused (All Controllers) */ +#define ADCS6_AUX_CMD_SIDE (1 << 1) /* 16FDC, 64FDC: Side Select* Low=Side 1, High=Side 0. */ +#define ADCS6_AUX_CTRL_OUT (1 << 2) /* Control Out* (All Controllers) */ +#define ADCS6_AUX_RESTORE (1 << 3) /* 4FDC, 16FDC Restore* / 64FDC Unused */ +#define ADCS6_AUX_FAST_SEEK (1 << 4) /* 4FDC, 16FDC Fast Seek* / 64FDC Unused */ +#define ADCS6_AUX_SEL_OVERRIDE (1 << 5) /* 4FDC Eject Right* / 16FDC, 64FDC Drive Select Override */ +#define ADCS6_AUX_EJECT (1 << 6) /* 4FDC Eject Left* / 16FDC Eject*, 64FDC Unused */ +#define ADCS6_AUX_RESERVED7 (1 << 7) /* Unused (All Controllers) */ + +/* 64FDC Interrupt Mask Register, 0x03 (OUT) */ +#define ADCS6_IRQ_TIMER1 (1 << 0) /* Timer1 Interrupt Mask */ +#define ADCS6_IRQ_TIMER2 (1 << 1) /* Timer2 Interrupt Mask */ +#define ADCS6_IRQ_EOJ (1 << 2) /* End of Job Interrupt Mask */ +#define ADCS6_IRQ_TIMER3 (1 << 3) /* Timer3 Interrupt Mask */ +#define ADCS6_IRQ_RDA (1 << 4) /* Read Data Available Interrupt Mask */ +#define ADCS6_IRQ_TBE (1 << 5) /* Transmit Buffer Empty Interrupt Mask */ +#define ADCS6_IRQ_TIMER4 (1 << 6) /* Timer4 Interrupt Mask */ +#define ADCS6_IRQ_TIMER5 (1 << 7) /* Timer5 Interrupt Mask */ + +#define ADCS6_TIMER1_RST 0xC7 /* RST0 - 0xC7 */ +#define ADCS6_TIMER2_RST 0xCF /* RST8 - 0xCF */ +#define ADCS6_EOJ_RST 0xD7 /* RST10 - 0xD7 */ +#define ADCS6_TIMER3_RST 0xDF /* RST18 - 0xDF */ +#define ADCS6_RDA_RST 0xE7 /* RST20 - 0xE7 */ +#define ADCS6_TBE_RST 0xEF /* RST28 - 0xEF */ +#define ADCS6_TIMER4_RST 0xF7 /* RST30 - 0xF7 */ +#define ADCS6_TIMER5_RST 0xFF /* RST38 - 0xFF */ + +#define RST_OPCODE_TO_VECTOR(x) (x & 0x38) + +/* The ADCS6 does not really have RAM associated with it, but for ease of integration with the + * SIMH/AltairZ80 Resource Mapping Scheme, rather than Map and Unmap the ROM, simply implement our + * own RAM that can be swapped in when the ADCS6 Boot ROM is disabled. + */ +static uint8 adcs6ram[ADCS6_ROM_SIZE]; + +static UNIT adcs6_unit[] = { + { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE + UNIT_ADCS6_ROM, ADCS6_CAPACITY), 1024 }, + { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, ADCS6_CAPACITY) }, + { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, ADCS6_CAPACITY) }, + { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, ADCS6_CAPACITY) } +}; + +static REG adcs6_reg[] = { + { HRDATA (J7, dipswitch, 8), }, + { NULL } +}; + +static MTAB adcs6_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { UNIT_ADCS6_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_ADCS6_WLK, UNIT_ADCS6_WLK, "WRTLCK", "WRTLCK", NULL }, + /* quiet, no warning messages */ + { UNIT_ADCS6_VERBOSE, 0, "QUIET", "QUIET", NULL }, + /* verbose, show warning messages */ + { UNIT_ADCS6_VERBOSE, UNIT_ADCS6_VERBOSE, "VERBOSE", "VERBOSE", NULL }, + { UNIT_ADCS6_ROM, 0, "NOROM", "NOROM", NULL }, + { UNIT_ADCS6_ROM, UNIT_ADCS6_ROM, "ROM", "ROM", NULL }, + { 0 } +}; + +#define TRACE_PRINT(level, args) if(adcs6_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB adcs6_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "DRIVE", DRIVE_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "IRQ", IRQ_MSG }, + { "DMA", DMA_MSG }, + { NULL, 0 } +}; + +DEVICE adcs6_dev = { + "ADCS6", adcs6_unit, adcs6_reg, adcs6_mod, + ADCS6_MAX_DRIVES, 10, 31, 1, ADCS6_MAX_DRIVES, ADCS6_MAX_DRIVES, + NULL, NULL, &adcs6_reset, + &adcs6_boot, &adcs6_attach, &adcs6_detach, + &adcs6_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + adcs6_dt, NULL, "ADC Super-Six ADCS6" +}; + +/* This is the DIGITEX Monitor version 1.2.A -- 10/06/83 + * + * MONITOR COMMANDS : + * B = LOAD DISK BOOT LOADER + * DSSSS,QQQQ = DUMP MEMORY IN HEX FROM S TO Q + * FSSSS,QQQQ,BB = FILL MEMORY FROM S TO Q WITH B + * GAAAA = GO TO ADDRESS A + * IPP = INPUT FROM PORT P + * LAAAA = LOAD MEMORY STARTING AT A + * MSSSS,QQQQ,DDDD = MOVE STARTING AT S TO Q TO ADDR. D + * OPP,DD = OUTPUT DATA D TO PORT P + * ESC WILL TERMINATE ANY COMMAND + */ +static uint8 adcs6_rom[ADCS6_ROM_SIZE] = { + 0xC3, 0x3C, 0xF0, 0xC3, 0xA4, 0xF0, 0xC3, 0xB6, 0xF0, 0xC3, 0xAF, 0xF0, 0xC3, 0xC9, 0xF0, 0xC3, + 0xE1, 0xF0, 0xC3, 0xF0, 0xF0, 0xC3, 0x06, 0xF1, 0xC3, 0x14, 0xF1, 0xC3, 0x0B, 0xF1, 0xC3, 0x22, + 0xF1, 0xC3, 0x2D, 0xF1, 0xC3, 0x4A, 0xF1, 0xC3, 0x77, 0xF1, 0xC3, 0xA1, 0xF1, 0xC3, 0xFA, 0xF1, + 0xC3, 0xBC, 0xF3, 0xC3, 0x53, 0xF3, 0xC3, 0x8E, 0xF2, 0xC3, 0xA0, 0xF2, 0xDB, 0x15, 0xD3, 0x18, + 0xCB, 0x77, 0x28, 0x10, 0xAF, 0xD3, 0x15, 0xD3, 0x40, 0xD3, 0x17, 0x3E, 0x40, 0xD3, 0x16, 0x21, + 0x3E, 0x60, 0x18, 0x0A, 0xAF, 0xD3, 0x17, 0x3E, 0x4F, 0xD3, 0x16, 0x21, 0x3E, 0x6F, 0x22, 0x04, + 0xEE, 0xAF, 0x32, 0x01, 0xEE, 0x31, 0x64, 0xEE, 0x21, 0xCA, 0xF3, 0x01, 0x01, 0x08, 0xED, 0xB3, + 0x21, 0xD2, 0xF3, 0xCD, 0xE1, 0xF0, 0xC3, 0xB2, 0xF2, 0x31, 0x64, 0xEE, 0x21, 0x4D, 0xF4, 0xCD, + 0xE1, 0xF0, 0xCD, 0xC9, 0xF0, 0x47, 0x21, 0xAF, 0xF6, 0x7E, 0xFE, 0xFF, 0x28, 0x08, 0xB8, 0x28, + 0x0D, 0x23, 0x23, 0x23, 0x18, 0xF3, 0x21, 0x52, 0xF4, 0xCD, 0xE1, 0xF0, 0x18, 0xDB, 0x23, 0x5E, + 0x23, 0x56, 0xEB, 0xE9, 0xF5, 0xDB, 0x01, 0xE6, 0x04, 0x28, 0xFA, 0xF1, 0xD3, 0x00, 0xC9, 0xDB, + 0x01, 0xE6, 0x01, 0xC8, 0x18, 0x06, 0xDB, 0x01, 0xE6, 0x01, 0x28, 0xFA, 0xDB, 0x00, 0xE6, 0x7F, + 0xFE, 0x61, 0xD8, 0xFE, 0x7B, 0xD0, 0xE6, 0x5F, 0xC9, 0x3E, 0xFF, 0x32, 0x00, 0xEE, 0xCD, 0xB6, + 0xF0, 0xF5, 0x3A, 0x00, 0xEE, 0xA7, 0x20, 0x02, 0xF1, 0xC9, 0xF1, 0xFE, 0x20, 0xD4, 0xA4, 0xF0, + 0xC9, 0xF5, 0xE5, 0x7E, 0xB7, 0x28, 0x06, 0xCD, 0xA4, 0xF0, 0x23, 0x18, 0xF6, 0xE1, 0xF1, 0xC9, + 0xE5, 0x21, 0x14, 0xF5, 0xCD, 0xE1, 0xF0, 0xE1, 0xC9, 0xCD, 0xAF, 0xF0, 0xFE, 0x1B, 0xCA, 0x79, + 0xF0, 0xFE, 0x08, 0xD0, 0x18, 0xF3, 0xF5, 0x3E, 0x20, 0x18, 0x12, 0xF5, 0x0F, 0x0F, 0x0F, 0x0F, + 0xCD, 0x14, 0xF1, 0xF1, 0xF5, 0xE6, 0x0F, 0xC6, 0x90, 0x27, 0xCE, 0x40, 0x27, 0xCD, 0xA4, 0xF0, + 0xF1, 0xC9, 0xF5, 0x7C, 0xCD, 0x0B, 0xF1, 0x7D, 0xCD, 0x0B, 0xF1, 0xF1, 0xC9, 0xCD, 0xC9, 0xF0, + 0xFE, 0x2C, 0xC8, 0xFE, 0x20, 0xC8, 0xFE, 0x30, 0xD8, 0xFE, 0x3A, 0xDA, 0x47, 0xF1, 0xFE, 0x41, + 0xD8, 0xFE, 0x47, 0x3F, 0xD8, 0xD6, 0x07, 0xD6, 0x30, 0xC9, 0xC5, 0xD5, 0x0E, 0x00, 0x1E, 0x00, + 0xCD, 0x2D, 0xF1, 0x30, 0x0E, 0xFE, 0x0D, 0x37, 0x20, 0x1A, 0x7B, 0xB7, 0x20, 0x15, 0x37, 0x3E, + 0x0D, 0x18, 0x11, 0xFE, 0x10, 0x30, 0x0C, 0x1C, 0x47, 0x79, 0x87, 0x87, 0x87, 0x87, 0x80, 0x4F, + 0xC3, 0x50, 0xF1, 0x79, 0xD1, 0xC1, 0xC9, 0xD5, 0x21, 0x00, 0x00, 0x37, 0x3F, 0xF5, 0xCD, 0x2D, + 0xF1, 0x30, 0x0D, 0xFE, 0x0D, 0x20, 0x05, 0xCD, 0x06, 0xF1, 0x18, 0x12, 0xF1, 0x37, 0xD1, 0xC9, + 0xFE, 0x10, 0x30, 0x0A, 0x29, 0x29, 0x29, 0x29, 0x5F, 0x16, 0x00, 0x19, 0x18, 0xE0, 0xF1, 0xD1, + 0xC9, 0x77, 0xBE, 0xC8, 0xE5, 0x21, 0x63, 0xF4, 0xCD, 0xE1, 0xF0, 0xE1, 0xCD, 0x22, 0xF1, 0xC3, + 0x79, 0xF0, 0xCD, 0x77, 0xF1, 0xD2, 0xBE, 0xF1, 0x21, 0x5D, 0xF4, 0xC3, 0x99, 0xF0, 0x22, 0x02, + 0xEE, 0xCD, 0xF0, 0xF0, 0x2A, 0x02, 0xEE, 0xCD, 0x22, 0xF1, 0xCD, 0x06, 0xF1, 0x7E, 0xCD, 0x0B, + 0xF1, 0xCD, 0x06, 0xF1, 0xCD, 0x4A, 0xF1, 0xDA, 0xE4, 0xF1, 0xCD, 0xA1, 0xF1, 0x2A, 0x02, 0xEE, + 0x23, 0xC3, 0xBE, 0xF1, 0xFE, 0x0D, 0xCA, 0x79, 0xF0, 0xFE, 0x20, 0xCA, 0xDD, 0xF1, 0xFE, 0x2D, + 0xC2, 0xB8, 0xF1, 0x2A, 0x02, 0xEE, 0x2B, 0xC3, 0xBE, 0xF1, 0xF5, 0x7A, 0x2F, 0x57, 0x7B, 0x2F, + 0x5F, 0x13, 0xF1, 0xC9, 0xCD, 0x7E, 0xF2, 0xCD, 0x7E, 0xF2, 0xCD, 0xFA, 0xF1, 0xCD, 0xF0, 0xF0, + 0xCD, 0x22, 0xF1, 0xCD, 0x06, 0xF1, 0xCD, 0x06, 0xF1, 0x7E, 0xCD, 0x0B, 0xF1, 0xCD, 0x3F, 0xF2, + 0xCD, 0x86, 0xF2, 0xFE, 0x13, 0xCC, 0xF9, 0xF0, 0x7D, 0xE6, 0x0F, 0xCA, 0x0D, 0xF2, 0xC3, 0x16, + 0xF2, 0xCD, 0x7E, 0xF2, 0xEB, 0xE9, 0x21, 0x17, 0xF5, 0xCD, 0xE1, 0xF0, 0xC3, 0x79, 0xF0, 0xE5, + 0x19, 0xDA, 0x79, 0xF0, 0xE1, 0x23, 0xC9, 0xCD, 0x7E, 0xF2, 0xD5, 0xCD, 0x7E, 0xF2, 0xCD, 0x7E, + 0xF2, 0xEB, 0xE3, 0x8D, 0xFA, 0xF1, 0x7E, 0xE3, 0xCD, 0xA1, 0xF1, 0x23, 0xE3, 0xCD, 0x3F, 0xF2, + 0xCD, 0x86, 0xF2, 0xC3, 0x56, 0xF2, 0xCD, 0x7E, 0xF2, 0xCD, 0x7E, 0xF2, 0xCD, 0xFA, 0xF1, 0xCD, + 0x4A, 0xF1, 0xDA, 0xB8, 0xF1, 0xCD, 0xA1, 0xF1, 0xCD, 0x3F, 0xF2, 0xC3, 0x75, 0xF2, 0xCD, 0x77, + 0xF1, 0xDA, 0xB8, 0xF1, 0xEB, 0xC9, 0xCD, 0xAF, 0xF0, 0xB7, 0xC2, 0x79, 0xF0, 0xC9, 0xCD, 0x4A, + 0xF1, 0xDA, 0xB8, 0xF1, 0x4F, 0xED, 0x78, 0xCD, 0xF0, 0xF0, 0xCD, 0x0B, 0xF1, 0xC3, 0x79, 0xF0, + 0xCD, 0x4A, 0xF1, 0xDA, 0xB8, 0xF1, 0x4F, 0xCD, 0x4A, 0xF1, 0xDA, 0xB8, 0xF1, 0xED, 0x79, 0xC3, + 0x79, 0xF0, 0xCD, 0x86, 0xF2, 0xCD, 0xC6, 0xF2, 0xCD, 0x6F, 0xF3, 0xCD, 0x86, 0xF2, 0xCD, 0xE8, + 0xF2, 0xCD, 0x8F, 0xF3, 0x18, 0xF5, 0xDB, 0x15, 0x47, 0x3E, 0x18, 0xCB, 0x60, 0x20, 0x01, 0xAF, + 0x32, 0x06, 0xEE, 0xD3, 0x14, 0x3E, 0x0B, 0xD3, 0x0C, 0x00, 0xDB, 0x14, 0xDB, 0x0C, 0xE6, 0x80, + 0xC8, 0xAF, 0x32, 0x06, 0xEE, 0xD3, 0x14, 0xC9, 0xDB, 0x0C, 0x17, 0xD8, 0x21, 0xE8, 0x03, 0xDB, + 0x0C, 0xE6, 0x02, 0x28, 0x06, 0x2B, 0x7D, 0xB4, 0x20, 0xF5, 0xC9, 0x06, 0x0A, 0x21, 0x80, 0x3E, + 0xDB, 0x0C, 0xE6, 0x02, 0x20, 0x08, 0x2B, 0x7D, 0xB4, 0x20, 0xF5, 0x10, 0xF0, 0xC9, 0x3E, 0xFF, + 0x32, 0x01, 0xEE, 0x3E, 0x01, 0x21, 0x00, 0xC0, 0x32, 0x08, 0xEE, 0xD3, 0x0E, 0x3E, 0x8C, 0xD3, + 0x0C, 0x00, 0xDB, 0x14, 0xB7, 0xF2, 0x2E, 0xF3, 0xDB, 0x0F, 0x77, 0x23, 0x18, 0xF4, 0xDB, 0x0C, + 0xB7, 0x20, 0x19, 0x3A, 0x08, 0xEE, 0x3C, 0xFE, 0x04, 0x20, 0xDD, 0x2A, 0x04, 0xEE, 0x22, 0xFC, + 0xBF, 0x2A, 0x4A, 0xF3, 0x22, 0xFE, 0xBF, 0xC3, 0xFC, 0xBF, 0xD3, 0x16, 0xF5, 0x3A, 0x01, 0xEE, + 0xB7, 0x28, 0x0D, 0x21, 0xB8, 0xF4, 0xCD, 0xE1, 0xF0, 0xF1, 0xCD, 0x0B, 0xF1, 0xC3, 0x79, 0xF0, + 0xF1, 0x21, 0xD4, 0xF4, 0xCD, 0xE1, 0xF0, 0x3E, 0xFF, 0x32, 0x01, 0xEE, 0xC3, 0x79, 0xF0, 0xAF, + 0xD3, 0xE6, 0x3E, 0x08, 0xD3, 0xE6, 0x3E, 0x10, 0xD3, 0xE6, 0x3E, 0x18, 0xD3, 0xE6, 0xAF, 0xD3, + 0xE6, 0xD3, 0xE3, 0xD3, 0xE4, 0xD3, 0xE5, 0x3C, 0xD3, 0xE2, 0x3E, 0x70, 0xD3, 0xE7, 0xC9, 0xDB, + 0xE7, 0xE6, 0x50, 0xFE, 0x50, 0xC0, 0xDB, 0xE7, 0xB7, 0xF8, 0xAF, 0xD3, 0xE6, 0x3E, 0x20, 0xD3, + 0xE7, 0xDB, 0xE7, 0xB7, 0xFA, 0xA1, 0xF3, 0xE6, 0x01, 0x20, 0x11, 0x21, 0x00, 0x80, 0x01, 0xE0, + 0x00, 0xED, 0xB2, 0x2A, 0x04, 0xEE, 0x22, 0x00, 0x80, 0xC3, 0x00, 0x80, 0x21, 0xF4, 0xF4, 0xCD, + 0xE1, 0xF0, 0xDB, 0xE1, 0xCD, 0x0B, 0xF1, 0xC3, 0x79, 0xF0, 0x18, 0x04, 0x44, 0x03, 0xC1, 0x05, + 0xEA, 0x00, 0x0D, 0x0A, 0x0A, 0x0A, 0x44, 0x49, 0x47, 0x49, 0x54, 0x45, 0x58, 0x20, 0x4D, 0x6F, + 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x31, 0x2E, + 0x32, 0x2E, 0x41, 0x20, 0x2D, 0x2D, 0x20, 0x31, 0x30, 0x2F, 0x30, 0x36, 0x2F, 0x38, 0x33, 0x0D, + 0x0A, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x22, 0x48, 0x22, 0x20, 0x66, 0x6F, 0x72, 0x20, + 0x48, 0x65, 0x6C, 0x70, 0x0D, 0x0A, 0x0A, 0x41, 0x74, 0x74, 0x65, 0x6D, 0x70, 0x74, 0x69, 0x6E, + 0x67, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x2E, 0x2E, 0x2E, 0x0D, 0x0A, 0x50, 0x72, + 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x61, + 0x62, 0x6F, 0x72, 0x74, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x2E, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x20, + 0x3E, 0x00, 0x20, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x49, 0x4E, 0x45, 0x44, 0x00, 0x20, 0x3F, 0x3F, + 0x3F, 0x3F, 0x00, 0x0D, 0x0D, 0x0A, 0x4D, 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x20, 0x57, 0x52, 0x49, + 0x54, 0x45, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x20, 0x41, 0x54, 0x20, 0x00, 0x45, 0x52, 0x52, + 0x4F, 0x52, 0x00, 0x20, 0x50, 0x41, 0x55, 0x53, 0x45, 0x00, 0x3F, 0x20, 0x00, 0x20, 0x41, 0x42, + 0x4F, 0x52, 0x54, 0x45, 0x44, 0x00, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x41, + 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x3A, 0x00, 0x45, 0x4E, 0x44, 0x49, 0x4E, 0x47, 0x20, 0x41, + 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x3A, 0x00, 0x0D, 0x0A, 0x46, 0x44, 0x43, 0x20, 0x43, 0x4F, + 0x4C, 0x44, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x20, 0x43, 0x4F, + 0x44, 0x45, 0x20, 0x00, 0x0D, 0x0A, 0x49, 0x4E, 0x53, 0x45, 0x52, 0x54, 0x20, 0x44, 0x49, 0x53, + 0x4B, 0x20, 0x26, 0x20, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x42, 0x20, 0x54, 0x4F, 0x20, 0x42, + 0x4F, 0x4F, 0x54, 0x00, 0x0D, 0x0A, 0x48, 0x44, 0x43, 0x31, 0x30, 0x30, 0x31, 0x20, 0x43, 0x4F, + 0x4C, 0x44, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x20, 0x43, 0x4F, + 0x44, 0x45, 0x20, 0x00, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x4D, 0x4F, 0x4E, 0x49, 0x54, 0x4F, 0x52, + 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44, 0x53, 0x20, 0x3A, 0x0D, 0x0A, 0xC2, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xBD, 0x20, 0x4C, + 0x4F, 0x41, 0x44, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x4C, 0x4F, + 0x41, 0x44, 0x45, 0x52, 0x0D, 0x0A, 0x44, 0x53, 0x53, 0x53, 0x53, 0x2C, 0x51, 0x51, 0x51, 0x51, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x44, 0x55, 0x4D, 0x50, 0x20, 0x4D, 0x45, 0x4D, + 0x4F, 0x52, 0x59, 0x20, 0x49, 0x4E, 0x20, 0x48, 0x45, 0x58, 0x20, 0x46, 0x52, 0x4F, 0x4D, 0x20, + 0x53, 0x20, 0x54, 0x4F, 0x20, 0x51, 0x0D, 0x0A, 0x46, 0x53, 0x53, 0x53, 0x53, 0x2C, 0x51, 0x51, + 0x51, 0x51, 0x2C, 0x42, 0x42, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x46, 0x49, 0x4C, 0x4C, 0x20, 0x4D, + 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x20, 0x46, 0x52, 0x4F, 0x4D, 0x20, 0x53, 0x20, 0x54, 0x4F, 0x20, + 0x51, 0x20, 0x57, 0x49, 0x54, 0x48, 0x20, 0x42, 0x0D, 0x0A, 0x47, 0x41, 0x41, 0x41, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x47, 0x4F, 0x20, 0x54, + 0x4F, 0x20, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x20, 0x41, 0x0D, 0x0A, 0x49, 0x50, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x49, + 0x4E, 0x50, 0x55, 0x54, 0x20, 0x46, 0x52, 0x4F, 0x4D, 0x20, 0x50, 0x4F, 0x52, 0x54, 0x20, 0x50, + 0x0D, 0x0A, 0x4C, 0x41, 0x41, 0x41, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x3D, 0x20, 0x4C, 0x4F, 0x41, 0x44, 0x20, 0x4D, 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x20, + 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x41, 0x54, 0x20, 0x41, 0x0D, 0x0A, 0x4D, + 0x53, 0x53, 0x53, 0x53, 0x2C, 0x51, 0x51, 0x51, 0x51, 0x2C, 0x44, 0x44, 0x44, 0x44, 0x20, 0x3D, + 0x20, 0x4D, 0x4F, 0x56, 0x45, 0x20, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x41, + 0x54, 0x20, 0x53, 0x20, 0x54, 0x4F, 0x20, 0x51, 0x20, 0x54, 0x4F, 0x20, 0x41, 0x44, 0x44, 0x52, + 0x2E, 0x20, 0x44, 0x0D, 0x0A, 0x4F, 0x50, 0x50, 0x2C, 0x44, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x4F, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20, 0x44, 0x41, + 0x54, 0x41, 0x20, 0x44, 0x20, 0x54, 0x4F, 0x20, 0x50, 0x4F, 0x52, 0x54, 0x20, 0x50, 0x0D, 0x0A, + 0x45, 0x53, 0x43, 0x20, 0x57, 0x49, 0x4C, 0x4C, 0x20, 0x54, 0x45, 0x52, 0x4D, 0x49, 0x4E, 0x41, + 0x54, 0x45, 0x20, 0x41, 0x4E, 0x59, 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44, 0x00, 0x4C, + 0xB2, 0xF1, 0x0D, 0x79, 0xF0, 0x2E, 0xC1, 0xF1, 0x2D, 0xF3, 0xF1, 0x44, 0x04, 0xF2, 0x49, 0x8E, + 0xF2, 0x4F, 0xA0, 0xF2, 0x46, 0x66, 0xF2, 0x47, 0x31, 0xF2, 0x4D, 0x47, 0xF2, 0x48, 0x36, 0xF2, + 0x42, 0xB2, 0xF2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x01, 0x00, 0x04, 0x00, 0x07, 0x00, 0x0A, 0x00, 0x0D, 0x00, 0x10, 0x00, 0x13, 0x00, 0x16, + 0x00, 0x19, 0x00, 0x1C, 0x00, 0x1F, 0x00, 0x22, 0x00, 0x25, 0x00, 0x28, 0x00, 0x2B, 0x00, 0x2E, + 0x00, 0x31, 0x00, 0x34, 0x00, 0x37, 0x00, 0x3A, 0x00, 0x69, 0x00, 0x71, 0x00, 0x74, 0x00, 0x77, + 0x00, 0x7D, 0x00, 0x80, 0x00, 0x83, 0x00, 0x87, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xCF, 0x00, 0xDE, + 0x00, 0xE8, 0x00, 0xF2, 0x00, 0xF5, 0x00, 0xFA, 0x00, 0xFF, 0x00, 0x11, 0x01, 0x1E, 0x01, 0x25, + 0x01, 0x29, 0x01, 0x2E, 0x01, 0x3C, 0x01, 0x51, 0x01, 0x71, 0x01, 0x7F, 0x01, 0x88, 0x01, 0xA6, + 0x01, 0xA9, 0x01, 0xAD, 0x01, 0xB0, 0x01, 0xB3, 0x01, 0xB6, 0x01, 0xB9, 0x01, 0xBC, 0x01, 0xC2, + 0x01, 0xC8, 0x01, 0xCB, 0x01, 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01, 0xDB, 0x01, 0xE2, + 0x01, 0xE7, 0x01, 0xEC, 0x01, 0xF1, 0x01, 0xF8, 0x01, 0x05, 0x02, 0x08, 0x02, 0x0B, 0x02, 0x0E, + 0x02, 0x11, 0x02, 0x14, 0x02, 0x17, 0x02, 0x1B, 0x02, 0x1E, 0x02, 0x21, 0x02, 0x26, 0x02, 0x2C, + 0x02, 0x2F, 0x02, 0x32, 0x02, 0x37, 0x02, 0x3A, 0x02, 0x3D, 0x02, 0x42, 0x02, 0x48, 0x02, 0x4C, + 0x02, 0x4F, 0x02, 0x54, 0x02, 0x59, 0x02, 0x5E, 0x02, 0x61, 0x02, 0x64, 0x02, 0x67, 0x02, 0x6A, + 0x02, 0x6D, 0x02, 0x70, 0x02, 0x73, 0x02, 0x76, 0x02, 0x79, 0x02, 0x7C, 0x02, 0x7F, 0x02, 0x82, + 0x02, 0x87, 0x02, 0x8B, 0x02, 0x8F, 0x02, 0x92, 0x02, 0x98, 0x02, 0x9B, 0x02, 0x9E, 0x02, 0xA1, + 0x02, 0xA4, 0x02, 0xA8, 0x02, 0xAB, 0x02, 0xB0, 0x02, 0xB3, 0x02, 0xB6, 0x02, 0xB9, 0x02, 0xBC, + 0x02, 0xBF, 0x02, 0xC2, 0x02, 0x26, 0x03, 0x42, 0x03, 0x54, 0x03, 0x57, 0x03, 0x5B, 0x03, 0x00 +}; + +/* returns TRUE iff there exists a disk with VERBOSE */ +static int32 adcs6_hasProperty(uint32 property) { + int32 i; + for (i = 0; i < ADCS6_MAX_DRIVES; i++) + if (adcs6_dev.units[i].flags & property) + return TRUE; + return FALSE; +} + +static uint8 motor_timeout = 0; + +/* Unit service routine */ +static t_stat adcs6_svc (UNIT *uptr) +{ + + if(adcs6_info->head_sel == 1) { + motor_timeout ++; + if(motor_timeout == MOTOR_TO_LIMIT) { + adcs6_info->head_sel = 0; + TRACE_PRINT(DRIVE_MSG, ("ADCS6: Motor OFF" NLP)) + } + } + + adcs6_info->rtc ++; + + printf("Timer IRQ\n"); + adcs6_info->ipend |= ADCS6_IRQ_TIMER3; + +/* sim_activate (adcs6_unit, adcs6_unit->wait); */ /* requeue! */ + + return SCPE_OK; +} + + +/* Reset routine */ +static t_stat adcs6_reset(DEVICE *dptr) +{ + PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; + + if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ + if (adcs6_hasProperty(UNIT_ADCS6_ROM)) { + sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &adcs6rom, TRUE); + } + /* Unmap I/O Ports (0x3-4,0x5-9,0x34,0x40 */ + sim_map_resource(0x10, 4, RESOURCE_TYPE_IO, &adcs6_dma, TRUE); + sim_map_resource(0x04, 8, RESOURCE_TYPE_IO, &adcs6_timer, TRUE); + sim_map_resource(0x14, 1, RESOURCE_TYPE_IO, &adcs6_control, TRUE); + sim_map_resource(0x15, 7, RESOURCE_TYPE_IO, &adcs6_banksel, TRUE); + } else { + /* Connect ADCS6 ROM at base address */ + if (adcs6_hasProperty(UNIT_ADCS6_ROM)) { + TRACE_PRINT(VERBOSE_MSG, ("ADCS6: ROM Enabled." NLP)) + if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &adcs6rom, FALSE) != 0) { + printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + adcs6_info->rom_disabled = FALSE; + } else { + TRACE_PRINT(VERBOSE_MSG, ("ADCS6: ROM Disabled." NLP)) + adcs6_info->rom_disabled = TRUE; + } + + /* Connect ADCS6 FDC Synchronization / Drive / Density Register */ + if(sim_map_resource(0x14, 0x01, RESOURCE_TYPE_IO, &adcs6_control, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } +/*#define ADCS6 */ +#ifdef ADCS6 + /* Connect ADCS6 Interrupt, and Aux Disk Registers */ + + if(sim_map_resource(0x10, 0x04, RESOURCE_TYPE_IO, &adcs6_dma, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + + /* Connect ADCS6 Timer Registers */ + if(sim_map_resource(0x04, 0x08, RESOURCE_TYPE_IO, &adcs6_timer, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } +#endif + /* Connect ADCS6 Memory Management / Bank Select Register */ + if(sim_map_resource(0x15, 0x7, RESOURCE_TYPE_IO, &adcs6_banksel, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + } + +/* sim_activate (adcs6_unit, adcs6_unit->wait); */ /* requeue! */ + return SCPE_OK; +} + +static t_stat adcs6_boot(int32 unitno, DEVICE *dptr) +{ + DBG_PRINT(("Booting ADCS6 Controller" NLP)); + + /* Re-enable the ROM in case it was disabled */ + adcs6_info->rom_disabled = FALSE; + + /* Set the PC to 0, and go. */ + *((int32 *) sim_PC->loc) = 0xF000; + return SCPE_OK; +} + +/* Attach routine */ +static t_stat adcs6_attach(UNIT *uptr, char *cptr) +{ + t_stat r; + r = wd179x_attach(uptr, cptr); + + return r; +} + +/* Detach routine */ +static t_stat adcs6_detach(UNIT *uptr) +{ + t_stat r; + + r = wd179x_detach(uptr); + + return r; +} + +static int32 adcs6rom(const int32 Addr, const int32 write, const int32 data) +{ +/* DBG_PRINT(("ADCS6: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ + if(write) { + if(adcs6_info->rom_disabled == FALSE) { + TRACE_PRINT(ERROR_MSG, + ("ADCS6: " ADDRESS_FORMAT " Cannot write to ROM." NLP, PCX)); + } else { + adcs6ram[Addr & ADCS6_ADDR_MASK] = data; + } + return 0; + } else { + if(adcs6_info->rom_disabled == FALSE) { + return(adcs6_rom[Addr & ADCS6_ADDR_MASK]); + } else { + return(adcs6ram[Addr & ADCS6_ADDR_MASK]); + } + } +} + +/* Disk Control/Flags Register, 0x14 */ +static int32 adcs6_control(const int32 port, const int32 io, const int32 data) +{ + int32 result = 0; + if(io) { /* I/O Write */ + wd179x_info->sel_drive = data & 0x03; + + if(data & ADCS6_CTRL_MINI) { + wd179x_info->drivetype = 5; + } else { + wd179x_info->drivetype = 8; + } + + if(data & ADCS6_CTRL_HDS) { + adcs6_info->head_sel = 1; + wd179x_info->fdc_head = 1; + } else { + adcs6_info->head_sel = 0; + wd179x_info->fdc_head = 0; + } + + if(data & ADCS6_CTRL_DDENS) { + wd179x_info->ddens = 1; + } else { + wd179x_info->ddens = 0; + } + if(data & ADCS6_CTRL_AUTOWAIT) { + adcs6_info->autowait = 1; + } else { + adcs6_info->autowait = 0; + } + + TRACE_PRINT(DRIVE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR CTRL: sel_drive=%d, drivetype=%d, head_sel=%d, dens=%d, aw=%d" NLP, PCX, + wd179x_info->sel_drive, wd179x_info->drivetype, adcs6_info->head_sel, wd179x_info->ddens, adcs6_info->autowait)); + } else { /* I/O Read */ + result = wd179x_info->drq ? 0xFF : 0; + if (wd179x_info->intrq) + result &= 0x7F; + +/* TRACE_PRINT(VERBOSE_MSG, */ +/* ("ADCS6: " ADDRESS_FORMAT " Read DISK FLAGS, Port 0x%02x Result 0x%02x" NLP, PCX, port, result)) */ + } + + return result; +} + +/* ADC Super Six DMA (Z80-DMA) */ +static int32 adcs6_dma(const int32 port, const int32 io, const int32 data) +{ + int32 result = 0xff; + if(io) { /* I/O Write */ + TRACE_PRINT(DMA_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR DMA: 0x%02x" NLP, PCX, data & 0xFF)); + } else { /* I/O Read */ + result = 0xFF; + TRACE_PRINT(DMA_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD DMA: 0x%02x" NLP, PCX, result)); + } + return result; +} + +/* ADC Super-Six PIO and CTC ports */ +static int32 adcs6_timer(const int32 port, const int32 io, const int32 data) +{ + static int32 result = 0xFF; + if(io) { /* Write */ + switch(port) { + case 0x04: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR PIOA DATA=0x%02x" NLP, PCX, data)); + break; + case 0x05: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR PIOB DATA=0x%02x" NLP, PCX, data)); + break; + case 0x06: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR PIOA CTRL=0x%02x" NLP, PCX, data)); + break; + case 0x07: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR PIOB CTRL=0x%02x" NLP, PCX, data)); + break; + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR CTC%d: 0x%02x" NLP, PCX, port - 8, data)); + break; + default: + TRACE_PRINT(ERROR_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR Unhandled Port: 0x%02x=0x%02x" NLP, PCX, port, data)); + break; + } + } else { /* Read */ + result = 0xFF; + switch(port) { + case 0x04: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD PIOA DATA=0x%02x" NLP, PCX, result)); + break; + case 0x05: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD PIOB DATA=0x%02x" NLP, PCX, result)); + break; + case 0x06: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD PIOA CTRL=0x%02x" NLP, PCX, result)); + break; + case 0x07: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD PIOB CTRL=0x%02x" NLP, PCX, result)); + break; + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD CTC%d: 0x%02x" NLP, PCX, port - 8, data)); + break; + default: + TRACE_PRINT(ERROR_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD Unhandled Port: 0x%02x=0x%02x" NLP, PCX, port, data)); + break; + } + } + return result; +} + +/* 64FDC Bank Select (Write Disables boot ROM) */ +static int32 adcs6_banksel(const int32 port, const int32 io, const int32 data) +{ + int32 result; + if(io) { /* Write */ + switch(port) { + case 0x15: + adcs6_info->s100_addr_u = data & 0xFF; + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR S100 A[23:16]=0x%02x" NLP, PCX, data)); + break; + case 0x16: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR MCTRL0: 0x%02x" NLP, PCX, data)); + adcs6_info->rom_disabled = (data & 0x20) ? TRUE : FALSE; /* Unmap Boot ROM */ + break; + case 0x17: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR MCTRL1: 0x%02x" NLP, PCX, data)); + break; + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR BAUD RATE=0x%02x" NLP, PCX, data)); + break; + default: + TRACE_PRINT(ERROR_MSG, + ("ADCS6: " ADDRESS_FORMAT " WR Unhandled Port: 0x%02x=0x%02x" NLP, PCX, port, data)); + break; + } + result = 0; + } else { /* Read */ + result = 0xFF; + switch(port) { + case 0x15: + /* These are the Jumpers at J7. + * Bit 7=0 = double-sided disk, bit 7=1 = single sided. + * Bit 6=0 = use on-board RAM, Bit 6=1 = use S-100 RAM cards. + * Bit 5:0 = "Baud Rate" + */ + result = dipswitch; + TRACE_PRINT(VERBOSE_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD BAUD RATE=0x%02x" NLP, PCX, result)); + break; + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + default: + TRACE_PRINT(ERROR_MSG, + ("ADCS6: " ADDRESS_FORMAT " RD attempt from write-only 0x%02x=0x%02x" NLP, PCX, port, result)); + break; + } + } + return result; +} diff --git a/AltairZ80/s100_disk1a.c b/AltairZ80/s100_disk1a.c index 3b607efb..814d910c 100644 --- a/AltairZ80/s100_disk1a.c +++ b/AltairZ80/s100_disk1a.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: s100_disk1a.c 1771 2008-01-09 07:10:46Z hharte $ * + * $Id: s100_disk1a.c 1996 2008-07-16 05:31:21Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -58,12 +58,15 @@ #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 -#define VERBOSE_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define VERBOSE_MSG (1 << 7) +#define IRQ_MSG (1 << 8) #define DISK1A_MAX_DRIVES 4 @@ -83,6 +86,8 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, int32 (*routine)(const int32, const int32, const int32), uint8 unmap); +extern void raise_ss1_interrupt(uint8 intnum); + extern REG *sim_PC; extern uint32 PCX; /* external view of PC */ @@ -104,8 +109,8 @@ static int32 disk1arom(const int32 port, const int32 io, const int32 data); static uint8 DISK1A_Read(const uint32 Addr); static uint8 DISK1A_Write(const uint32 Addr, uint8 cData); +void raise_disk1a_interrupt(void); -static int32 trace_level = 0; /* Disable all tracing by default */ static int32 bootstrap = 0; /* The DISK1A does not really have RAM associated with it, but for ease of integration with the @@ -122,7 +127,6 @@ static UNIT disk1a_unit[] = { }; static REG disk1a_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, { DRDATA (BOOTSTRAP, bootstrap, 10), }, { NULL } }; @@ -141,13 +145,30 @@ static MTAB disk1a_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if(disk1a_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB disk1a_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "IRQ", IRQ_MSG }, + { NULL, 0 } +}; + DEVICE disk1a_dev = { "DISK1A", disk1a_unit, disk1a_reg, disk1a_mod, DISK1A_MAX_DRIVES, 10, 31, 1, DISK1A_MAX_DRIVES, DISK1A_MAX_DRIVES, NULL, NULL, &disk1a_reset, &disk1a_boot, &disk1a_attach, &disk1a_detach, - &disk1a_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &disk1a_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + disk1a_dt, NULL, "Compupro Floppy Controller DISK1A" }; /* This is the DISK1A Boot ROM. @@ -155,6 +176,16 @@ DEVICE disk1a_dev = { * 512-bytes each. See the DISK1A Manual for details of each * bootstrap. Bootstrap 0 is the default, but others can be * selected with 'd disk1a bootstrap ' at the SIMH SCP Prompt. + * + * Bootstraps 0- 3 8085/8088/Z80 + * Bootstraps 4- 7 8086/80286 + * Bootstraps 8-11 68000 + * Bootstraps 12-15 32016 + * + * 0,4, 8,12: Attempt to boot 8" drive 0, if not ready boot from DISK3. + * 1,5, 9,13: Always boot from DISK3. + * 2,6,10,14: Attempt to boot 8" drive 0, if not ready, attempt to boot 5.25" drive 2. + * 3,7,11,15: Attempt to boot 5.25" drive 0, if not ready, attempt to boot DISK3. */ static uint8 disk1a_rom[16][512] = { { 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x80, 0x3E, 0xFF, 0xD3, 0xC3, 0x01, 0x00, 0x40, 0xE3, 0xE3, /* 0 */ @@ -322,7 +353,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, -{ 0xDB, 0xFD, 0x33, 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x1D, 0x00, 0xBA, 0x90, 0x00, +{ 0xDB, 0xFD, 0x33, 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x1D, 0x00, 0xBA, 0x90, 0x00, /* 5 */ 0xBE, 0x00, 0x00, 0x8B, 0xFE, 0xFC, 0xB9, 0x00, 0x01, 0xF3, 0xA5, 0xEB, 0x18, 0x43, 0x6F, 0x6D, 0x70, 0xB9, 0x00, 0xD0, 0x50, 0x58, 0xE2, 0xFC, 0xC3, 0x33, 0xC0, 0xEE, 0x0A, 0x44, 0x01, 0x74, 0xFB, 0x79, 0x01, 0xC3, 0x58, 0xB0, 0xFE, 0xE6, 0xC3, 0xBE, 0x50, 0x00, 0xB0, 0x01, 0xEE, 0xEB, @@ -355,7 +386,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, -{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xD0, 0x50, 0x58, 0xE2, 0xFC, 0x33, +{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xD0, 0x50, 0x58, 0xE2, 0xFC, 0x33, /* 6 */ 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x04, 0x00, 0xBE, 0x00, 0x00, 0x8B, 0xFE, 0xB9, 0x80, 0x00, 0xF3, 0xA5, 0xEB, 0x17, 0xFC, 0x33, 0xC0, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xAC, 0xE6, 0xC1, 0xE2, 0xF5, 0xC3, 0xB9, 0x00, 0xF0, 0x50, 0x58, 0xE2, 0xFC, 0xC3, 0xBE, 0xCA, 0x00, @@ -387,7 +418,8 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, -{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xA0, 0x50, 0x58, 0xE2, 0xFC, 0x33, + +{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xA0, 0x50, 0x58, 0xE2, 0xFC, 0x33, /* 7 */ 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x04, 0x00, 0xBA, 0x90, 0x00, 0xBE, 0x00, 0x00, 0x8B, 0xFE, 0xB9, 0x00, 0x01, 0xF3, 0xA5, 0xB0, 0xFE, 0xE6, 0xC3, 0xB0, 0x28, 0xE6, 0xC0, 0xB9, 0x00, 0xA0, 0x50, 0x58, 0xE2, 0xFC, 0xB9, 0x03, 0x00, 0xBE, 0xCA, 0x00, 0xE8, 0xC1, 0x00, 0xB9, @@ -420,7 +452,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xF8, +{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xF8, /* 8 */ 0x00, 0x00, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x24, 0xD9, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x2C, 0x42, 0x39, 0x00, 0xFF, 0x00, 0xC3, 0x4E, 0xD2, 0x49, 0xF9, 0x00, 0xFF, 0x00, 0xC0, 0x4B, 0xEC, 0x00, 0x01, 0x4D, 0xEC, 0x00, 0x02, 0x43, 0xEC, 0x00, 0x02, 0x19, 0x7C, @@ -453,7 +485,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x43, 0xF9, 0x00, 0xFF, 0x00, 0x90, 0x20, 0x3C, +{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x43, 0xF9, 0x00, 0xFF, 0x00, 0x90, 0x20, 0x3C, /* 9 */ 0x00, 0x00, 0x00, 0x7F, 0x45, 0xF8, 0x00, 0x00, 0x26, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x26, 0xDA, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x34, 0x41, 0xF9, 0x00, 0xFF, 0x00, 0xC3, 0x42, 0x10, 0x4E, 0xD2, 0x2A, 0x7C, 0x00, 0x00, 0x80, 0x66, 0x21, 0xFC, 0x00, 0x66, 0x80, 0x00, @@ -486,7 +518,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x41, 0xF8, +{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x41, 0xF8, /* A */ 0x00, 0x00, 0x22, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x22, 0xD8, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x2C, 0x42, 0x39, 0x00, 0xFF, 0x00, 0xC3, 0x4E, 0xD2, 0x41, 0xF9, 0x00, 0xFF, 0x00, 0xC0, 0x43, 0xE8, 0x00, 0x01, 0x45, 0xE8, 0x00, 0x02, 0x47, 0xE8, 0x00, 0x03, 0x17, 0x7C, @@ -519,7 +551,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xF8, +{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xF8, /* B */ 0x00, 0x00, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x24, 0xD9, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x2C, 0x42, 0x39, 0x00, 0xFF, 0x00, 0xC3, 0x4E, 0xD2, 0x49, 0xF9, 0x00, 0xFF, 0x00, 0xC0, 0x4B, 0xEC, 0x00, 0x01, 0x4D, 0xEC, 0x00, 0x02, 0x43, 0xEC, 0x00, 0x02, 0x19, 0x7C, @@ -552,7 +584,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, +{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, /* C */ 0xFE, 0x00, 0xC0, 0x67, 0x61, 0x01, 0xA7, 0x61, 0x02, 0x67, 0x60, 0x03, 0x54, 0xA2, 0x80, 0x00, 0xDC, 0x1B, 0x5C, 0x60, 0x00, 0xE7, 0xA9, 0xC0, 0x00, 0x01, 0xCD, 0x5C, 0x70, 0x00, 0x5C, 0x71, 0x00, 0x5C, 0x70, 0x00, 0xDC, 0x12, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, @@ -585,7 +617,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0xA7, 0xA9, 0xC0, 0xFE, 0x00, 0x90, 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, +{ 0xA7, 0xA9, 0xC0, 0xFE, 0x00, 0x90, 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, /* D */ 0x0E, 0x03, 0x00, 0x67, 0xA8, 0xC0, 0xFE, 0x00, 0xC3, 0x5C, 0x48, 0x00, 0x5C, 0xA8, 0xC0, 0x00, 0x00, 0x61, 0xDC, 0x70, 0x00, 0x5C, 0x70, 0x00, 0xDD, 0x07, 0xA2, 0xA2, 0xA2, 0xCD, 0x07, 0x7D, 0x9C, 0xAF, 0xC0, 0x00, 0x00, 0x61, 0x1A, 0x66, 0xEA, 0xC0, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, @@ -618,7 +650,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, +{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, /* E */ 0xFE, 0x00, 0xC0, 0x67, 0x61, 0x01, 0xA7, 0x61, 0x02, 0x67, 0x60, 0x03, 0x54, 0xA2, 0x80, 0x00, 0xDC, 0x1B, 0x5C, 0x60, 0x00, 0xE7, 0xA9, 0xC0, 0x00, 0x01, 0x33, 0x5C, 0x70, 0x00, 0x5C, 0x71, 0x00, 0x5C, 0x70, 0x00, 0xDC, 0x11, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, @@ -651,7 +683,7 @@ static uint8 disk1a_rom[16][512] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, +{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, /* F */ 0xFE, 0x00, 0xC0, 0x67, 0x61, 0x01, 0xA7, 0x61, 0x02, 0x67, 0x60, 0x03, 0x54, 0xA2, 0x80, 0x00, 0xDC, 0x1B, 0x14, 0xA3, 0x28, 0x00, 0xE7, 0xA9, 0xC0, 0x00, 0x01, 0xCD, 0x5C, 0x70, 0x00, 0x5C, 0x71, 0x00, 0x5C, 0x70, 0x00, 0xDC, 0x12, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, @@ -690,7 +722,8 @@ static uint8 disk1a_rom[16][512] = { static int32 disk1a_hasProperty(uint32 property) { int32 i; for (i = 0; i < DISK1A_MAX_DRIVES; i++) - if (disk1a_dev.units[i].flags & property) return TRUE; + if (disk1a_dev.units[i].flags & property) + return TRUE; return FALSE; } @@ -707,7 +740,7 @@ static t_stat disk1a_reset(DEVICE *dptr) /* Connect DISK1A ROM at base address */ if (disk1a_hasProperty(UNIT_DISK1A_ROM)) if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &disk1arom, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); return SCPE_ARG; } @@ -722,6 +755,7 @@ static t_stat disk1a_reset(DEVICE *dptr) static t_stat disk1a_boot(int32 unitno, DEVICE *dptr) { + bootstrap &= 0xF; DBG_PRINT(("Booting DISK1A Controller, bootstrap=%d" NLP, bootstrap)); /* Re-enable the ROM in case it was disabled */ @@ -758,6 +792,7 @@ static int32 disk1arom(const int32 Addr, const int32 write, const int32 data) disk1aram[Addr & 0x1FF] = data; return 0; } else { + bootstrap &= 0xF; if(disk1a_info->rom_disabled == FALSE) { return(disk1a_rom[bootstrap][Addr & 0x1FF]); } else { @@ -786,7 +821,7 @@ static int32 disk1adev(const int32 port, const int32 io, const int32 data) #define DISK1A_MOTOR 3 /* R=Unused / W=Motor Control Register */ #define BOOT_PROM_DISABLE 0x01 #define FLOPPY_MOTORS 0xF0 - +extern uint8 i8272_irq; static uint8 DISK1A_Read(const uint32 Addr) { uint8 cData; @@ -799,7 +834,7 @@ static uint8 DISK1A_Read(const uint32 Addr) cData = I8272_Read(Addr); break; case DISK1A_DRIVE_STATUS: - cData = 0x81; /* Ready */ + cData = i8272_irq ? 0x81 : 0x01; /* Ready */ TRACE_PRINT(STATUS_MSG, ("DISK1A: " ADDRESS_FORMAT " RD STATUS = 0x%02x" NLP, PCX, cData)) break; @@ -851,3 +886,12 @@ static uint8 DISK1A_Write(const uint32 Addr, uint8 cData) return (result); } +#define SS1_VI4_INT 4 /* IF3 Tx interrupts tied to VI3 */ + +void raise_disk1a_interrupt(void) +{ + TRACE_PRINT(IRQ_MSG, ("DISK1A: " ADDRESS_FORMAT " Interrupt" NLP, PCX)); + + raise_ss1_interrupt(SS1_VI4_INT); + +} diff --git a/AltairZ80/s100_disk2.c b/AltairZ80/s100_disk2.c index 25d6a7b9..a0cdc5fb 100644 --- a/AltairZ80/s100_disk2.c +++ b/AltairZ80/s100_disk2.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: s100_disk2.c 1771 2008-01-09 07:10:46Z hharte $ * + * $Id: s100_disk2.c 1995 2008-07-15 03:59:13Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -49,13 +49,15 @@ #include "sim_imd.h" -#define SEEK_MSG 0x01 -#define BUG_MSG 0x02 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 -#define VERBOSE_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define IRQ_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) #define DISK2_MAX_DRIVES 4 @@ -104,6 +106,17 @@ typedef struct { static DISK2_INFO disk2_info_data = { { 0x0, 0, 0xC8, 2 } }; static DISK2_INFO *disk2_info = &disk2_info_data; +/* Default geometry for a 20MB hard disk. */ +#define C20MB_NTRACKS 243 +#define C20MB_NHEADS 8 +#define C20MB_NSECTORS 11 +#define C20MB_SECTSIZE 1024 + +static int32 ntracks = C20MB_NTRACKS; +static int32 nheads = C20MB_NHEADS; +static int32 nsectors = C20MB_NSECTORS; +static int32 sectsize = C20MB_SECTSIZE; + extern uint32 PCX; extern REG *sim_PC; extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); @@ -112,16 +125,13 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ int32 (*routine)(const int32, const int32, const int32), uint8 unmap); extern int32 selchan_dma(uint8 *buf, uint32 len); extern int32 find_unit_index(UNIT *uptr); - -/* These are needed for DMA. PIO Mode has not been implemented yet. */ -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); +extern void raise_ss1_interrupt(uint8 intnum); #define UNIT_V_DISK2_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_DISK2_WLK (1 << UNIT_V_DISK2_WLK) #define UNIT_V_DISK2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE) -#define DISK2_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ +#define DISK2_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */ #define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */ #define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */ #define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */ @@ -129,14 +139,13 @@ extern uint8 GetBYTEWrapper(const uint32 Addr); static t_stat disk2_reset(DEVICE *disk2_dev); static t_stat disk2_attach(UNIT *uptr, char *cptr); static t_stat disk2_detach(UNIT *uptr); +static void raise_disk2_interrupt(void); static int32 disk2dev(const int32 port, const int32 io, const int32 data); static uint8 DISK2_Read(const uint32 Addr); static uint8 DISK2_Write(const uint32 Addr, uint8 cData); -static int32 trace_level = 0; /* Disable all tracing by default */ - static UNIT disk2_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK2_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK2_CAPACITY) }, @@ -145,7 +154,15 @@ static UNIT disk2_unit[] = { }; static REG disk2_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, + { DRDATA (NTRACKS, ntracks, 10), }, + { DRDATA (NHEADS, nheads, 8), }, + { DRDATA (NSECTORS, nsectors, 8), }, + { DRDATA (SECTSIZE, sectsize, 11), }, + { HRDATA (SEL_DRIVE, disk2_info_data.sel_drive, 3), }, + { HRDATA (CYL, disk2_info_data.cyl, 8), }, + { HRDATA (HEAD, disk2_info_data.head, 8), }, + { HRDATA (SECTOR, disk2_info_data.sector, 8), }, + { NULL } }; @@ -160,13 +177,30 @@ static MTAB disk2_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if(disk2_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB disk2_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "IRQ", IRQ_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { NULL, 0 } +}; + DEVICE disk2_dev = { "DISK2", disk2_unit, disk2_reg, disk2_mod, DISK2_MAX_DRIVES, 10, 31, 1, DISK2_MAX_DRIVES, DISK2_MAX_DRIVES, NULL, NULL, &disk2_reset, NULL, &disk2_attach, &disk2_detach, - &disk2_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &disk2_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + disk2_dt, NULL, "Compupro Hard Disk Controller DISK2" }; /* Reset routine */ @@ -193,7 +227,7 @@ static t_stat disk2_attach(UNIT *uptr, char *cptr) t_stat r = SCPE_OK; DISK2_DRIVE_INFO *pDrive; char header[4]; - unsigned int i = 0; + int i = 0; i = find_unit_index(uptr); if (i == -1) { @@ -204,10 +238,10 @@ static t_stat disk2_attach(UNIT *uptr, char *cptr) pDrive->ready = 1; disk2_info->write_fault = 1; pDrive->track = 5; - pDrive->ntracks = 243; - pDrive->nheads = 8; - pDrive->nsectors = 11; - pDrive->sectsize = 1024; + pDrive->ntracks = ntracks; + pDrive->nheads = nheads; + pDrive->nsectors = nsectors; + pDrive->sectsize = sectsize; r = attach_unit(uptr, cptr); /* attach unit */ if ( r != SCPE_OK) /* error? */ @@ -254,7 +288,8 @@ static t_stat disk2_attach(UNIT *uptr, char *cptr) if (uptr->flags & UNIT_DISK2_VERBOSE) printf("--------------------------------------------------------\n"); disk2_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_DISK2_VERBOSE)); - if (uptr->flags & UNIT_DISK2_VERBOSE) printf("\n"); + if (uptr->flags & UNIT_DISK2_VERBOSE) + printf("\n"); } else { disk2_info->drive[i].imd = NULL; } @@ -415,11 +450,11 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData) } /* See FIXME above... that might be why this does not work properly... */ if(disk2_info->cyl != pDrive->track) { /* problem, should not happen, see above */ - TRACE_PRINT(BUG_MSG, ("DISK2: " ADDRESS_FORMAT " READ_DATA: cyl=%d, track=%d" NLP, + TRACE_PRINT(ERROR_MSG, ("DISK2: " ADDRESS_FORMAT " READ_DATA: cyl=%d, track=%d" NLP, PCX, disk2_info->cyl, pDrive->track)); pDrive->track = disk2_info->cyl; /* update track */ } - fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); for(i=0;insectors;i++) { /* Read sector */ fread(sdata.raw, (pDrive->sectsize + 3), 1, (pDrive->uptr)->fileref); @@ -453,12 +488,12 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData) printf("DISK2: " ADDRESS_FORMAT " WRITE_DATA: head_sel != head" NLP, PCX); } if(disk2_info->cyl != pDrive->track) { /* problem, should not happen, see above */ - TRACE_PRINT(BUG_MSG, ("DISK2: " ADDRESS_FORMAT " WRITE_DATA = 0x%02x, cyl=%d, track=%d" NLP, + TRACE_PRINT(ERROR_MSG, ("DISK2: " ADDRESS_FORMAT " WRITE_DATA = 0x%02x, cyl=%d, track=%d" NLP, PCX, cData, disk2_info->cyl, pDrive->track)); pDrive->track = disk2_info->cyl; /* update track */ } - fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); for(i=0;insectors;i++) { /* Read sector */ file_offset = ftell((pDrive->uptr)->fileref); @@ -474,7 +509,7 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData) } selchan_dma(sdata.u.data, pDrive->sectsize); - fseek((pDrive->uptr)->fileref, file_offset+3, SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, file_offset+3, SEEK_SET); fwrite(sdata.u.data, (pDrive->sectsize), 1, (pDrive->uptr)->fileref); break; } @@ -496,7 +531,7 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData) i = disk2_info->hdr_sector; selchan_dma(sdata.raw, 3); - fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * (pDrive->sectsize + 3) * pDrive->nsectors) + (i * (pDrive->sectsize + 3)), SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * (pDrive->sectsize + 3) * pDrive->nsectors) + (i * (pDrive->sectsize + 3)), SEEK_SET); fwrite(sdata.raw, 3, 1, (pDrive->uptr)->fileref); disk2_info->hdr_sector++; @@ -508,15 +543,17 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData) case DISK2_CMD_READ_HEADER: track_offset = pDrive->track * pDrive->nheads * pDrive->nsectors * (pDrive->sectsize + 3); TRACE_PRINT(CMD_MSG, ("DISK2: " ADDRESS_FORMAT " READ_HEADER Command" NLP, PCX)); - fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); fread(sdata.raw, 3, 1, (pDrive->uptr)->fileref); selchan_dma(sdata.raw, 3); + break; default: printf("DISK2: " ADDRESS_FORMAT " Unknown CMD=%d" NLP, PCX, disk2_info->ctl_op); break; } + raise_disk2_interrupt(); disk2_info->ctl_attn = 0; } @@ -572,3 +609,12 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData) return (result); } +#define SS1_VI1_INT 1 /* DISK2/DISK3 interrupts tied to VI1 */ + +static void raise_disk2_interrupt(void) +{ + TRACE_PRINT(IRQ_MSG, ("DISK2: " ADDRESS_FORMAT " Interrupt" NLP, PCX)); + + raise_ss1_interrupt(SS1_VI1_INT); + +} diff --git a/AltairZ80/s100_disk3.c b/AltairZ80/s100_disk3.c new file mode 100644 index 00000000..6602f9cb --- /dev/null +++ b/AltairZ80/s100_disk3.c @@ -0,0 +1,667 @@ +/************************************************************************* + * * + * $Id: s100_disk3.c 1997 2008-07-18 05:29:52Z hharte $ * + * * + * Copyright (c) 2007-2008 Howard M. Harte. * + * http://www.hartetec.com * + * * + * Permission is hereby granted, free of charge, to any person obtaining * + * a copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to * + * the following conditions: * + * * + * The above copyright notice and this permission notice shall be * + * included in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * + * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE 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 Howard M. Harte shall * + * not be used in advertising or otherwise to promote the sale, use or * + * other dealings in this Software without prior written authorization * + * Howard M. Harte. * + * * + * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * + * * + * Module Description: * + * CompuPro DISK3 Hard Disk Controller module for SIMH. * + * * + * Environment: * + * User mode only * + * * + *************************************************************************/ + +#include "altairz80_defs.h" + +#if defined (_WIN32) +#include +#endif + +#include "sim_imd.h" + +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define IRQ_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) +#define SPECIFY_MSG (1 << 8) + +#define DISK3_MAX_DRIVES 4 + +#define DISK3_CSR 0 /* R=DISK3 Status / W=DISK3 Control Register */ +#define DISK3_DATA 1 /* R=Step Pulse / W=Write Data Register */ + +#define DISK3_OP_DRIVE 0x00 +#define DISK3_OP_CYL 0x01 +#define DISK3_OP_HEAD 0x02 +#define DISK3_OP_SECTOR 0x03 + +#define DISK3_CMD_NULL 0x00 +#define DISK3_CMD_READ_DATA 0x01 +#define DISK3_CMD_WRITE_DATA 0x02 +#define DISK3_CMD_WRITE_HEADER 0x03 +#define DISK3_CMD_READ_HEADER 0x04 + +#define DISK3_STATUS_BUSY 0 +#define DISK3_STATUS_RANGE 1 +#define DISK3_STATUS_NOT_READY 2 +#define DISK3_STATUS_TIMEOUT 3 +#define DISK3_STATUS_DAT_CRC 4 +#define DISK3_STATUS_WR_FAULT 5 +#define DISK3_STATUS_OVERRUN 6 +#define DISK3_STATUS_HDR_CRC 7 +#define DISK3_STATUS_MAP_FULL 8 +#define DISK3_STATUS_COMPLETE 0xFF /* Complete with No Error */ + +#define DISK3_CODE_NOOP 0x00 +#define DISK3_CODE_VERSION 0x01 +#define DISK3_CODE_GLOBAL 0x02 +#define DISK3_CODE_SPECIFY 0x03 +#define DISK3_CODE_SET_MAP 0x04 +#define DISK3_CODE_HOME 0x05 +#define DISK3_CODE_SEEK 0x06 +#define DISK3_CODE_READ_HDR 0x07 +#define DISK3_CODE_READWRITE 0x08 +#define DISK3_CODE_RELOCATE 0x09 +#define DISK3_CODE_FORMAT 0x0A +#define DISK3_CODE_FORMAT_BAD 0x0B +#define DISK3_CODE_STATUS 0x0C +#define DISK3_CODE_SELECT 0x0D +#define DISK3_CODE_EXAMINE 0x0E +#define DISK3_CODE_MODIFY 0x0F + +#define DISK3_CMD_MASK 0x3F +#define DISK3_REQUEST_IRQ 0x80 + +#define DISK3_IOPB_LEN 16 + +#define DISK3_IOPB_CMD 0 +#define DISK3_IOPB_STATUS 1 +#define DISK3_IOPB_DRIVE 2 +#define DISK3_IOPB_ARG1 3 +#define DISK3_IOPB_ARG2 4 +#define DISK3_IOPB_ARG3 5 +#define DISK3_IOPB_ARG4 6 +#define DISK3_IOPB_ARG5 7 +#define DISK3_IOPB_ARG6 8 +#define DISK3_IOPB_ARG7 9 +#define DISK3_IOPB_DATA 10 +#define DISK3_IOPB_LINK 13 + +#define DISK3_MODE_ABS 0xFF +#define DISK3_MODE_LOGICAL 0x00 + +typedef struct { + UNIT *uptr; + DISK_INFO *imd; + uint16 sectsize; /* sector size, not including pre/postamble */ + uint16 nsectors; /* number of sectors/track */ + uint16 nheads; /* number of heads */ + uint16 ntracks; /* number of tracks */ + uint16 res_tracks; /* Number of reserved tracks on drive. */ + uint16 track; /* Current Track */ + + uint16 cur_sect; /* current starting sector of transfer */ + uint16 cur_track; /* Current Track */ + uint16 xfr_nsects; /* Number of sectors to transfer */ + uint8 ready; /* Is drive ready? */ +} DISK3_DRIVE_INFO; + +typedef struct { + PNP_INFO pnp; /* Plug and Play */ + uint8 sel_drive; /* Currently selected drive */ + uint8 mode; /* mode (0xFF=absolute, 0x00=logical) */ + uint8 retries; /* Number of retries to attempt */ + uint8 ndrives; /* Number of drives attached to the controller */ + + uint32 link_addr; /* Link Address for next IOPB */ + uint32 dma_addr; /* DMA Address for the current IOPB */ + + DISK3_DRIVE_INFO drive[DISK3_MAX_DRIVES]; + uint8 iopb[16]; +} DISK3_INFO; + +static DISK3_INFO disk3_info_data = { { 0x0, 0, 0x90, 2 } }; +static DISK3_INFO *disk3_info = &disk3_info_data; + +/* Disk geometries: + * ST506 ST412 CMI5619 Q520 Q540 Q2080 + * Sectsize: 1024 1024 1024 1024 1024 1024 + * Sectors: 9 9 9 9 9 11 + * Heads: 4 4 6 4 8 7 + * Tracks: 153 306 306 512 512 1172 + */ + +/* Default geometry for a 20MB hard disk. */ +#define C20MB_SECTSIZE 1024 +#define C20MB_NSECTORS 9 +#define C20MB_NHEADS 4 +#define C20MB_NTRACKS 512 + +static int32 ntracks = C20MB_NTRACKS; +static int32 nheads = C20MB_NHEADS; +static int32 nsectors = C20MB_NSECTORS; +static int32 sectsize = C20MB_SECTSIZE; + +extern uint32 PCX; +extern REG *sim_PC; +extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); +extern int32 find_unit_index(UNIT *uptr); +extern void raise_ss1_interrupt(uint8 intnum); + +/* These are needed for DMA. */ +extern void PutByteDMA(const uint32 Addr, const uint32 Value); +extern uint8 GetByteDMA(const uint32 Addr); + +#define UNIT_V_DISK3_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_DISK3_WLK (1 << UNIT_V_DISK3_WLK) +#define UNIT_V_DISK3_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE) +#define DISK3_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */ +#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */ +#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */ +#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */ + +static t_stat disk3_reset(DEVICE *disk3_dev); +static t_stat disk3_attach(UNIT *uptr, char *cptr); +static t_stat disk3_detach(UNIT *uptr); +static void raise_disk3_interrupt(void); + +static int32 disk3dev(const int32 port, const int32 io, const int32 data); + +/* static uint8 DISK3_Read(const uint32 Addr); */ +static uint8 DISK3_Write(const uint32 Addr, uint8 cData); + +static UNIT disk3_unit[] = { + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) } +}; + +static REG disk3_reg[] = { + { DRDATA (NTRACKS, ntracks, 10), }, + { DRDATA (NHEADS, nheads, 8), }, + { DRDATA (NSECTORS, nsectors, 8), }, + { DRDATA (SECTSIZE, sectsize, 11), }, + { HRDATA (SEL_DRIVE, disk3_info_data.sel_drive, 3), }, + { HRDATA (MODE, disk3_info_data.mode, 8), }, + { HRDATA (RETRIES, disk3_info_data.retries, 8), }, + { HRDATA (NDRIVES, disk3_info_data.ndrives, 8), }, + { HRDATA (LINK_ADDR, disk3_info_data.link_addr, 32), }, + { HRDATA (DMA_ADDR, disk3_info_data.dma_addr, 32), }, + { BRDATA (IOPB, &disk3_info_data.iopb[DISK3_IOPB_CMD], 16, 8, 16), }, + { NULL } +}; + +static MTAB disk3_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { UNIT_DISK3_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_DISK3_WLK, UNIT_DISK3_WLK, "WRTLCK", "WRTLCK", NULL }, + /* quiet, no warning messages */ + { UNIT_DISK3_VERBOSE, 0, "QUIET", "QUIET", NULL }, + /* verbose, show warning messages */ + { UNIT_DISK3_VERBOSE, UNIT_DISK3_VERBOSE, "VERBOSE", "VERBOSE", NULL }, + { 0 } +}; + +#define TRACE_PRINT(level, args) if(disk3_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB disk3_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "IRQ", IRQ_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "SPECIFY",SPECIFY_MSG }, + { NULL, 0 } +}; + +DEVICE disk3_dev = { + "DISK3", disk3_unit, disk3_reg, disk3_mod, + DISK3_MAX_DRIVES, 10, 31, 1, DISK3_MAX_DRIVES, DISK3_MAX_DRIVES, + NULL, NULL, &disk3_reset, + NULL, &disk3_attach, &disk3_detach, + &disk3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + disk3_dt, NULL, "Compupro ST-506 Disk Controller DISK3" +}; + +/* Reset routine */ +static t_stat disk3_reset(DEVICE *dptr) +{ + PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; + + if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ + sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk3dev, TRUE); + } else { + /* Connect DISK3 at base address */ + if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk3dev, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + } + + disk3_info->link_addr = 0x50; /* After RESET, the link pointer is at 0x50. */ + + return SCPE_OK; +} + + +/* Attach routine */ +static t_stat disk3_attach(UNIT *uptr, char *cptr) +{ + t_stat r = SCPE_OK; + DISK3_DRIVE_INFO *pDrive; + char header[4]; + unsigned int i = 0; + + i = find_unit_index(uptr); + if (i == -1) { + return (SCPE_IERR); + } + pDrive = &disk3_info->drive[i]; + + pDrive->ready = 1; + pDrive->track = 5; + pDrive->ntracks = C20MB_NTRACKS; + pDrive->nheads = C20MB_NHEADS; + pDrive->nsectors = C20MB_NSECTORS; + pDrive->sectsize = C20MB_SECTSIZE; + + r = attach_unit(uptr, cptr); /* attach unit */ + if ( r != SCPE_OK) /* error? */ + return r; + + /* Determine length of this disk */ + if(sim_fsize(uptr->fileref) != 0) { + uptr->capac = sim_fsize(uptr->fileref); + } else { + uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); + } + + pDrive->uptr = uptr; + + /* Default for new file is DSK */ + uptr->u3 = IMAGE_TYPE_DSK; + + if(uptr->capac > 0) { + fgets(header, 4, uptr->fileref); + if(!strcmp(header, "IMD")) { + uptr->u3 = IMAGE_TYPE_IMD; + } else if(!strcmp(header, "CPT")) { + printf("CPT images not yet supported\n"); + uptr->u3 = IMAGE_TYPE_CPT; + disk3_detach(uptr); + return SCPE_OPENERR; + } else { + uptr->u3 = IMAGE_TYPE_DSK; + } + } + + if (uptr->flags & UNIT_DISK3_VERBOSE) + printf("DISK3%d, attached to '%s', type=%s, len=%d\n", i, cptr, + uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", + uptr->capac); + + if(uptr->u3 == IMAGE_TYPE_IMD) { + if(uptr->capac < 318000) { + printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); + disk3_detach(uptr); + return SCPE_OPENERR; + } + + if (uptr->flags & UNIT_DISK3_VERBOSE) + printf("--------------------------------------------------------\n"); + disk3_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_DISK3_VERBOSE)); + if (uptr->flags & UNIT_DISK3_VERBOSE) + printf("\n"); + } else { + disk3_info->drive[i].imd = NULL; + } + + return SCPE_OK; +} + + +/* Detach routine */ +t_stat disk3_detach(UNIT *uptr) +{ + DISK3_DRIVE_INFO *pDrive; + t_stat r; + int8 i; + + i = find_unit_index(uptr); + + if (i == -1) { + return (SCPE_IERR); + } + + pDrive = &disk3_info->drive[i]; + + pDrive->ready = 0; + + if (uptr->flags & UNIT_DISK3_VERBOSE) + printf("Detach DISK3%d\n", i); + + r = detach_unit(uptr); /* detach unit */ + if ( r != SCPE_OK) + return r; + + return SCPE_OK; +} + + +static int32 disk3dev(const int32 port, const int32 io, const int32 data) +{ + TRACE_PRINT(VERBOSE_MSG, ("DISK3: " ADDRESS_FORMAT " IO %s, Port %02x" NLP, PCX, io ? "WR" : "RD", port)); + if(io) { + DISK3_Write(port, data); + return 0; + } else { + return(0xFF); + } +} + +static uint8 DISK3_Write(const uint32 Addr, uint8 cData) +{ + uint32 next_link; + uint8 result = DISK3_STATUS_COMPLETE; + uint8 i; + uint8 cmd; + + DISK3_DRIVE_INFO *pDrive; + + for(i = 0; i < DISK3_IOPB_LEN; i++) { + disk3_info->iopb[i] = GetByteDMA(disk3_info->link_addr + i); + } + + cmd = disk3_info->iopb[DISK3_IOPB_CMD]; + disk3_info->sel_drive = disk3_info->iopb[DISK3_IOPB_DRIVE] & 0x03; + + disk3_info->dma_addr = disk3_info->iopb[0x0A]; + disk3_info->dma_addr |= disk3_info->iopb[0x0B] << 8; + disk3_info->dma_addr |= disk3_info->iopb[0x0C] << 16; + + next_link = disk3_info->iopb[DISK3_IOPB_LINK+0]; + next_link |= disk3_info->iopb[DISK3_IOPB_LINK+1] << 8; + next_link |= disk3_info->iopb[DISK3_IOPB_LINK+2] << 16; + + TRACE_PRINT(VERBOSE_MSG, ("DISK3[%d]: LINK=0x%05x, NEXT=0x%05x, CMD=%x, %s DMA@0x%05x\n", + disk3_info->sel_drive, + disk3_info->link_addr, + next_link, + disk3_info->iopb[DISK3_IOPB_CMD] & DISK3_CMD_MASK, + (disk3_info->iopb[DISK3_IOPB_CMD] & DISK3_REQUEST_IRQ) ? "IRQ" : "POLL", + disk3_info->dma_addr)); + + pDrive = &disk3_info->drive[disk3_info->sel_drive]; + + if(pDrive->ready) { + + /* Perform command */ + switch(cmd & DISK3_CMD_MASK) { + case DISK3_CODE_NOOP: + TRACE_PRINT(VERBOSE_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " NOOP" NLP, disk3_info->sel_drive, PCX)); + break; + case DISK3_CODE_VERSION: + break; + case DISK3_CODE_GLOBAL: + TRACE_PRINT(CMD_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " GLOBAL" NLP, disk3_info->sel_drive, PCX)); + + disk3_info->mode = disk3_info->iopb[DISK3_IOPB_ARG1]; + disk3_info->retries = disk3_info->iopb[DISK3_IOPB_ARG2]; + disk3_info->ndrives = disk3_info->iopb[DISK3_IOPB_ARG3]; + + TRACE_PRINT(SPECIFY_MSG, (" Mode: 0x%02x" NLP, disk3_info->mode)); + TRACE_PRINT(SPECIFY_MSG, (" # Retries: 0x%02x" NLP, disk3_info->retries)); + TRACE_PRINT(SPECIFY_MSG, (" # Drives: 0x%02x" NLP, disk3_info->ndrives)); + + if(disk3_info->mode == DISK3_MODE_ABS) { + TRACE_PRINT(ERROR_MSG, ("DISK3: Absolute addressing not supported." NLP)); + } + + break; + case DISK3_CODE_SPECIFY: + { + uint8 specify_data[22]; + TRACE_PRINT(CMD_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " SPECIFY" NLP, disk3_info->sel_drive, PCX)); + + for(i = 0; i < 22; i++) { + specify_data[i] = GetByteDMA(disk3_info->dma_addr + i); + } + + pDrive->sectsize = specify_data[4] | (specify_data[5] << 8); + pDrive->nsectors = specify_data[6] | (specify_data[7] << 8); + pDrive->nheads = specify_data[8] | (specify_data[9] << 8); + pDrive->ntracks = specify_data[10] | (specify_data[11] << 8); + pDrive->res_tracks = specify_data[18] | (specify_data[19] << 8); + + TRACE_PRINT(SPECIFY_MSG, (" Sectsize: %d" NLP, pDrive->sectsize)); + TRACE_PRINT(SPECIFY_MSG, (" Sectors: %d" NLP, pDrive->nsectors)); + TRACE_PRINT(SPECIFY_MSG, (" Heads: %d" NLP, pDrive->nheads)); + TRACE_PRINT(SPECIFY_MSG, (" Tracks: %d" NLP, pDrive->ntracks)); + TRACE_PRINT(SPECIFY_MSG, (" Reserved: %d" NLP, pDrive->res_tracks)); + break; + } + case DISK3_CODE_HOME: + pDrive->track = 0; + TRACE_PRINT(SEEK_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " HOME" NLP, disk3_info->sel_drive, PCX)); + break; + case DISK3_CODE_SEEK: + pDrive->track = disk3_info->iopb[DISK3_IOPB_ARG1]; + pDrive->track |= (disk3_info->iopb[DISK3_IOPB_ARG2] << 8); + + if(pDrive->track > pDrive->ntracks) { + TRACE_PRINT(ERROR_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " SEEK ERROR %d not found" NLP, disk3_info->sel_drive, PCX, pDrive->track)); + pDrive->track = pDrive->ntracks - 1; + result = DISK3_STATUS_TIMEOUT; + } else { + TRACE_PRINT(SEEK_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " SEEK %d" NLP, disk3_info->sel_drive, PCX, pDrive->track)); + } + break; + case DISK3_CODE_READ_HDR: + { + TRACE_PRINT(CMD_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " READ HEADER: %d" NLP, pDrive->track, PCX, pDrive->track >> 8)); + PutByteDMA(disk3_info->dma_addr + 0, pDrive->track & 0xFF); + PutByteDMA(disk3_info->dma_addr + 1, (pDrive->track >> 8) & 0xFF); + PutByteDMA(disk3_info->dma_addr + 2, 0); + PutByteDMA(disk3_info->dma_addr + 3, 1); + + break; + } + case DISK3_CODE_READWRITE: + { + uint32 track_len; + uint32 xfr_len; + uint32 file_offset; + uint32 xfr_count = 0; + uint8 *dataBuffer; + + if(disk3_info->mode == DISK3_MODE_ABS) { + TRACE_PRINT(ERROR_MSG, ("DISK3: Absolute addressing not supported." NLP)); + break; + } + + pDrive->cur_sect = disk3_info->iopb[DISK3_IOPB_ARG2] | (disk3_info->iopb[DISK3_IOPB_ARG3] << 8); + pDrive->cur_track = disk3_info->iopb[DISK3_IOPB_ARG4] | (disk3_info->iopb[DISK3_IOPB_ARG5] << 8); + pDrive->xfr_nsects = disk3_info->iopb[DISK3_IOPB_ARG6] | (disk3_info->iopb[DISK3_IOPB_ARG7] << 8); + + track_len = pDrive->nsectors * pDrive->sectsize; + + file_offset = (pDrive->cur_track * track_len); /* Calculate offset based on current track */ + file_offset += pDrive->cur_sect * pDrive->sectsize; + + xfr_len = pDrive->xfr_nsects * pDrive->sectsize; + + dataBuffer = malloc(xfr_len); + + sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); + + if(disk3_info->iopb[DISK3_IOPB_ARG1] == 1) { /* Read */ + TRACE_PRINT(RD_DATA_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " READ @0x%05x T:%04d/S:%04d/#:%d" NLP, + disk3_info->sel_drive, + PCX, + disk3_info->dma_addr, + pDrive->cur_track, + pDrive->cur_sect, + pDrive->xfr_nsects + )); + + fread(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref); + + /* Perform DMA Transfer */ + for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { + PutByteDMA(disk3_info->dma_addr + xfr_count, dataBuffer[xfr_count]); + } + } else { /* Write */ + TRACE_PRINT(WR_DATA_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " WRITE @0x%05x T:%04d/S:%04d/#:%d" NLP, + disk3_info->sel_drive, + PCX, + disk3_info->dma_addr, + pDrive->cur_track, + pDrive->cur_sect, + pDrive->xfr_nsects + )); + + /* Perform DMA Transfer */ + for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { + dataBuffer[xfr_count] = GetByteDMA(disk3_info->dma_addr + xfr_count); + } + + fwrite(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref); + } + + free(dataBuffer); + /* Update Track/Sector in IOPB */ + pDrive->cur_sect += pDrive->xfr_nsects; + if(pDrive->cur_sect >= pDrive->nsectors) { + pDrive->cur_sect = pDrive->cur_sect % pDrive->nsectors; + pDrive->cur_track++; + } + disk3_info->iopb[DISK3_IOPB_ARG2] = pDrive->cur_sect & 0xFF; + disk3_info->iopb[DISK3_IOPB_ARG3] = (pDrive->cur_sect >> 8) & 0xFF; + disk3_info->iopb[DISK3_IOPB_ARG4] = pDrive->cur_track & 0xFF; + disk3_info->iopb[DISK3_IOPB_ARG5] = (pDrive->cur_track >> 8) & 0xFF; + disk3_info->iopb[DISK3_IOPB_ARG6] = 0; + disk3_info->iopb[DISK3_IOPB_ARG7] = 0; + + /* Update the DATA field in the IOPB */ + disk3_info->dma_addr += xfr_len; + disk3_info->iopb[DISK3_IOPB_DATA+0] = disk3_info->dma_addr & 0xFF; + disk3_info->iopb[DISK3_IOPB_DATA+1] = (disk3_info->dma_addr >> 8) & 0xFF; + disk3_info->iopb[DISK3_IOPB_DATA+2] = (disk3_info->dma_addr >> 16) & 0xFF; + + break; + } + case DISK3_CODE_FORMAT: + { + uint32 data_len; + uint32 file_offset; + uint8 *fmtBuffer; + + data_len = pDrive->nsectors * pDrive->sectsize; + + TRACE_PRINT(WR_DATA_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " FORMAT T:%d/H:%d/Fill=0x%02x/Len=%d" NLP, + disk3_info->sel_drive, + PCX, + pDrive->track, + disk3_info->iopb[DISK3_IOPB_ARG3], + disk3_info->iopb[DISK3_IOPB_ARG2], + data_len + )); + + file_offset = (pDrive->track * (pDrive->nheads) * data_len); /* Calculate offset based on current track */ + file_offset += (disk3_info->iopb[DISK3_IOPB_ARG3] * data_len); + + fmtBuffer = malloc(data_len); + memset(fmtBuffer, disk3_info->iopb[DISK3_IOPB_ARG2], data_len); + + sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); + fwrite(fmtBuffer, data_len, 1, (pDrive->uptr)->fileref); + + free(fmtBuffer); + + break; + } + case DISK3_CODE_SET_MAP: + break; + case DISK3_CODE_RELOCATE: + case DISK3_CODE_FORMAT_BAD: + case DISK3_CODE_STATUS: + case DISK3_CODE_SELECT: + case DISK3_CODE_EXAMINE: + case DISK3_CODE_MODIFY: + default: + TRACE_PRINT(ERROR_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " CMD=%x Unsupported" NLP, disk3_info->sel_drive, PCX, cmd & DISK3_CMD_MASK)); + break; + } + } else { /* Drive not ready */ + result = DISK3_STATUS_NOT_READY; + } + + /* Return status */ + disk3_info->iopb[DISK3_IOPB_STATUS] = result; + + /* Update IOPB in host memory */ + for(i = 0; i < DISK3_IOPB_LEN; i++) { + PutByteDMA(disk3_info->link_addr + i, disk3_info->iopb[i]); + } + + if(cmd & DISK3_REQUEST_IRQ) { + raise_disk3_interrupt(); + } + disk3_info->link_addr = next_link; + + return 0; +} + +#define SS1_VI1_INT 1 /* DISK2/DISK3 interrupts tied to VI1 */ + +static void raise_disk3_interrupt(void) +{ + TRACE_PRINT(IRQ_MSG, ("DISK3: " ADDRESS_FORMAT " Interrupt" NLP, PCX)); + + raise_ss1_interrupt(SS1_VI1_INT); + +} diff --git a/AltairZ80/s100_fif.c b/AltairZ80/s100_fif.c index 62ddfa8b..0b7e8b1c 100644 --- a/AltairZ80/s100_fif.c +++ b/AltairZ80/s100_fif.c @@ -1,4 +1,4 @@ -/* $Id: s100_fif.c 1773 2008-01-11 05:46:19Z hharte $ +/* $Id: s100_fif.c 1995 2008-07-15 03:59:13Z hharte $ IMSAI FIF Disk Controller by Ernie Price @@ -53,8 +53,6 @@ extern uint8 GetBYTEWrapper(const uint32 Addr); extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); extern uint32 PCX; -extern char messageBuffer[]; -extern void printMessage(void); /* global data on status */ @@ -112,7 +110,7 @@ DEVICE fif_dev = { NULL, NULL, &fif_reset, NULL, NULL, NULL, &fif_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + NULL, NULL, "IMSAI FIF" }; static void resetDSKWarningFlags(void) { @@ -148,7 +146,7 @@ static t_stat fif_reset(DEVICE *dptr) PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; resetDSKWarningFlags(); - current_disk = NUM_OF_DSK; + current_disk = NUM_OF_DSK; if(dptr->flags & DEV_DIS) { sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &fif_io, TRUE); @@ -216,7 +214,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val) if (current_disk >= NUM_OF_DSK) { if (hasVerbose() && (warnDSK11 < warnLevelDSK)) { warnDSK11++; -/*03*/ MESSAGE_2("Attempt disk io on illegal disk %d - ignored.", current_disk + 1); +/*03*/ printf("FIF%i: " ADDRESS_FORMAT " Attempt disk io on illegal disk %d - ignored." NLP, current_disk, PCX, current_disk); } return 0; /* no drive selected - can do nothing */ } @@ -224,7 +222,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val) if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */ if ( (current_disk_flags & UNIT_DSK_VERBOSE) && (warnAttached[current_disk] < warnLevelDSK) ) { warnAttached[current_disk]++; -/*02*/MESSAGE_2("Attempt to select unattached DSK%d - ignored.", current_disk); +/*02*/printf("FIF%i: " ADDRESS_FORMAT " Attempt to select unattached FIF%d - ignored." NLP, current_disk, PCX, current_disk); } current_disk = NUM_OF_DSK; return 2; @@ -240,7 +238,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val) /*Sleep(250); */ memset(blanksec, 0, SEC_SZ); addr = dsc->track * SPT; - fseek(cpx, addr * SEC_SZ, SEEK_SET); + sim_fseek(cpx, addr * SEC_SZ, SEEK_SET); /* write a track worth of sectors */ for (kt=0; kt < SPT; kt++) { @@ -250,7 +248,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val) case READ_SEC: addr = (dsc->track * SPT) + dsc->sector - 1; - fseek(cpx, addr * SEC_SZ, SEEK_SET); + sim_fseek(cpx, addr * SEC_SZ, SEEK_SET); fread(blanksec, 1, SEC_SZ, cpx); addr = dsc->addr_l + (dsc->addr_h << 8); /* no assumption on endianness */ for (kt = 0; kt < SEC_SZ; kt++) { @@ -260,7 +258,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val) case WRITE_SEC: addr = (dsc->track * SPT) + dsc->sector - 1; - fseek(cpx, addr * SEC_SZ, SEEK_SET); + sim_fseek(cpx, addr * SEC_SZ, SEEK_SET); addr = dsc->addr_l + (dsc->addr_h << 8); /* no assumption on endianness */ for (kt = 0; kt < SEC_SZ; kt++) { blanksec[kt] = GetBYTEWrapper(addr++); @@ -280,7 +278,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val) */ static void getdesc(uint16 addr) { - int32 x; + uint32 x; uint8 *p1 = (uint8*)&mydesc; for (x = 0; x < sizeof(mydesc); x++) { @@ -364,9 +362,10 @@ static void xferi(int32 addr, char *dst, int32 lth) } #if !defined (_WIN32) -static void strupr(char *fn) { /* psco added */ +static void strupr(char *fn) { while (*fn) { - if (('a' <= *fn) && (*fn <= 'z')) *fn -= 'a' - 'A'; + if (('a' <= *fn) && (*fn <= 'z')) + *fn -= 'a' - 'A'; fn++; } } diff --git a/AltairZ80/s100_hdc1001.c b/AltairZ80/s100_hdc1001.c new file mode 100644 index 00000000..75cf1fd3 --- /dev/null +++ b/AltairZ80/s100_hdc1001.c @@ -0,0 +1,624 @@ +/************************************************************************* + * * + * $Id: s100_hdc1001.c 1995 2008-07-15 03:59:13Z hharte $ * + * * + * Copyright (c) 2007-2008 Howard M. Harte. * + * http://www.hartetec.com * + * * + * Permission is hereby granted, free of charge, to any person obtaining * + * a copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to * + * the following conditions: * + * * + * The above copyright notice and this permission notice shall be * + * included in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * + * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE 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 Howard M. Harte shall * + * not be used in advertising or otherwise to promote the sale, use or * + * other dealings in this Software without prior written authorization * + * Howard M. Harte. * + * * + * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * + * * + * Module Description: * + * Advanced Digital Corporation (ADC) HDC-1001 Hard Disk Controller * + * module for SIMH. The HDC-1001 controller uses the standard IDE/ATA * + * task-file, so this controller should be compatible with other con- * + * trollers that use IDE, like the GIDE interface. * + * * + * Environment: * + * User mode only * + * * + *************************************************************************/ + +#include "altairz80_defs.h" + +#if defined (_WIN32) +#include +#endif + +#include "sim_imd.h" + +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define VERBOSE_MSG (1 << 7) + +#define HDC1001_MAX_DRIVES 4 + +typedef struct { + UNIT *uptr; + DISK_INFO *imd; + uint16 sectsize; /* sector size, not including pre/postamble */ + uint16 nsectors; /* number of sectors/track */ + uint16 nheads; /* number of heads */ + uint16 ntracks; /* number of tracks */ + uint16 res_tracks; /* Number of reserved tracks on drive. */ + uint16 track; /* Current Track */ + + uint16 cur_sect; /* current starting sector of transfer */ + uint16 cur_track; /* Current Track */ + uint16 xfr_nsects; /* Number of sectors to transfer */ + uint8 ready; /* Is drive ready? */ +} HDC1001_DRIVE_INFO; + +typedef struct { + PNP_INFO pnp; /* Plug and Play */ + uint8 sel_drive; /* Currently selected drive */ + uint8 taskfile[8]; /* ATA Task File Registers */ + uint8 mode; /* mode (0xFF=absolute, 0x00=logical) */ + uint8 retries; /* Number of retries to attempt */ + uint8 ndrives; /* Number of drives attached to the controller */ + + uint32 link_addr; /* Link Address for next IOPB */ + uint32 dma_addr; /* DMA Address for the current IOPB */ + + HDC1001_DRIVE_INFO drive[HDC1001_MAX_DRIVES]; + uint8 iopb[16]; +} HDC1001_INFO; + +static HDC1001_INFO hdc1001_info_data = { { 0x0, 0, 0xC8, 8 } }; +static HDC1001_INFO *hdc1001_info = &hdc1001_info_data; + +extern uint32 PCX; +extern REG *sim_PC; +extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); +extern int32 find_unit_index(UNIT *uptr); + +/* These are needed for DMA. */ +extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); +extern uint8 GetBYTEWrapper(const uint32 Addr); + +#define UNIT_V_HDC1001_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_HDC1001_WLK (1 << UNIT_V_HDC1001_WLK) +#define UNIT_V_HDC1001_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE) +#define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ +#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */ +#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */ +#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */ + +static t_stat hdc1001_reset(DEVICE *hdc1001_dev); +static t_stat hdc1001_attach(UNIT *uptr, char *cptr); +static t_stat hdc1001_detach(UNIT *uptr); + +static int32 hdc1001dev(const int32 port, const int32 io, const int32 data); + +static uint8 HDC1001_Read(const uint32 Addr); +static uint8 HDC1001_Write(const uint32 Addr, uint8 cData); + +static UNIT hdc1001_unit[] = { + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) } +}; + +static REG hdc1001_reg[] = { + { NULL } +}; + +static MTAB hdc1001_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { UNIT_HDC1001_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_HDC1001_WLK, UNIT_HDC1001_WLK, "WRTLCK", "WRTLCK", NULL }, + /* quiet, no warning messages */ + { UNIT_HDC1001_VERBOSE, 0, "QUIET", "QUIET", NULL }, + /* verbose, show warning messages */ + { UNIT_HDC1001_VERBOSE, UNIT_HDC1001_VERBOSE, "VERBOSE", "VERBOSE", NULL }, + { 0 } +}; + +#define TRACE_PRINT(level, args) if(hdc1001_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB hdc1001_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { NULL, 0 } +}; + +DEVICE hdc1001_dev = { + "HDC1001", hdc1001_unit, hdc1001_reg, hdc1001_mod, + HDC1001_MAX_DRIVES, 10, 31, 1, HDC1001_MAX_DRIVES, HDC1001_MAX_DRIVES, + NULL, NULL, &hdc1001_reset, + NULL, &hdc1001_attach, &hdc1001_detach, + &hdc1001_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + hdc1001_dt, NULL, "ADC Hard Disk Controller HDC1001" +}; + +/* Reset routine */ +static t_stat hdc1001_reset(DEVICE *dptr) +{ + PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; + + if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ + sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdc1001dev, TRUE); + } else { + /* Connect HDC1001 at base address */ + if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdc1001dev, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + } + + hdc1001_info->link_addr = 0x50; /* After RESET, the link pointer is at 0x50. */ + + return SCPE_OK; +} + + +/* Attach routine */ +static t_stat hdc1001_attach(UNIT *uptr, char *cptr) +{ + t_stat r = SCPE_OK; + HDC1001_DRIVE_INFO *pDrive; + char header[4]; + unsigned int i = 0; + + i = find_unit_index(uptr); + if (i == -1) { + return (SCPE_IERR); + } + pDrive = &hdc1001_info->drive[i]; + + pDrive->ready = 1; + pDrive->track = 5; + pDrive->ntracks = 243; + pDrive->nheads = 8; + pDrive->nsectors = 11; + pDrive->sectsize = 1024; + + r = attach_unit(uptr, cptr); /* attach unit */ + if ( r != SCPE_OK) /* error? */ + return r; + + /* Determine length of this disk */ + if(sim_fsize(uptr->fileref) != 0) { + uptr->capac = sim_fsize(uptr->fileref); + } else { + uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); + } + + pDrive->uptr = uptr; + + /* Default for new file is DSK */ + uptr->u3 = IMAGE_TYPE_DSK; + + if(uptr->capac > 0) { + fgets(header, 4, uptr->fileref); + if(!strcmp(header, "IMD")) { + uptr->u3 = IMAGE_TYPE_IMD; + } else if(!strcmp(header, "CPT")) { + printf("CPT images not yet supported\n"); + uptr->u3 = IMAGE_TYPE_CPT; + hdc1001_detach(uptr); + return SCPE_OPENERR; + } else { + uptr->u3 = IMAGE_TYPE_DSK; + } + } + + if (uptr->flags & UNIT_HDC1001_VERBOSE) + printf("HDC1001%d, attached to '%s', type=%s, len=%d\n", i, cptr, + uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", + uptr->capac); + + if(uptr->u3 == IMAGE_TYPE_IMD) { + if(uptr->capac < 318000) { + printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); + hdc1001_detach(uptr); + return SCPE_OPENERR; + } + + if (uptr->flags & UNIT_HDC1001_VERBOSE) + printf("--------------------------------------------------------\n"); + hdc1001_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_HDC1001_VERBOSE)); + if (uptr->flags & UNIT_HDC1001_VERBOSE) + printf("\n"); + } else { + hdc1001_info->drive[i].imd = NULL; + } + + return SCPE_OK; +} + + +/* Detach routine */ +t_stat hdc1001_detach(UNIT *uptr) +{ + HDC1001_DRIVE_INFO *pDrive; + t_stat r; + int8 i; + + i = find_unit_index(uptr); + + if (i == -1) { + return (SCPE_IERR); + } + + pDrive = &hdc1001_info->drive[i]; + + pDrive->ready = 0; + + if (uptr->flags & UNIT_HDC1001_VERBOSE) + printf("Detach HDC1001%d\n", i); + + r = detach_unit(uptr); /* detach unit */ + if ( r != SCPE_OK) + return r; + + return SCPE_OK; +} + + +static int32 hdc1001dev(const int32 port, const int32 io, const int32 data) +{ +/* TRACE_PRINT(VERBOSE_MSG, ("HDC1001: " ADDRESS_FORMAT " IO %s, Port %02x" NLP, PCX, io ? "WR" : "RD", port)); */ + if(io) { + HDC1001_Write(port, data); + return 0; + } else { + return(HDC1001_Read(port)); + } +} + +#define HDC1001_CSR 0 /* R=HDC1001 Status / W=HDC1001 Control Register */ +#define HDC1001_DATA 1 /* R=Step Pulse / W=Write Data Register */ + +#define HDC1001_OP_DRIVE 0x00 +#define HDC1001_OP_CYL 0x01 +#define HDC1001_OP_HEAD 0x02 +#define HDC1001_OP_SECTOR 0x03 + +#define HDC1001_CMD_NULL 0x00 +#define HDC1001_CMD_READ_DATA 0x01 +#define HDC1001_CMD_WRITE_DATA 0x02 +#define HDC1001_CMD_WRITE_HEADER 0x03 +#define HDC1001_CMD_READ_HEADER 0x04 + +#define HDC1001_STATUS_BUSY 0 +#define HDC1001_STATUS_RANGE 1 +#define HDC1001_STATUS_NOT_READY 2 +#define HDC1001_STATUS_TIMEOUT 3 +#define HDC1001_STATUS_DAT_CRC 4 +#define HDC1001_STATUS_WR_FAULT 5 +#define HDC1001_STATUS_OVERRUN 6 +#define HDC1001_STATUS_HDR_CRC 7 +#define HDC1001_STATUS_MAP_FULL 8 +#define HDC1001_STATUS_COMPLETE 0xFF /* Complete with No Error */ + +#define HDC1001_CODE_NOOP 0x00 +#define HDC1001_CODE_VERSION 0x01 +#define HDC1001_CODE_GLOBAL 0x02 +#define HDC1001_CODE_SPECIFY 0x03 +#define HDC1001_CODE_SET_MAP 0x04 +#define HDC1001_CODE_HOME 0x05 +#define HDC1001_CODE_SEEK 0x06 +#define HDC1001_CODE_READ_HDR 0x07 +#define HDC1001_CODE_READWRITE 0x08 +#define HDC1001_CODE_RELOCATE 0x09 +#define HDC1001_CODE_FORMAT 0x0A +#define HDC1001_CODE_FORMAT_BAD 0x0B +#define HDC1001_CODE_STATUS 0x0C +#define HDC1001_CODE_SELECT 0x0D +#define HDC1001_CODE_EXAMINE 0x0E +#define HDC1001_CODE_MODIFY 0x0F + +#define HDC1001_IOPB_LEN 16 + +#define TF_DATA 0 +#define TF_ERROR 1 +#define TF_SECNT 2 +#define TF_SECNO 3 +#define TF_CYLLO 4 +#define TF_CYLHI 5 +#define TF_SDH 6 +#define TF_CMD 7 + +static uint8 HDC1001_Write(const uint32 Addr, uint8 cData) +{ +/* uint8 result = HDC1001_STATUS_COMPLETE; */ + + HDC1001_DRIVE_INFO *pDrive; + + pDrive = &hdc1001_info->drive[hdc1001_info->sel_drive]; + + switch(Addr & 0x07) { + case TF_SDH: + hdc1001_info->sel_drive = (cData >> 3) & 0x03; + pDrive = &hdc1001_info->drive[hdc1001_info->sel_drive]; + case TF_DATA: + case TF_ERROR: + case TF_SECNT: + case TF_SECNO: + case TF_CYLLO: + case TF_CYLHI: + hdc1001_info->taskfile[Addr & 0x07] = cData; + TRACE_PRINT(VERBOSE_MSG, ("HDC1001: " ADDRESS_FORMAT " WR TF[%d]=0x%02x" NLP, PCX, Addr & 7, cData)); + break; + case TF_CMD: + pDrive->track = hdc1001_info->taskfile[TF_CYLLO] | (hdc1001_info->taskfile[TF_CYLHI] << 8); + pDrive->xfr_nsects = hdc1001_info->taskfile[TF_SECNT]; + + TRACE_PRINT(CMD_MSG, ("HDC1001[%d]: Command=%d, T:%d/H:%d/S:%d N=%d" NLP, + hdc1001_info->sel_drive, + hdc1001_info->taskfile[TF_CMD], + pDrive->track, + hdc1001_info->taskfile[TF_SDH] & 0x07, + hdc1001_info->taskfile[TF_SECNO], + pDrive->xfr_nsects)); + + break; + default: + break; + } + + + + return 0; +} + +static uint8 HDC1001_Read(const uint32 Addr) +{ + uint8 cData; + + cData = hdc1001_info->taskfile[Addr & 0x07]; + TRACE_PRINT(VERBOSE_MSG, ("HDC1001: " ADDRESS_FORMAT " RD TF[%d]=0x%02x" NLP, PCX, Addr & 7, cData)); + + return (cData); +} + +#if 0 + for(i = 0; i < HDC1001_IOPB_LEN; i++) { + hdc1001_info->iopb[i] = GetBYTEWrapper(hdc1001_info->link_addr + i); + } + + cmd = hdc1001_info->iopb[0]; + hdc1001_info->sel_drive = hdc1001_info->iopb[2]; + + hdc1001_info->dma_addr = hdc1001_info->iopb[0x0A]; + hdc1001_info->dma_addr |= hdc1001_info->iopb[0x0B] << 8; + hdc1001_info->dma_addr |= hdc1001_info->iopb[0x0C] << 16; + + next_link = hdc1001_info->iopb[0x0D]; + next_link |= hdc1001_info->iopb[0x0E] << 8; + next_link |= hdc1001_info->iopb[0x0F] << 16; + + TRACE_PRINT(VERBOSE_MSG, ("HDC1001[%d]: LINK=0x%05x, NEXT=0x%05x, CMD=%x, DMA@0x%05x\n", + hdc1001_info->sel_drive, + hdc1001_info->link_addr, + next_link, + hdc1001_info->iopb[0], + hdc1001_info->dma_addr)); + + + + if(pDrive->ready) { + + /* Perform command */ + switch(cmd) { + case HDC1001_CODE_NOOP: + TRACE_PRINT(VERBOSE_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " NOOP" NLP, hdc1001_info->sel_drive, PCX)); + break; + case HDC1001_CODE_VERSION: + break; + case HDC1001_CODE_GLOBAL: + TRACE_PRINT(CMD_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " GLOBAL" NLP, hdc1001_info->sel_drive, PCX)); + + hdc1001_info->mode = hdc1001_info->iopb[3]; + hdc1001_info->retries = hdc1001_info->iopb[4]; + hdc1001_info->ndrives = hdc1001_info->iopb[5]; + + TRACE_PRINT(VERBOSE_MSG, (" Mode: 0x%02x" NLP, hdc1001_info->mode)); + TRACE_PRINT(VERBOSE_MSG, (" # Retries: 0x%02x" NLP, hdc1001_info->retries)); + TRACE_PRINT(VERBOSE_MSG, (" # Drives: 0x%02x" NLP, hdc1001_info->ndrives)); + + break; + case HDC1001_CODE_SPECIFY: + { + uint8 specify_data[22]; + TRACE_PRINT(CMD_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " SPECIFY" NLP, hdc1001_info->sel_drive, PCX)); + + for(i = 0; i < 22; i++) { + specify_data[i] = GetBYTEWrapper(hdc1001_info->dma_addr + i); + } + + pDrive->sectsize = specify_data[4] | (specify_data[5] << 8); + pDrive->nsectors = specify_data[6] | (specify_data[7] << 8); + pDrive->nheads = specify_data[8] | (specify_data[9] << 8); + pDrive->ntracks = specify_data[10] | (specify_data[11] << 8); + pDrive->res_tracks = specify_data[18] | (specify_data[19] << 8); + + TRACE_PRINT(VERBOSE_MSG, (" Sectsize: %d" NLP, pDrive->sectsize)); + TRACE_PRINT(VERBOSE_MSG, (" Sectors: %d" NLP, pDrive->nsectors)); + TRACE_PRINT(VERBOSE_MSG, (" Heads: %d" NLP, pDrive->nheads)); + TRACE_PRINT(VERBOSE_MSG, (" Tracks: %d" NLP, pDrive->ntracks)); + TRACE_PRINT(VERBOSE_MSG, (" Reserved: %d" NLP, pDrive->res_tracks)); + break; + } + case HDC1001_CODE_HOME: + pDrive->track = 0; + TRACE_PRINT(SEEK_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " HOME" NLP, hdc1001_info->sel_drive, PCX)); + break; + case HDC1001_CODE_SEEK: + pDrive->track = hdc1001_info->iopb[3]; + pDrive->track |= (hdc1001_info->iopb[4] << 8); + + if(pDrive->track > pDrive->ntracks) { + TRACE_PRINT(ERROR_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " SEEK ERROR %d not found" NLP, hdc1001_info->sel_drive, PCX, pDrive->track)); + pDrive->track = pDrive->ntracks - 1; + result = HDC1001_STATUS_TIMEOUT; + } else { + TRACE_PRINT(SEEK_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " SEEK %d" NLP, hdc1001_info->sel_drive, PCX, pDrive->track)); + } + break; + case HDC1001_CODE_READ_HDR: + { + TRACE_PRINT(CMD_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " READ HEADER: %d" NLP, pDrive->track, PCX)); + PutBYTEWrapper(hdc1001_info->dma_addr + 0, pDrive->track & 0xFF); + PutBYTEWrapper(hdc1001_info->dma_addr + 1, (pDrive->track >> 8) & 0xFF); + PutBYTEWrapper(hdc1001_info->dma_addr + 2, 0); + PutBYTEWrapper(hdc1001_info->dma_addr + 3, 1); + + break; + } + case HDC1001_CODE_READWRITE: + { + uint32 track_len; + uint32 xfr_len; + uint32 file_offset; + uint32 xfr_count = 0; + uint8 *dataBuffer; + + pDrive->cur_sect = hdc1001_info->iopb[4] | (hdc1001_info->iopb[5] << 8); + pDrive->cur_track = hdc1001_info->iopb[6] | (hdc1001_info->iopb[7] << 8); + pDrive->xfr_nsects = hdc1001_info->iopb[8] | (hdc1001_info->iopb[9] << 8); + + track_len = pDrive->nsectors * pDrive->sectsize; + + file_offset = (pDrive->cur_track * track_len); /* Calculate offset based on current track */ + file_offset += pDrive->cur_sect + pDrive->sectsize; + + xfr_len = pDrive->xfr_nsects * pDrive->sectsize; + + dataBuffer = malloc(xfr_len); + + sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); + + if(hdc1001_info->iopb[3] == 1) { /* Read */ + TRACE_PRINT(RD_DATA_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " READ @0x%05x T:%04d/S:%04d/#:%d" NLP, + hdc1001_info->sel_drive, + PCX, + hdc1001_info->dma_addr, + pDrive->cur_track, + pDrive->cur_sect, + pDrive->xfr_nsects + )); + + fread(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref); + + /* Perform DMA Transfer */ + for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { + PutBYTEWrapper(hdc1001_info->dma_addr + xfr_count, dataBuffer[xfr_count]); + } + } else { /* Write */ + TRACE_PRINT(WR_DATA_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " WRITE @0x%05x T:%04d/S:%04d/#:%d" NLP, + hdc1001_info->sel_drive, + PCX, + hdc1001_info->dma_addr, + pDrive->cur_track, + pDrive->cur_sect, + pDrive->xfr_nsects + )); + + /* Perform DMA Transfer */ + for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { + dataBuffer[xfr_count] = GetBYTEWrapper(hdc1001_info->dma_addr + xfr_count); + } + + fwrite(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref); + } + + free(dataBuffer); + + break; + } + case HDC1001_CODE_FORMAT: + { + uint32 data_len; + uint32 file_offset; + uint8 *fmtBuffer; + + data_len = pDrive->nsectors * pDrive->sectsize; + + TRACE_PRINT(WR_DATA_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " FORMAT T:%d/H:%d/Fill=0x%02x/Len=%d" NLP, + hdc1001_info->sel_drive, + PCX, + pDrive->track, + hdc1001_info->iopb[5], + hdc1001_info->iopb[4], + data_len + )); + + file_offset = (pDrive->track * (pDrive->nheads) * data_len); /* Calculate offset based on current track */ + file_offset += (hdc1001_info->iopb[5] * data_len); + + fmtBuffer = malloc(data_len); + memset(fmtBuffer, hdc1001_info->iopb[4], data_len); + + sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); + fwrite(fmtBuffer, data_len, 1, (pDrive->uptr)->fileref); + + free(fmtBuffer); + + break; + } + case HDC1001_CODE_SET_MAP: + case HDC1001_CODE_RELOCATE: + case HDC1001_CODE_FORMAT_BAD: + case HDC1001_CODE_STATUS: + case HDC1001_CODE_SELECT: + case HDC1001_CODE_EXAMINE: + case HDC1001_CODE_MODIFY: + default: + TRACE_PRINT(ERROR_MSG, ("HDC1001[%d]: " ADDRESS_FORMAT " CMD=%x Unsupported" NLP, hdc1001_info->sel_drive, PCX, cmd)); + break; + } + } else { /* Drive not ready */ + result = HDC1001_STATUS_NOT_READY; + } + + /* Return status */ + PutBYTEWrapper(hdc1001_info->link_addr + 1, result); + + hdc1001_info->link_addr = next_link; + + return 0; +} +#endif /* 0 */ diff --git a/AltairZ80/s100_if3.c b/AltairZ80/s100_if3.c new file mode 100644 index 00000000..3ca1f9e6 --- /dev/null +++ b/AltairZ80/s100_if3.c @@ -0,0 +1,371 @@ +/************************************************************************* + * * + * $Id: s100_if3.c 1991 2008-07-10 16:06:12Z hharte $ * + * * + * Copyright (c) 2007-2008 Howard M. Harte. * + * http://www.hartetec.com * + * * + * Permission is hereby granted, free of charge, to any person obtaining * + * a copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to * + * the following conditions: * + * * + * The above copyright notice and this permission notice shall be * + * included in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * + * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE 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 Howard M. Harte shall * + * not be used in advertising or otherwise to promote the sale, use or * + * other dealings in this Software without prior written authorization * + * Howard M. Harte. * + * * + * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * + * * + * Module Description: * + * CompuPro System Support 1 module for SIMH. * + * Note this does not include the Boot ROM on the System Support 1 Card * + * * + * Environment: * + * User mode only * + * * + *************************************************************************/ + +/*#define DBG_MSG */ + +#include "altairz80_defs.h" + +#if defined (_WIN32) +#include +#endif + +#include + +#ifdef DBG_MSG +#define DBG_PRINT(args) printf args +#else +#define DBG_PRINT(args) +#endif + +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define TRACE_MSG (1 << 1) +#define RXIRQ_MSG (1 << 2) +#define TXIRQ_MSG (1 << 3) +#define UART_MSG (1 << 4) +#define USER_MSG (1 << 5) + +#define IF3_MAX_BOARDS 4 + +#define UNIT_V_IF3_CONNECT (UNIT_V_UF + 1) /* Connect/Disconnect IF3 unit */ +#define UNIT_IF3_CONNECT (1 << UNIT_V_IF3_CONNECT) + +#define IF3_PORT_BASE 0x300 + +typedef struct { + PNP_INFO pnp; /* Plug and Play */ +} IF3_INFO; + +static IF3_INFO if3_info_data = { { 0x0, 0, 0x10, 8 } }; + +extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), uint8 unmap); +extern uint32 PCX; + +extern int32 sio0d(const int32 port, const int32 io, const int32 data); +extern int32 sio0s(const int32 port, const int32 io, const int32 data); + +static t_stat set_if3_connect(UNIT *uptr, int32 val, char *cptr, void *desc); + +static t_stat if3_reset(DEVICE *if3_dev); +static t_stat if3_svc (UNIT *uptr); +static uint8 IF3_Read(const uint32 Addr); +static uint8 IF3_Write(const uint32 Addr, uint8 cData); +static int32 if3dev(const int32 port, const int32 io, const int32 data); +static t_stat update_rx_tx_isr (UNIT *uptr); + +static UNIT if3_unit[] = { + { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE | UNIT_IF3_CONNECT, 0) }, + { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, + { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, + { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) } +}; + +static uint8 if3_user = 0; +static uint8 if3_board = 0; +static uint8 if3_rimr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; +static uint8 if3_timr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; +static uint8 if3_risr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; +static uint8 if3_tisr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; + +static REG if3_reg[] = { + { HRDATA (USER, if3_user, 3), }, + { HRDATA (BOARD, if3_board, 2), }, + { BRDATA (RIMR, &if3_rimr[0], 16, 8, 4), }, + { BRDATA (RISR, &if3_risr[0], 16, 8, 4), }, + { BRDATA (TIMR, &if3_timr[0], 16, 8, 4), }, + { BRDATA (TISR, &if3_tisr[0], 16, 8, 4), }, + { NULL } +}; + +static MTAB if3_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { UNIT_IF3_CONNECT, UNIT_IF3_CONNECT,"INSTALLED", "INSTALLED", &set_if3_connect, NULL, NULL }, + { UNIT_IF3_CONNECT, 0, "UNINSTALLED","UNINSTALLED", &set_if3_connect, NULL, NULL }, + { 0 } +}; + +#define TRACE_PRINT(level, args) if(if3_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB if3_dt[] = { + { "ERROR", ERROR_MSG }, + { "TRACE", TRACE_MSG }, + { "RXIRQ", RXIRQ_MSG }, + { "TXIRQ", TXIRQ_MSG }, + { "UART", UART_MSG }, + { "USER", USER_MSG }, + { NULL, 0 } +}; + +DEVICE if3_dev = { + "IF3", if3_unit, if3_reg, if3_mod, + IF3_MAX_BOARDS, 10, 31, 1, IF3_MAX_BOARDS, IF3_MAX_BOARDS, + NULL, NULL, &if3_reset, + NULL, NULL, NULL, + &if3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0, + if3_dt, NULL, "Compupro Interfacer 3 IF3" +}; + +static t_stat set_if3_connect(UNIT *uptr, int32 val, char *cptr, void *desc) +{ + if(uptr->flags & UNIT_DISABLE) { + TRACE_PRINT(ERROR_MSG, ("IF3[%d]: not enabled." NLP, uptr->u3)); + return SCPE_OK; + } + + if(val & UNIT_IF3_CONNECT) { + TRACE_PRINT((RXIRQ_MSG|TXIRQ_MSG), ("IF3[%d]: IRQ polling started..." NLP, uptr->u3)); + sim_activate(uptr, 100000); + } else { + TRACE_PRINT((RXIRQ_MSG|TXIRQ_MSG), ("IF3[%d]: IRQ polling stopped." NLP, uptr->u3)); + sim_cancel(uptr); + } + return (SCPE_OK); +} + +/* Reset routine */ +static t_stat if3_reset(DEVICE *dptr) +{ + uint8 i; + + PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; + + if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ + for(i=0;iio_base, pnp->io_size, RESOURCE_TYPE_IO, &if3dev, TRUE); + } else { + /* Connect IF3 at base address */ + if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &if3dev, FALSE) != 0) { + printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + + for(i=0;i> 3; /* guarantees that if3_board < IF3_MAX_BOARDS */ + if3_user = cData & 0x7; + TRACE_PRINT(USER_MSG, ("IF3[%d]: " ADDRESS_FORMAT " WR UART_SEL=0x%02x (Board=%d, Rel_User=%d, User=%d)" NLP, + if3_board, PCX, cData, if3_board, if3_user, cData)); + break; + } + + return(0); +} + +#define SS1_VI2_INT 2 /* IF3 Rx interrupts tied to VI2 */ +#define SS1_VI3_INT 3 /* IF3 Tx interrupts tied to VI3 */ + +#define IF3_NUM_PORTS 8 /* Number of ports per IF3 board */ + +extern void raise_ss1_interrupt(uint8 isr_index); + +/* Unit service routine */ +static t_stat if3_svc (UNIT *uptr) +{ + uint8 pending_rx_irqs; + uint8 pending_tx_irqs; + uint8 board = uptr->u3; + + update_rx_tx_isr(uptr); + + pending_rx_irqs = if3_risr[board] & if3_rimr[board]; + if(pending_rx_irqs) { + TRACE_PRINT(RXIRQ_MSG, ("IF3[%d]: " ADDRESS_FORMAT " Rx IRQ Pending: 0x%02x" NLP, board, PCX, pending_rx_irqs)); + raise_ss1_interrupt(SS1_VI2_INT); + } + + pending_tx_irqs = if3_tisr[board] & if3_timr[board]; + if(pending_tx_irqs) { + TRACE_PRINT(TXIRQ_MSG, ("IF3[%d]: " ADDRESS_FORMAT " Tx IRQ Pending: 0x%02x" NLP, board, PCX, pending_tx_irqs)); + raise_ss1_interrupt(SS1_VI3_INT); + } + + sim_activate(&if3_unit[board], 200000); + return SCPE_OK; +} + + +static t_stat update_rx_tx_isr (UNIT *uptr) +{ + uint8 i; + uint8 cData; + uint8 board = uptr->u3; + + if3_risr[board] = 0; + if3_tisr[board] = 0; + + for(i=0;i #endif -#include "sim_imd.h" - #ifdef DBG_MSG #define DBG_PRINT(args) printf args #else #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define ORDERS_MSG 0x02 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 -#define RD_DATA_DETAIL_MSG 0x40 -#define WR_DATA_DETAIL_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define ORDERS_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) +#define RD_DATA_DETAIL_MSG (1 << 8) +#define WR_DATA_DETAIL_MSG (1 << 9) extern uint32 PCX; extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); @@ -90,7 +91,6 @@ typedef union { typedef struct { UNIT *uptr; - DISK_INFO *imd; uint8 track; uint8 wp; /* Disk write protected */ uint8 sector; /* Current Sector number */ @@ -161,7 +161,6 @@ static SECTOR_FORMAT sdata; #define UNIT_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE) #define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */ #define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */ -#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */ #define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */ /* MDS-AD Controller Subcases */ @@ -223,8 +222,6 @@ static uint8 MDSAD_Read(const uint32 Addr); static int32 mdsaddev(const int32 Addr, const int32 rw, const int32 data); -static int32 trace_level = 0; - static UNIT mdsad_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MDSAD_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MDSAD_CAPACITY) }, @@ -233,7 +230,6 @@ static UNIT mdsad_unit[] = { }; static REG mdsad_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, { NULL } }; @@ -248,13 +244,32 @@ static MTAB mdsad_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if(mdsad_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB mdsad_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "ORDERS", ORDERS_MSG }, + { "RDDETAIL", RD_DATA_DETAIL_MSG }, + { "WRDETAIL", WR_DATA_DETAIL_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { NULL, 0 } +}; + DEVICE mdsad_dev = { "MDSAD", mdsad_unit, mdsad_reg, mdsad_mod, MDSAD_MAX_DRIVES, 10, 31, 1, MDSAD_MAX_DRIVES, MDSAD_MAX_DRIVES, NULL, NULL, &mdsad_reset, &mdsad_boot, &mdsad_attach, &mdsad_detach, - &mdsad_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &mdsad_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + mdsad_dt, NULL, "North Star Floppy Controller MDSAD" }; /* Reset routine */ @@ -311,9 +326,7 @@ t_stat mdsad_attach(UNIT *uptr, char *cptr) if(uptr->capac > 0) { fgets(header, 4, uptr->fileref); - if(!strcmp(header, "IMD")) { - uptr->u3 = IMAGE_TYPE_IMD; - } else if(!strcmp(header, "CPT")) { + if(!strcmp(header, "CPT")) { printf("CPT images not yet supported\n"); uptr->u3 = IMAGE_TYPE_CPT; mdsad_detach(uptr); @@ -325,25 +338,9 @@ t_stat mdsad_attach(UNIT *uptr, char *cptr) if (uptr->flags & UNIT_MDSAD_VERBOSE) printf("MDSAD%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", + uptr->u3 == uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", uptr->capac); - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - mdsad_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_MDSAD_VERBOSE) - printf("--------------------------------------------------------\n"); - mdsad_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_MDSAD_VERBOSE)); - if (uptr->flags & UNIT_MDSAD_VERBOSE) - printf("\n"); - } else { - mdsad_info->drive[i].imd = NULL; - } - return SCPE_OK; } @@ -360,16 +357,16 @@ t_stat mdsad_detach(UNIT *uptr) } } - if (i >= MDSAD_MAX_DRIVES) return SCPE_ARG; + if (i >= MDSAD_MAX_DRIVES) + return SCPE_ARG; DBG_PRINT(("Detach MDSAD%d\n", i)); - diskClose(mdsad_info->drive[i].imd); r = detach_unit(uptr); /* detach unit */ if(r != SCPE_OK) return r; - mdsad_dev.units[i].fileref = NULL; /* psco check if ok */ + mdsad_dev.units[i].fileref = NULL; return SCPE_OK; } @@ -428,7 +425,8 @@ static void showdata(int32 isRead) { printf("MDSAD: " ADDRESS_FORMAT " %s Sector =" NLP "\t", PCX, isRead ? "Read" : "Write"); for(i=0; i < MDSAD_SECTOR_LEN; i++) { printf("%02X ", sdata.u.data[i]); - if(((i+1) & 0xf) == 0) printf(NLP "\t"); + if(((i+1) & 0xf) == 0) + printf(NLP "\t"); } printf(NLP); } @@ -436,6 +434,17 @@ static void showdata(int32 isRead) { static int checksum; static uint32 sec_offset; +static uint32 calculate_mdsad_sec_offset(uint8 track, uint8 head, uint8 sector) +{ + if(mdsad_info->orders.ss == 0) { + return ((track * (MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK)) + (sector * MDSAD_SECTOR_LEN)); + } else { + return ((((MDSAD_TRACKS-1) - track) * (MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK)) + + ((MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK) * MDSAD_TRACKS) + /* Skip over side 0 */ + (sector * MDSAD_SECTOR_LEN)); /* Sector offset from beginning of track. */ + } +} + static uint8 MDSAD_Read(const uint32 Addr) { uint8 cData; @@ -452,9 +461,6 @@ static uint8 MDSAD_Read(const uint32 Addr) break; case MDSAD_WRITE_DATA: { - unsigned int flags = 0; - unsigned int writelen; - if(mdsad_info->datacount == 0) { TRACE_PRINT(WR_DATA_MSG, ("MDSAD: " ADDRESS_FORMAT " WRITE Start: Drive: %d, Track=%d, Head=%d, Sector=%d" NLP, @@ -464,9 +470,9 @@ static uint8 MDSAD_Read(const uint32 Addr) mdsad_info->orders.ss, pDrive->sector)); - sec_offset = (pDrive->track * (MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK)) + - (mdsad_info->orders.ss * ((MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK) * MDSAD_TRACKS)) + - (pDrive->sector * MDSAD_SECTOR_LEN); + sec_offset = calculate_mdsad_sec_offset(pDrive->track, + mdsad_info->orders.ss, + pDrive->sector); } @@ -487,27 +493,15 @@ static uint8 MDSAD_Read(const uint32 Addr) PCX, mdsad_info->orders.ds)); return 0x00; } - if(trace_level & WR_DATA_DETAIL_MSG) showdata(FALSE); + if(mdsad_dev.dctrl & WR_DATA_DETAIL_MSG) + showdata(FALSE); switch((pDrive->uptr)->u3) { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } - sectWrite(pDrive->imd, - pDrive->track, - mdsad_info->orders.ss, - pDrive->sector, - sdata.u.data, - MDSAD_SECTOR_LEN, - &flags, - &writelen); - break; case IMAGE_TYPE_DSK: if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { - fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); fwrite(sdata.u.data, MDSAD_SECTOR_LEN, 1, (pDrive->uptr)->fileref); } @@ -546,6 +540,11 @@ static uint8 MDSAD_Read(const uint32 Addr) break; } + if(mdsad_info->orders.ds != (mdsad_info->orders.ds & 0x03)) { + TRACE_PRINT(ERROR_MSG, ("MDSAD: " ADDRESS_FORMAT + " Controller Orders update drive %x" NLP, PCX, mdsad_info->orders.ds)); + mdsad_info->orders.ds &= 0x03; + } TRACE_PRINT(ORDERS_MSG, ("MDSAD: " ADDRESS_FORMAT " Controller Orders: Drive=%x[%x], DD=%d, SS=%d, DP=%d, ST=%d" NLP, PCX, @@ -705,9 +704,6 @@ static uint8 MDSAD_Read(const uint32 Addr) break; case MDSAD_READ_DATA: /* READ DATA */ { - unsigned int flags; - unsigned int readlen; - if(mdsad_info->datacount == 0) { TRACE_PRINT(RD_DATA_MSG, ("MDSAD: " ADDRESS_FORMAT " READ Start: Drive: %d, Track=%d, Head=%d, Sector=%d" NLP, @@ -719,9 +715,9 @@ static uint8 MDSAD_Read(const uint32 Addr) checksum = 0; - sec_offset = (pDrive->track * (MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK)) + - (mdsad_info->orders.ss * ((MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK) * MDSAD_TRACKS)) + - (pDrive->sector * MDSAD_SECTOR_LEN); + sec_offset = calculate_mdsad_sec_offset(pDrive->track, + mdsad_info->orders.ss, + pDrive->sector); if ((pDrive->uptr == NULL) || (pDrive->uptr->fileref == NULL)) { @@ -733,25 +729,11 @@ static uint8 MDSAD_Read(const uint32 Addr) switch((pDrive->uptr)->u3) { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } -/* DBG_PRINT(("%s: Read: imd=%p" NLP, __FUNCTION__, mdsad_info->drive[mdsad_info->sel_drive].imd)); */ - sectRead(pDrive->imd, - pDrive->track, - mdsad_info->orders.ss, - pDrive->sector, - sdata.u.data, - MDSAD_SECTOR_LEN, - &flags, - &readlen); - break; case IMAGE_TYPE_DSK: if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { - fseek((pDrive->uptr)->fileref, + sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); fread(&sdata.u.data[0], MDSAD_SECTOR_LEN, 1, (pDrive->uptr)->fileref); @@ -766,10 +748,11 @@ static uint8 MDSAD_Read(const uint32 Addr) NLP, __FUNCTION__); break; } - if(trace_level & RD_DATA_DETAIL_MSG) showdata(TRUE); + if(mdsad_dev.dctrl & RD_DATA_DETAIL_MSG) + showdata(TRUE); } - if(mdsad_info->datacount < 0x200) { + if(mdsad_info->datacount < MDSAD_SECTOR_LEN) { cData = sdata.u.data[mdsad_info->datacount]; /* Exclusive OR */ diff --git a/AltairZ80/s100_scp300f.c b/AltairZ80/s100_scp300f.c index e6b7d0b4..1aaa35eb 100644 --- a/AltairZ80/s100_scp300f.c +++ b/AltairZ80/s100_scp300f.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: s100_scp300f.c 1902 2008-05-11 02:40:41Z hharte $ * + * $Id: s100_scp300f.c 1940 2008-06-13 05:28:57Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -53,19 +53,24 @@ #define DBG_PRINT(args) #endif -#define PIO_MSG 0x01 -#define UART_MSG 0x02 -#define RTC_MSG 0x04 -#define MPCL_MSG 0x08 -#define ROM_MSG 0x10 -#define TRACE_MSG 0x80 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define PIO_MSG (1 << 1) +#define UART_MSG (1 << 2) +#define RTC_MSG (1 << 3) +#define ROM_MSG (1 << 5) +#define VERBOSE_MSG (1 << 7) +#define IRQ_MSG (1 << 8) -#define SCP300F_MAX_DRIVES 1 -#define SCP300F_ROM_SIZE (2048) -#define SCP300F_ADDR_MASK (SCP300F_ROM_SIZE - 1) +#define SCP300F_MAX_DRIVES 1 +#define SCP300F_ROM_SIZE (2048) +#define SCP300F_ADDR_MASK (SCP300F_ROM_SIZE - 1) -#define UNIT_V_SCP300F_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_SCP300F_VERBOSE (1 << UNIT_V_SCP300F_VERBOSE) +#define SCP300F_IO_SIZE (16) +#define SCP300F_IO_MASK (SCP300F_IO_SIZE - 1) + +#define UNIT_V_SCP300F_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_SCP300F_VERBOSE (1 << UNIT_V_SCP300F_VERBOSE) typedef struct { PNP_INFO pnp; /* Plug and Play */ @@ -74,7 +79,7 @@ typedef struct { uint8 rom_enabled; } SCP300F_INFO; -static SCP300F_INFO scp300f_info_data = { { 0xFF800, SCP300F_ROM_SIZE, 0xF0, 16 } }; +static SCP300F_INFO scp300f_info_data = { { 0xFF800, SCP300F_ROM_SIZE, 0xF0, SCP300F_IO_SIZE } }; static SCP300F_INFO *scp300f_info = &scp300f_info_data; extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); @@ -84,7 +89,6 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, int32 (*routine)(const int32, const int32, const int32), uint8 unmap); extern uint32 PCX; -extern REG *sim_PC; extern int32 find_unit_index (UNIT *uptr); static t_stat scp300f_reset(DEVICE *scp300f_dev); @@ -95,36 +99,51 @@ static uint8 SCP300F_Write(const uint32 Addr, uint8 cData); static int32 scp300fdev(const int32 port, const int32 io, const int32 data); static int32 scp300f_mem(const int32 port, const int32 io, const int32 data); -static int32 trace_level = 0x00; /* Disable all tracing by default */ -static int32 scp300f_sr = 0x00; /* Sense Switch Register */ +static int32 scp300f_sr = 0x00; /* Sense Switch Register, 0=Monitor prompt, 1=disk boot */ static UNIT scp300f_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_DISABLE, 0) } }; static REG scp300f_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, { HRDATA (SR, scp300f_sr, 8), }, { NULL } }; static MTAB scp300f_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, /* quiet, no warning messages */ - { UNIT_SCP300F_VERBOSE, 0, "QUIET", "QUIET", NULL }, + { UNIT_SCP300F_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* verbose, show warning messages */ { UNIT_SCP300F_VERBOSE, UNIT_SCP300F_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if(scp300f_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB scp300f_dt[] = { + { "ERROR", ERROR_MSG }, + { "PIO", PIO_MSG }, + { "UART", UART_MSG }, + { "RTC", RTC_MSG }, + { "ROM", ROM_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "IRQ", IRQ_MSG }, + { NULL, 0 } +}; + + DEVICE scp300f_dev = { "SCP300F", scp300f_unit, scp300f_reg, scp300f_mod, SCP300F_MAX_DRIVES, 10, 31, 1, SCP300F_MAX_DRIVES, SCP300F_MAX_DRIVES, NULL, NULL, &scp300f_reset, NULL, NULL, NULL, - &scp300f_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &scp300f_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + scp300f_dt, NULL, "SCP Support Board SCP300F" }; /* Reset routine */ @@ -132,7 +151,7 @@ static t_stat scp300f_reset(DEVICE *dptr) { PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - TRACE_PRINT(TRACE_MSG, ("SCP300F: Reset." NLP)); + TRACE_PRINT(VERBOSE_MSG, ("SCP300F: Reset." NLP)); if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &scp300fdev, TRUE); @@ -163,6 +182,7 @@ static uint8 scp300f_ram[SCP300F_ROM_SIZE]; * ; This software is not copyrighted. * * This was assembled from source (MON.ASM) using 86DOS ASM.COM running under Windows XP. + * It is configured for a Cromemco 16FDC disk controller. */ static uint8 scp300f_rom[SCP300F_ROM_SIZE] = { 0xFC, 0x33, 0xC0, 0x8E, 0xD0, 0x8E, 0xD8, 0x8E, 0xC0, 0xBF, 0x9C, 0x01, 0xB9, 0x0E, 0x00, 0xF3, @@ -285,14 +305,14 @@ static uint8 scp300f_rom[SCP300F_ROM_SIZE] = { 0x37, 0x0D, 0x0A, 0x0A, 0x53, 0x43, 0x50, 0x20, 0x38, 0x30, 0x38, 0x36, 0x20, 0x4D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x20, 0x31, 0x2E, 0x35, 0x0D, 0x8A, 0x5E, 0x20, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x8A, 0x08, 0x20, 0x88, 0x57, 0xB0, 0x01, 0xE6, 0x02, 0xB0, 0x84, 0xE6, 0x00, 0xB0, - 0x7F, 0xE6, 0x04, 0xB6, 0x21, 0xB0, 0xD0, 0xE6, 0x30, 0xD4, 0x0A, 0xD4, 0x0A, 0xD4, 0x0A, 0xD4, - 0x0A, 0x80, 0xF6, 0x10, 0x8A, 0xC6, 0xE6, 0x34, 0xBF, 0x00, 0x02, 0xB0, 0x0F, 0xE6, 0x30, 0xE4, - 0x34, 0xD0, 0xC8, 0x73, 0xFA, 0xE4, 0x30, 0x24, 0x98, 0x75, 0xDA, 0xB0, 0x01, 0xE6, 0x32, 0x8A, - 0xC6, 0x0C, 0x80, 0xE6, 0x34, 0xB2, 0x33, 0xB0, 0x8C, 0xE6, 0x30, 0xEB, 0x02, 0xEC, 0xAA, 0xE4, - 0x34, 0xD0, 0xC8, 0x73, 0xF8, 0xE4, 0x30, 0x24, 0x9C, 0x75, 0xBA, 0xC7, 0x06, 0xB2, 0x01, 0x00, - 0x00, 0xC7, 0x06, 0xB4, 0x01, 0x00, 0x02, 0x5F, 0xE9, 0x8F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0x00, 0x80, 0xFF, 0x0D, 0x00, 0x68, 0x00, 0xA0, 0x01, 0x40, 0x03, 0x78, 0x04, 0x00 + 0x7F, 0xE6, 0x04, 0xB6, 0x21, 0xB0, 0x30, 0xE6, 0x34, 0xB9, 0xC4, 0xAA, 0xD4, 0x0A, 0xD4, 0x0A, + 0xE2, 0xFA, 0xB0, 0xD0, 0xE6, 0x30, 0xD4, 0x0A, 0xD4, 0x0A, 0xD4, 0x0A, 0xD4, 0x0A, 0x80, 0xF6, + 0x10, 0x8A, 0xC6, 0xE6, 0x34, 0xBF, 0x00, 0x02, 0xB0, 0x0F, 0xE6, 0x30, 0xE4, 0x34, 0xD0, 0xC8, + 0x73, 0xFA, 0xE4, 0x30, 0x24, 0x98, 0x75, 0xDA, 0xB0, 0x01, 0xE6, 0x32, 0x8A, 0xC6, 0x0C, 0x80, + 0xE6, 0x34, 0xB2, 0x33, 0xB0, 0x8C, 0xE6, 0x30, 0xEB, 0x02, 0xEC, 0xAA, 0xE4, 0x34, 0xD0, 0xC8, + 0x73, 0xF8, 0xE4, 0x30, 0x24, 0x9C, 0x75, 0xBA, 0xC7, 0x06, 0xB2, 0x01, 0x00, 0x00, 0xC7, 0x06, + 0xB4, 0x01, 0x00, 0x02, 0x5F, 0xE9, 0x82, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x80, 0xFF, 0x0D, 0x00, 0x68, 0x00, 0xA0, 0x01, 0x40, 0x03, 0x78, 0x04, 0xFF }; static int32 scp300f_mem(const int32 Addr, const int32 write, const int32 data) @@ -347,7 +367,7 @@ static uint8 SCP300F_Read(const uint32 Addr) { uint8 cData = 0xFF; - switch(Addr & 0xF) { + switch(Addr & SCP300F_IO_MASK) { case SCP300F_MPIC_0: case SCP300F_MPIC_1: TRACE_PRINT(UART_MSG, ("SCP300F: " ADDRESS_FORMAT " Master 8259 DATA RD[%02x]: not implemented." NLP, PCX, Addr)); @@ -364,7 +384,7 @@ static uint8 SCP300F_Read(const uint32 Addr) break; case SCP300F_UART_DATA: /* UART is handled by the 2SIO, if this gets called, then the 2SIO was not */ case SCP300F_UART_STATUS: /* configured properly. */ - TRACE_PRINT(TRACE_MSG, ("SCP300F: " ADDRESS_FORMAT " RD[%02x]: UART not configured properly." NLP, PCX, Addr)); + TRACE_PRINT(VERBOSE_MSG, ("SCP300F: " ADDRESS_FORMAT " RD[%02x]: UART not configured properly." NLP, PCX, Addr)); break; case SCP300F_PIO_DATA: TRACE_PRINT(UART_MSG, ("SCP300F: " ADDRESS_FORMAT " PIO DATA RD[%02x]: not implemented." NLP, PCX, Addr)); @@ -372,11 +392,16 @@ static uint8 SCP300F_Read(const uint32 Addr) case SCP300F_PIO_STATUS: TRACE_PRINT(UART_MSG, ("SCP300F: " ADDRESS_FORMAT " PIO STATUS RD[%02x]: not implemented." NLP, PCX, Addr)); break; + case SCP300F_EPROM_DIS: + TRACE_PRINT(ROM_MSG, ("SCP300F: " ADDRESS_FORMAT " EPROM DIS RD: EPROM Disabled." NLP, PCX)); + scp300f_info->rom_enabled = 0; + break; case SCP300F_SENSE_SW: /* Sense Switch */ cData = scp300f_sr; + TRACE_PRINT(VERBOSE_MSG, ("SCP300F: " ADDRESS_FORMAT " RD: Sense Switch=0x%02x" NLP, PCX, cData)); break; default: - TRACE_PRINT(TRACE_MSG, ("SCP300F: " ADDRESS_FORMAT " RD[%02x]: not Implemented." NLP, PCX, Addr)); + TRACE_PRINT(VERBOSE_MSG, ("SCP300F: " ADDRESS_FORMAT " RD[%02x]: not Implemented." NLP, PCX, Addr)); break; } @@ -387,7 +412,7 @@ static uint8 SCP300F_Read(const uint32 Addr) static uint8 SCP300F_Write(const uint32 Addr, uint8 cData) { - switch(Addr & 0xF) { + switch(Addr & SCP300F_IO_MASK) { case SCP300F_MPIC_0: case SCP300F_MPIC_1: TRACE_PRINT(UART_MSG, ("SCP300F: " ADDRESS_FORMAT " Master 8259 DATA WR[%02x]=%02x: not implemented." NLP, PCX, Addr, cData)); @@ -412,11 +437,15 @@ static uint8 SCP300F_Write(const uint32 Addr, uint8 cData) case SCP300F_PIO_STATUS: TRACE_PRINT(UART_MSG, ("SCP300F: " ADDRESS_FORMAT " WR[%02x]: Cannot write to PIO STATUS." NLP, PCX, Addr)); break; + case SCP300F_EPROM_DIS: + TRACE_PRINT(ROM_MSG, ("SCP300F: " ADDRESS_FORMAT " EPROM DIS WR: EPROM Disabled." NLP, PCX)); + scp300f_info->rom_enabled = 0; + break; case SCP300F_SENSE_SW: - TRACE_PRINT(UART_MSG, ("SCP300F: " ADDRESS_FORMAT " WR[%02x]: Cannot write to SR." NLP, PCX, Addr)); + TRACE_PRINT(VERBOSE_MSG, ("SCP300F: " ADDRESS_FORMAT " WR[%02x]: Cannot write to SR." NLP, PCX, Addr)); break; default: - TRACE_PRINT(TRACE_MSG, ("SCP300F: " ADDRESS_FORMAT " WR[0x%02x]=0x%02x: not Implemented." NLP, PCX, Addr, cData)); + TRACE_PRINT(VERBOSE_MSG, ("SCP300F: " ADDRESS_FORMAT " WR[0x%02x]=0x%02x: not Implemented." NLP, PCX, Addr, cData)); break; } diff --git a/AltairZ80/s100_selchan.c b/AltairZ80/s100_selchan.c index 09c508ae..b9a312cd 100644 --- a/AltairZ80/s100_selchan.c +++ b/AltairZ80/s100_selchan.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: s100_selchan.c 1771 2008-01-09 07:10:46Z hharte $ * + * $Id: s100_selchan.c 1995 2008-07-15 03:59:13Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -53,13 +53,15 @@ #define DBG_PRINT(args) #endif -#define TRACE_MSG 0x01 -#define DMA_MSG 0x02 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define VERBOSE_MSG (1 << 1) +#define DMA_MSG (1 << 2) -#define SELCHAN_MAX_DRIVES 1 +#define SELCHAN_MAX_DRIVES 1 -#define UNIT_V_SELCHAN_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_SELCHAN_VERBOSE (1 << UNIT_V_SELCHAN_VERBOSE) +#define UNIT_V_SELCHAN_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_SELCHAN_VERBOSE (1 << UNIT_V_SELCHAN_VERBOSE) typedef struct { PNP_INFO pnp; /* Plug and Play */ @@ -78,24 +80,23 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, int32 (*routine)(const int32, const int32, const int32), uint8 unmap); extern uint32 PCX; -extern REG *sim_PC; -/* These are needed for DMA. PIO Mode has not been implemented yet. */ -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); +/* These are needed for DMA. */ +extern void PutByteDMA(const uint32 Addr, const uint32 Value); +extern uint8 GetByteDMA(const uint32 Addr); static t_stat selchan_reset(DEVICE *selchan_dev); static int32 selchandev(const int32 port, const int32 io, const int32 data); -static int32 trace_level = 0; /* Disable all tracing by default */ static UNIT selchan_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ROABLE, 0) } }; static REG selchan_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, + { HRDATA (DMA_MODE, selchan_info_data.dma_mode, 8), }, + { HRDATA (DMA_ADDR, selchan_info_data.dma_addr, 24), }, { NULL } }; @@ -108,13 +109,25 @@ static MTAB selchan_mod[] = { { 0 } }; +#define TRACE_PRINT(level, args) if(selchan_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB selchan_dt[] = { + { "ERROR", ERROR_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { "DMA", DMA_MSG }, + { NULL, 0 } +}; + DEVICE selchan_dev = { "SELCHAN", selchan_unit, selchan_reg, selchan_mod, SELCHAN_MAX_DRIVES, 10, 31, 1, SELCHAN_MAX_DRIVES, SELCHAN_MAX_DRIVES, NULL, NULL, &selchan_reset, NULL, NULL, NULL, - &selchan_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &selchan_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + selchan_dt, NULL, "Compupro Selector Channel SELCHAN" }; /* Reset routine */ @@ -154,7 +167,7 @@ static int32 selchandev(const int32 port, const int32 io, const int32 data) selchan_info->reg_cnt ++; if(selchan_info->reg_cnt == 4) { - TRACE_PRINT(TRACE_MSG, ("SELCHAN: " ADDRESS_FORMAT " DMA=0x%06x, Mode=0x%02x (%s, %s, %s)" NLP, + TRACE_PRINT(VERBOSE_MSG, ("SELCHAN: " ADDRESS_FORMAT " DMA=0x%06x, Mode=0x%02x (%s, %s, %s)" NLP, PCX, selchan_info->dma_addr, selchan_info->dma_mode, @@ -165,7 +178,7 @@ static int32 selchandev(const int32 port, const int32 io, const int32 data) return 0; } else { - TRACE_PRINT(TRACE_MSG, ("SELCHAN: " ADDRESS_FORMAT " Reset" NLP, PCX)); + TRACE_PRINT(VERBOSE_MSG, ("SELCHAN: " ADDRESS_FORMAT " Reset" NLP, PCX)); selchan_info->reg_cnt = 0; return(0xFF); } @@ -191,9 +204,9 @@ int32 selchan_dma(uint8 *buf, uint32 len) (selchan_info->dma_mode & SELCHAN_MODE_WRITE) ? "WR" : "RD", len)); for(i=0;idma_mode & SELCHAN_MODE_WRITE) { - PutBYTEWrapper(selchan_info->dma_addr + i, buf[i]); + PutByteDMA(selchan_info->dma_addr + i, buf[i]); } else { - buf[i] = GetBYTEWrapper(selchan_info->dma_addr + i); + buf[i] = GetByteDMA(selchan_info->dma_addr + i); } } diff --git a/AltairZ80/s100_ss1.c b/AltairZ80/s100_ss1.c index 39b93879..7a92b0a4 100644 --- a/AltairZ80/s100_ss1.c +++ b/AltairZ80/s100_ss1.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: s100_ss1.c 1773 2008-01-11 05:46:19Z hharte $ * + * $Id: s100_ss1.c 1997 2008-07-18 05:29:52Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -48,72 +48,189 @@ #include #endif +#include + #ifdef DBG_MSG #define DBG_PRINT(args) printf args #else #define DBG_PRINT(args) #endif -#define TRACE_MSG 0x01 -#define DMA_MSG 0x02 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define TRACE_MSG (1 << 1) +#define PIC_MSG (1 << 2) +#define TC_MSG (1 << 3) +#define RTC_MSG (1 << 4) +#define MATH_MSG (1 << 5) +#define UART_MSG (1 << 6) +#define IRQ_MSG (1 << 7) -#define SS1_MAX_DRIVES 1 - -#define UNIT_V_SS1_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_SS1_VERBOSE (1 << UNIT_V_SS1_VERBOSE) +#define SS1_MAX_TIMERS 3 typedef struct { PNP_INFO pnp; /* Plug and Play */ } SS1_INFO; -static SS1_INFO ss1_info_data = { { 0x0, 0, 0x50, 12 } }; -/* static SS1_INFO *ss1_info = &ss1_info_data;*/ +static SS1_INFO ss1_info_data = { { 0x0, 0, 0x50, 16 } }; extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, int32 (*routine)(const int32, const int32, const int32), uint8 unmap); extern uint32 PCX; -extern REG *sim_PC; - -/* These are needed for DMA. PIO Mode has not been implemented yet. */ -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); static t_stat ss1_reset(DEVICE *ss1_dev); +static t_stat ss1_svc (UNIT *uptr); static uint8 SS1_Read(const uint32 Addr); static uint8 SS1_Write(const uint32 Addr, uint8 cData); - - static int32 ss1dev(const int32 port, const int32 io, const int32 data); +void raise_ss1_interrupt(uint8 isr_index); -static int32 trace_level = 0x00; /* Disable all tracing by default */ +/* SS1 Interrupt Controller notes: + * + * Msster 8259: + * IRQ0 = VI0 + * IRQ1 = VI1 - DISK3 Interrupt + * IRQ2 = VI2 - IF3 Rx Interrupt + * IRQ3 = VI3 - IF3 Tx Interrupt + * IRQ4 = VI4 - DISK1A + * IRQ5 = VI5 - ? + * IRQ6 = VI6 + * + * + * Slave 8259: + * IRQ0 = VI7 0x48 + * IRQ1 = Timer0 0x49 + * IRQ2 = Timer1 0x4A + * IRQ3 = Timer2 0x4B + * IRQ4 = 9511 SVRQ 0x4C + * IRQ5 = 9511 END 0x4D + * IRQ6 = 2651 TxRDY 0x4E + * IRQ7 = 2651 RxRDY 0x4F + */ +#define MASTER_PIC 0 +#define SLAVE_PIC 1 + +#define VI0_IRQ_OFFSET 0 +#define VI1_IRQ_OFFSET 1 +#define VI2_IRQ_OFFSET 2 +#define VI3_IRQ_OFFSET 3 +#define VI4_IRQ_OFFSET 4 +#define VI5_IRQ_OFFSET 5 +#define VI6_IRQ_OFFSET 6 +#define VI7_IRQ_OFFSET 0 +#define TC0_IRQ_OFFSET 1 +#define TC1_IRQ_OFFSET 2 +#define TC2_IRQ_OFFSET 3 +#define MSVRQ_IRQ_OFFSET 4 +#define MEND_IRQ_OFFSET 5 +#define TXRDY_IRQ_OFFSET 6 +#define RXRDY_IRQ_OFFSET 7 + +typedef struct { + uint8 config_cnt; + uint8 ICW[5]; + uint8 IMR; /* OCW1 = IMR */ + uint8 OCW2; + uint8 OCW3; + uint8 IRR; + uint8 ISR; +} I8259_REGS; + +I8259_REGS ss1_pic[2]; + +/* SS1 Timer notes: + * + * T0, T1, T2 inputs connected to 2MHz clock on SS1 + * T0 IRQ connected to Slave IRQ 1 + * T1 IRQ connected to Slave IRQ 2 + * T2 IRQ connected to Slave IRQ 3 + */ +typedef struct { + uint16 count[3]; /* Current counter value for each timer. */ + uint8 mode[3]; /* Current mode of each timer. */ + uint8 bcd[3]; + uint8 rl[3]; + uint8 CTL; +} I8253_REGS; + +I8253_REGS ss1_tc[1]; + +#define I8253_CTL_SC_MASK 0xC0 +#define I8253_CTL_RL_MASK 0x30 +#define I8253_CTL_MODE_MASK 0x0E +#define I8253_CTL_BCD 0x01 + +typedef struct { + uint8 digit_sel; + uint8 flags; +} RTC_REGS; + +RTC_REGS ss1_rtc[1]; static UNIT ss1_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ROABLE, 0) } + { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, + { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, + { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, + { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) } }; static REG ss1_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, + { HRDATA (MPIC_IMR, ss1_pic[MASTER_PIC].IMR, 8), }, + { HRDATA (MPIC_IRR, ss1_pic[MASTER_PIC].IRR, 8), }, + { HRDATA (MPIC_ISR, ss1_pic[MASTER_PIC].ISR, 8), }, + { HRDATA (MPIC_OCW2, ss1_pic[MASTER_PIC].OCW2, 8), }, + { HRDATA (MPIC_OCW3, ss1_pic[MASTER_PIC].OCW3, 8), }, + + { HRDATA (SPIC_IMR, ss1_pic[SLAVE_PIC].IMR, 8), }, + { HRDATA (SPIC_IRR, ss1_pic[SLAVE_PIC].IRR, 8), }, + { HRDATA (SPIC_ISR, ss1_pic[SLAVE_PIC].ISR, 8), }, + { HRDATA (SPIC_OCW2, ss1_pic[SLAVE_PIC].OCW2, 8), }, + { HRDATA (SPIC_OCW3, ss1_pic[SLAVE_PIC].OCW3, 8), }, + + { HRDATA (T0_MODE, ss1_tc[0].mode, 3), }, + { HRDATA (T0_COUNT, ss1_tc[0].count, 16), }, + { HRDATA (T1_MODE, ss1_tc[1].mode, 3), }, + { HRDATA (T1_COUNT, ss1_tc[1].count, 16), }, + { HRDATA (T2_MODE, ss1_tc[2].mode, 3), }, + { HRDATA (T2_COUNT, ss1_tc[2].count, 16), }, + + { HRDATA (RTC_DIGIT, ss1_rtc[0].digit_sel, 4), }, + { HRDATA (RTC_FLAGS, ss1_rtc[0].flags, 4), }, + { NULL } }; static MTAB ss1_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - /* quiet, no warning messages */ - { UNIT_SS1_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_SS1_VERBOSE, UNIT_SS1_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if(ss1_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB ss1_dt[] = { + { "ERROR", ERROR_MSG }, + { "TRACE", TRACE_MSG }, + { "PIC", PIC_MSG }, + { "TC", TC_MSG }, + { "RTC", RTC_MSG }, + { "MATH", MATH_MSG }, + { "UART", UART_MSG }, + { "IRQ", IRQ_MSG }, + { NULL, 0 } +}; + DEVICE ss1_dev = { "SS1", ss1_unit, ss1_reg, ss1_mod, - SS1_MAX_DRIVES, 10, 31, 1, SS1_MAX_DRIVES, SS1_MAX_DRIVES, + SS1_MAX_TIMERS, 10, 31, 1, SS1_MAX_TIMERS, SS1_MAX_TIMERS, NULL, NULL, &ss1_reset, NULL, NULL, NULL, - &ss1_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &ss1_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + ss1_dt, NULL, "Compupro System Support 1 SS1" }; /* Reset routine */ @@ -128,6 +245,14 @@ static t_stat ss1_reset(DEVICE *dptr) if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &ss1dev, FALSE) != 0) { printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); return SCPE_ARG; + } else { + DBG_PRINT(("SS1: Mapped I/O resource at 0x%04x, len=%d\n", pnp->io_base, pnp->io_size)); + ss1_unit[0].u4 = 0; + ss1_unit[1].u4 = 1; + ss1_unit[2].u4 = 2; + ss1_unit[3].u4 = 3; + ss1_pic[MASTER_PIC].IMR = 0xFF; + ss1_pic[SLAVE_PIC].IMR = 0xFF; } } return SCPE_OK; @@ -164,40 +289,120 @@ static int32 ss1dev(const int32 port, const int32 io, const int32 data) extern int32 sio0d(const int32 port, const int32 io, const int32 data); extern int32 sio0s(const int32 port, const int32 io, const int32 data); +static struct tm currentTime; +static int32 toBCD(const int32 x); + static uint8 SS1_Read(const uint32 Addr) { uint8 cData = 0x00; + uint8 sel_pic = MASTER_PIC; + uint8 sel_tc = 0; + time_t now; + switch(Addr & 0x0F) { - case SS1_M8259_L: - case SS1_M8259_H: case SS1_S8259_L: - case SS1_S8259_H: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " RD: Interrupt Controller not Implemented." NLP, PCX)); + sel_pic = SLAVE_PIC; + case SS1_M8259_L: + if((ss1_pic[sel_pic].OCW3 & 0x03) == 0x03) { + cData = ss1_pic[sel_pic].ISR; + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " RD: %s PIC ISR=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + } else if((ss1_pic[sel_pic].OCW3 & 0x03) == 0x02) { + cData = ss1_pic[sel_pic].IRR; + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " RD: %s PIC IRR=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + } else { + cData = 0xFF; + } + break; + case SS1_S8259_H: + sel_pic = SLAVE_PIC; + case SS1_M8259_H: + cData = ss1_pic[sel_pic].IMR; + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " RD: %s PIC IMR=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + ss1_pic[sel_pic].IMR = cData; break; - case SS1_8253_TC0: - case SS1_8253_TC1: - case SS1_8253_TC2: case SS1_8253_CTL: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " RD: Timer not Implemented." NLP, PCX)); + cData = ss1_tc[0].CTL; + TRACE_PRINT(TC_MSG, ("SS1: " ADDRESS_FORMAT " RD: TC CTL=0x%02x." NLP, PCX, cData)); + break; + case SS1_8253_TC2: + sel_tc++; + case SS1_8253_TC1: + sel_tc++; + case SS1_8253_TC0: + TRACE_PRINT(TC_MSG, ("SS1: " ADDRESS_FORMAT " RD: TC [%d]=0x%02x." NLP, PCX, sel_tc, cData)); break; case SS1_9511A_DATA: case SS1_9511A_CMD: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " RD: Math Coprocessor not Implemented." NLP, PCX)); + TRACE_PRINT(MATH_MSG, ("SS1: " ADDRESS_FORMAT " RD: Math Coprocessor not Implemented." NLP, PCX)); break; case SS1_RTC_CMD: + cData = 0xFF; + TRACE_PRINT(RTC_MSG, ("SS1: " ADDRESS_FORMAT " RD: RTC Cmd=0x%02x." NLP, PCX, cData)); + break; case SS1_RTC_DATA: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " RD: RTC not Implemented." NLP, PCX)); + time(&now); + currentTime = *localtime(&now); + + switch(ss1_rtc[0].digit_sel) { + case 0: + cData = toBCD(currentTime.tm_sec) & 0xF; + break; + case 1: + cData = (toBCD(currentTime.tm_sec) >> 4) & 0xF; + break; + case 2: + cData = toBCD(currentTime.tm_min) & 0xF; + break; + case 3: + cData = (toBCD(currentTime.tm_min) >> 4) & 0xF; + break; + case 4: + cData = toBCD(currentTime.tm_hour) & 0xF; + break; + case 5: + cData = (toBCD(currentTime.tm_hour) >> 4) & 0x3; + cData |= 0x08; /* Set to 24-hour format */ + break; + case 6: + cData = toBCD(currentTime.tm_wday) & 0xF; + break; + case 7: + cData = toBCD(currentTime.tm_mday) & 0xF; + break; + case 8: + cData = (toBCD(currentTime.tm_mday) >> 4) & 0xF; + break; + case 9: + cData = toBCD(currentTime.tm_mon+1) & 0xF; + break; + case 10: + cData = (toBCD(currentTime.tm_mon+1) >> 4) & 0xF; + break; + case 11: + cData = toBCD(currentTime.tm_year-22) & 0xF; + break; + case 12: + cData = (toBCD(currentTime.tm_year-22) >> 4) & 0xF; + break; + default: + cData = 0; + break; + } + TRACE_PRINT(RTC_MSG, ("SS1: " ADDRESS_FORMAT " RD: RTC Data[%x]=0x%02x." NLP, PCX, ss1_rtc[0].digit_sel, cData)); + break; case SS1_UART_DATA: cData = sio0d(Addr, 0, 0); + TRACE_PRINT(UART_MSG, ("SS1: " ADDRESS_FORMAT " RD: UART Data=0x%02x." NLP, PCX, cData)); break; case SS1_UART_STAT: cData = sio0s(Addr, 0, 0); + TRACE_PRINT(UART_MSG, ("SS1: " ADDRESS_FORMAT " RD: UART Stat=0x%02x." NLP, PCX, cData)); break; case SS1_UART_MODE: case SS1_UART_CMD: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " RD: UART not Implemented." NLP, PCX)); + TRACE_PRINT(UART_MSG, ("SS1: " ADDRESS_FORMAT " RD: UART not Implemented." NLP, PCX)); break; } @@ -205,34 +410,120 @@ static uint8 SS1_Read(const uint32 Addr) } +uint16 newcount = 0; +uint8 bc; + +static void generate_ss1_interrupt(void); + static uint8 SS1_Write(const uint32 Addr, uint8 cData) { + uint8 sel_pic = MASTER_PIC; + uint8 sel_tc = 0; + uint8 sel_timer = 0; + switch(Addr & 0x0F) { - case SS1_M8259_L: - case SS1_M8259_H: case SS1_S8259_L: - case SS1_S8259_H: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " WR: Interrupt Controller not Implemented." NLP, PCX)); + sel_pic = SLAVE_PIC; + case SS1_M8259_L: + if(cData & 0x10) { + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " WR: %s PIC ICW1=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + ss1_pic[sel_pic].ICW[1] = cData; + ss1_pic[sel_pic].config_cnt=1; + } else { + if(cData & 0x08) { /* OCW3 */ + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " WR: %s PIC OCW3=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + ss1_pic[sel_pic].OCW3 = cData; + } else { /* OCW2 */ + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " WR: %s PIC OCW2=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + ss1_pic[sel_pic].OCW2 = cData; + } + } + break; + case SS1_S8259_H: + sel_pic = SLAVE_PIC; + case SS1_M8259_H: + if(ss1_pic[sel_pic].config_cnt == 0) { + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " WR: %s PIC IMR=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), cData)); + ss1_pic[sel_pic].IMR = cData; + generate_ss1_interrupt(); + } else { + ss1_pic[sel_pic].config_cnt++; + TRACE_PRINT(PIC_MSG, ("SS1: " ADDRESS_FORMAT " WR: %s PIC ICW%d=0x%02x." NLP, PCX, (sel_pic ? "Slave " : "Master"), ss1_pic[sel_pic].config_cnt, cData)); + ss1_pic[sel_pic].ICW[ss1_pic[sel_pic].config_cnt] = cData; + + ss1_unit[0].u3 = ss1_pic[SLAVE_PIC].ICW[2]+TC0_IRQ_OFFSET; + ss1_unit[1].u3 = ss1_pic[SLAVE_PIC].ICW[2]+TC1_IRQ_OFFSET; + ss1_unit[2].u3 = ss1_pic[SLAVE_PIC].ICW[2]+TC2_IRQ_OFFSET; + + if(ss1_pic[sel_pic].config_cnt == 4) { + ss1_pic[sel_pic].config_cnt = 0; + } + } break; - case SS1_8253_TC0: - case SS1_8253_TC1: - case SS1_8253_TC2: case SS1_8253_CTL: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " WR: Timer not Implemented." NLP, PCX)); + ss1_tc[0].CTL = cData; + sel_timer = (ss1_tc[0].CTL & I8253_CTL_SC_MASK) >> 6; + TRACE_PRINT(TC_MSG, ("SS1: " ADDRESS_FORMAT " WR: TC CTL=0x%02x." NLP, PCX, ss1_tc[0].CTL)); + if(ss1_tc[0].CTL & I8253_CTL_BCD) { + TRACE_PRINT(ERROR_MSG, ("SS1: " ADDRESS_FORMAT " Timer %d: BCD Mode not supported: TC CTL=0x%02x." NLP, PCX, sel_timer, ss1_tc[0].CTL)); + } + ss1_tc[0].bcd[sel_timer] = (ss1_tc[0].CTL & I8253_CTL_BCD); + ss1_tc[0].mode[sel_timer] = (ss1_tc[0].CTL & I8253_CTL_MODE_MASK) >> 1; + ss1_tc[0].rl[sel_timer] = (ss1_tc[0].CTL & I8253_CTL_RL_MASK) >> 4; + TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " Timer %d: Mode: %d, RL=%d, %s." NLP, PCX, + sel_timer, ss1_tc[0].mode[sel_timer], ss1_tc[0].rl[sel_timer], ss1_tc[0].bcd[sel_timer] ? "BCD" : "Binary")); + newcount = 0; + bc=0; + break; + case SS1_8253_TC2: + sel_tc++; + case SS1_8253_TC1: + sel_tc++; + case SS1_8253_TC0: + if(ss1_tc[0].rl[sel_timer] == 3) { + if(bc==0) { + newcount = cData; + } + if(bc==1) { + newcount |= (cData << 8); + sim_activate(&ss1_unit[sel_tc], newcount); + } + bc++; + } + + if(ss1_tc[0].rl[sel_timer] == 2) { + newcount = (cData << 8); + sim_activate(&ss1_unit[sel_tc], newcount); + } + + TRACE_PRINT(TC_MSG, ("SS1: " ADDRESS_FORMAT " WR: TC [%d]=0x%02x." NLP, PCX, sel_tc, cData)); + if(sel_tc == 0) { + } break; case SS1_9511A_DATA: case SS1_9511A_CMD: TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " WR: Math Coprocessor not Implemented." NLP, PCX)); break; case SS1_RTC_CMD: + ss1_rtc[0].digit_sel = cData & 0x0F; + ss1_rtc[0].flags = (cData >> 4) & 0x0F; + TRACE_PRINT(RTC_MSG, ("SS1: " ADDRESS_FORMAT " WR: RTC Cmd=0x%02x (%s%s%s SEL=%x)" NLP, + PCX, cData, + ss1_rtc[0].flags & 0x4 ? "HOLD " :"", + ss1_rtc[0].flags & 0x2 ? "WR" :"", + ss1_rtc[0].flags & 0x1 ? "RD" :"", + ss1_rtc[0].digit_sel)) + break; case SS1_RTC_DATA: - TRACE_PRINT(TRACE_MSG, ("SS1: " ADDRESS_FORMAT " WR: RTC not Implemented." NLP, PCX)); + TRACE_PRINT(RTC_MSG, ("SS1: " ADDRESS_FORMAT " WR: RTC Data=0x%02x" NLP, PCX, cData)); break; case SS1_UART_DATA: + TRACE_PRINT(UART_MSG, ("SS1: " ADDRESS_FORMAT " WR: UART Data=0x%02x." NLP, PCX, cData)); sio0d(Addr, 1, cData); break; case SS1_UART_STAT: + TRACE_PRINT(UART_MSG, ("SS1: " ADDRESS_FORMAT " WR: UART Stat=0x%02x." NLP, PCX, cData)); sio0s(Addr, 1, cData); break; case SS1_UART_MODE: @@ -244,3 +535,116 @@ static uint8 SS1_Write(const uint32 Addr, uint8 cData) return(0); } +void raise_ss1_interrupt(uint8 isr_index) +{ + uint8 irq_bit; + if(isr_index < 7) { /* VI0-6 on master PIC */ + irq_bit = (1 << isr_index); + ss1_pic[MASTER_PIC].ISR |= irq_bit; + generate_ss1_interrupt(); + } else { /* VI7 is on slave PIC */ + ss1_pic[SLAVE_PIC].ISR |= 1; + generate_ss1_interrupt(); + } +} +extern void cpu_raise_interrupt(uint32 irq); + +static void generate_ss1_interrupt(void) +{ + uint8 irq, irq_pend, irq_index = 0, irq_bit = 0; + + uint8 pic; + + for(pic=MASTER_PIC;pic<=SLAVE_PIC;pic++) { + irq_pend = (~ss1_pic[pic].IMR) & ss1_pic[pic].ISR; + + while(irq_pend) { + + irq_bit = irq_pend & 1; + if(irq_bit) { + ss1_pic[pic].IRR |= (irq_bit << irq_index); + irq = ss1_pic[pic].ICW[2]+irq_index; + TRACE_PRINT(IRQ_MSG, ("Handling interrupt on %s PIC: IMR=0x%02x, ISR=0x%02x, IRR=0x%02x, index=%d" NLP, + pic ? "SLAVE" : "MASTER", + ss1_pic[pic].IMR, + ss1_pic[pic].ISR, + ss1_pic[pic].IRR, + irq_index)); + cpu_raise_interrupt(irq); + ss1_pic[pic].IRR &= ~(irq_bit << irq_index); + ss1_pic[pic].ISR &= ~(irq_bit << irq_index); + if(irq_pend & 0x7E) { +/* TRACE_PRINT(IRQ_MSG, ("Requeue interrupt on %s PIC: IMR=0x%02x, ISR=0x%02x, IRR=0x%02x, index=%d" NLP, + pic ? "SLAVE" : "MASTER", + ss1_pic[pic].IMR, + ss1_pic[pic].ISR, + ss1_pic[pic].IRR, + irq_index)); +*/ + sim_activate(&ss1_unit[3], 1000); /* requeue, because more interrupts are pending. */ + } + break; + } else { + irq_index++; + irq_pend = irq_pend >> 1; + } + } + } +} + + +/* Unit service routine */ +/* Unit 0-2 = Timer0-2, Unit3=ISR queue */ +static t_stat ss1_svc (UNIT *uptr) +{ + uint8 cData; + uint8 irq_bit = 0; + + /* Handle SS1 UART Rx interrupts here. */ + cData = sio0s(0x5D, 0, 0); + if(cData & 2) { /* && ((ss1_pic[SLAVE_PIC].IMR & 0x80) == 0)) { */ + ss1_pic[SLAVE_PIC].ISR |= 0x80; + generate_ss1_interrupt(); + sim_activate(uptr, 1000); /* requeue, because we still need to handle the timer interrupt. */ + } else if((cData & 1) && ((ss1_pic[SLAVE_PIC].IMR & 0x40) == 0)) { + TRACE_PRINT(IRQ_MSG, ("SS1: " ADDRESS_FORMAT " Calling UART Tx ISR." NLP, PCX)); + ss1_pic[SLAVE_PIC].ISR |= 0x40; + generate_ss1_interrupt(); + sim_activate(uptr, 1000); /* requeue, because we still need to handle the timer interrupt. */ + } else if (uptr->u4 == 0x3) { /* ISR was requeued because additional interrupts were pending. */ + generate_ss1_interrupt(); + } else { + switch(uptr->u4) { + case 0: + irq_bit = 2; + break; + case 1: + irq_bit = 4; + break; + case 2: + irq_bit = 8; + break; + } + if(ss1_tc[0].mode[uptr->u4] == 0x0) { + TRACE_PRINT(TC_MSG, ("SS1: " ADDRESS_FORMAT " Calling Timer%d ISR." NLP, PCX, uptr->u4)); + ss1_pic[SLAVE_PIC].ISR |= irq_bit; + generate_ss1_interrupt(); + } + if(ss1_tc[0].mode[uptr->u4] == 0x3) { + TRACE_PRINT(TC_MSG, ("SS1: " ADDRESS_FORMAT " Calling Timer%d ISR." NLP, PCX, uptr->u4)); + ss1_pic[SLAVE_PIC].ISR |= irq_bit; + generate_ss1_interrupt(); + TRACE_PRINT(TC_MSG, ("Timer %d, mode %d, reloading\n", uptr->u4, ss1_tc[0].mode[uptr->u4])); + sim_activate(uptr, 33280); + } + } + + sim_activate(&ss1_unit[3], 1000000); // requeue, because more interrupts are pending. + + return SCPE_OK; +} + +static int32 toBCD(const int32 x) { + return (x / 10) * 16 + (x % 10); +} + diff --git a/AltairZ80/sim_imd.c b/AltairZ80/sim_imd.c index 37a7a5b3..c487fa76 100644 --- a/AltairZ80/sim_imd.c +++ b/AltairZ80/sim_imd.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: sim_imd.c 1904 2008-05-21 06:57:57Z hharte $ * + * $Id: sim_imd.c 1999 2008-07-22 04:25:28Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -32,8 +32,8 @@ * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * * * * Module Description: * - * ImageDisk Disk Image File access module for SIMH, definitions. * - * see : * + * ImageDisk (IMD) Disk Image File access module for SIMH. * + * see: http://www.classiccmp.org/dunfield/img/index.htm * * for details on the ImageDisk format and other utilities. * * * * Environment: * @@ -41,9 +41,19 @@ * * *************************************************************************/ -#include "altairz80_defs.h" -#include "sim_imd.h" +/* Change log: + - 06-Aug-2008, Tony Nicholson, Add support for logical Head and + Cylinder maps in the .IMD image file (AGN) +*/ +#include "sim_defs.h" +#include "sim_imd.h" +#include +#ifdef _WIN32 +#include /* for _chsize() */ +#else +#include +#endif /* #define DBG_MSG */ #ifdef DBG_MSG @@ -52,48 +62,132 @@ #define DBG_PRINT(args) #endif +/* use NLP for new line printing while the simulation is running */ +#define UNIX_PLATFORM (defined (__linux) || defined(__NetBSD__) \ +|| defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__)) -DISK_INFO * diskOpen(FILE *fileref, int isVerbose) +#if UNIX_PLATFORM +#define NLP "\r\n" +#else +#define NLP "\n" +#endif + +#if defined (__MWERKS__) && defined (macintosh) +#define __FUNCTION__ __FILE__ +#endif + +static t_stat commentParse(DISK_INFO *myDisk, uint8 comment[], uint32 buffLen); +static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose); +static t_stat diskFormat(DISK_INFO *myDisk); + +/* Open an existing IMD disk image. It will be opened and parsed, and after this + * call, will be ready for sector read/write. The result is the corresponding + * DISK_INFO or NULL if an error occurred. + */ +DISK_INFO *diskOpen(FILE *fileref, uint32 isVerbose) { - char cBuf[256]; - char sectorMap[256]; - char sectorHeadMap[256]; - char sectorCylMap[256]; - unsigned int sectorSize, sectRecordType; - unsigned int i; - unsigned char start_sect; DISK_INFO *myDisk = NULL; - unsigned int TotalSectorCount = 0; - IMD_HEADER imd; - myDisk = (DISK_INFO *)malloc(sizeof(DISK_INFO)); - myDisk->file = fileref; - /* rewind to the beginning of the file. */ - fseek(myDisk->file, 0, SEEK_SET); - - do { - cBuf[0] = fgetc(myDisk->file); - if((cBuf[0] != 0x1a) && isVerbose) putchar(cBuf[0]); + if (diskParse(myDisk, isVerbose) != SCPE_OK) { + free(myDisk); + myDisk = NULL; } - while (cBuf[0] != 0x1a); + + return myDisk; +} + +/* Scans the IMD file for the comment string, and returns it in comment buffer. + * After this function returns, the file pointer is placed after the comment and + * the 0x1A "EOF" marker. + * + * The comment parameter is optional, and if NULL, then the ocmment will not + * be extracted from the IMD file, but the file position will still be advanced + * to the end of the comment. + */ +static t_stat commentParse(DISK_INFO *myDisk, uint8 comment[], uint32 buffLen) +{ + uint8 cData; + uint32 commentLen = 0; + + /* rewind to the beginning of the file. */ + rewind(myDisk->file); + cData = fgetc(myDisk->file); + while ((!feof(myDisk->file)) && (cData != 0x1a)) { + if ((comment != NULL) && (commentLen < buffLen)) { + comment[commentLen++] = cData; + } + cData = fgetc(myDisk->file); + } + if (comment != NULL) { + if (commentLen == buffLen) + commentLen--; + comment[commentLen] = 0; + } + return SCPE_OK; +} + +static uint32 headerOk(IMD_HEADER imd) { + return (imd.cyl < MAX_CYL) && (imd.head < MAX_HEAD); +} + +/* Parse an IMD image. This sets up sim_imd to be able to do sector read/write and + * track write. + */ +static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose) +{ + uint8 comment[256]; + uint8 sectorMap[256]; + uint8 sectorHeadMap[256]; + uint8 sectorCylMap[256]; + uint32 sectorSize, sectorHeadwithFlags, sectRecordType; + uint32 i; + uint8 start_sect; + + uint32 TotalSectorCount = 0; + IMD_HEADER imd; + + if(myDisk == NULL) { + return (SCPE_OPENERR); + } + + memset(myDisk->track, 0, (sizeof(TRACK_INFO)*MAX_CYL*MAX_HEAD)); + + if (commentParse(myDisk, comment, sizeof(comment)) != SCPE_OK) { + return (SCPE_OPENERR); + } + + if(isVerbose) + printf("%s" NLP, comment); myDisk->nsides = 1; myDisk->ntracks = 0; myDisk->flags = 0; /* Make sure all flags are clear. */ + if(feof(myDisk->file)) { + printf("SIM_IMD: Disk image is blank, it must be formatted." NLP); + return (SCPE_OPENERR); + } + do { - DBG_PRINT(("start of track %d at file offset %d\n", myDisk->ntracks, ftell(myDisk->file))); + DBG_PRINT(("start of track %d at file offset %ld" NLP, myDisk->ntracks, ftell(myDisk->file))); fread(&imd, 1, 5, myDisk->file); - if(feof(myDisk->file)) break; + if (feof(myDisk->file)) + break; + sectorSize = 128 << imd.sectsize; + sectorHeadwithFlags = imd.head; /*AGN save the head and flags */ + imd.head &= 1 ; /*AGN mask out flag bits to head 0 or 1 */ - sectorSize = (1 << imd.sectsize) * 128; + DBG_PRINT(("Track %d:" NLP, myDisk->ntracks)); + DBG_PRINT(("\tMode=%d, Cyl=%d, Head=%d(%d), #sectors=%d, sectsize=%d (%d bytes)" NLP, imd.mode, imd.cyl, sectorHeadwithFlags, imd.head, imd.nsects, imd.sectsize, sectorSize)); - DBG_PRINT(("Track %d:\n", myDisk->ntracks)); - DBG_PRINT(("\tMode=%d, Cyl=%d, Head=%d, #sectors=%d, sectsize=%d (%d bytes)\n", imd.mode, imd.cyl, imd.head, imd.nsects, imd.sectsize, sectorSize)); + if (!headerOk(imd)) { + printf("SIM_IMD: Corrupt header." NLP); + return (SCPE_OPENERR); + } if((imd.head + 1) > myDisk->nsides) { myDisk->nsides = imd.head + 1; @@ -114,29 +208,35 @@ DISK_INFO * diskOpen(FILE *fileref, int isVerbose) } DBG_PRINT((", Start Sector=%d", myDisk->track[imd.cyl][imd.head].start_sector)); - if(imd.head & IMD_FLAG_SECT_HEAD_MAP) { + if(sectorHeadwithFlags & IMD_FLAG_SECT_HEAD_MAP) { fread(sectorHeadMap, 1, imd.nsects, myDisk->file); DBG_PRINT(("\tSector Head Map: ")); for(i=0;ifile); DBG_PRINT(("\tSector Cyl Map: ")); for(i=0;ifile))); + DBG_PRINT((NLP "Sector data at offset 0x%08lx" NLP, ftell(myDisk->file))); /* Build the table with location 0 being the start sector. */ start_sect = myDisk->track[imd.cyl][imd.head].start_sector; @@ -146,42 +246,63 @@ DISK_INFO * diskOpen(FILE *fileref, int isVerbose) TotalSectorCount++; DBG_PRINT(("Sector Phys: %d/Logical: %d: %d bytes: ", i, sectorMap[i], sectorSize)); sectRecordType = fgetc(myDisk->file); + /* AGN Logical head mapping */ + myDisk->track[imd.cyl][imd.head].logicalHead[i] = sectorHeadMap[i]; + /* AGN Logical cylinder mapping */ + myDisk->track[imd.cyl][imd.head].logicalCyl[i] = sectorCylMap[i]; switch(sectRecordType) { case SECT_RECORD_UNAVAILABLE: /* Data could not be read from the original media */ - myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = 0xBADBAD; + if (sectorMap[i]-start_sect < MAX_SPT) + myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = 0xBADBAD; + else { + printf("SIM_IMD: ERROR: Illegal sector offset %d" NLP, sectorMap[i]-start_sect); + return (SCPE_OPENERR); + } break; case SECT_RECORD_NORM: /* Normal Data */ case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */ case SECT_RECORD_NORM_ERR: /* Normal Data with read error */ case SECT_RECORD_NORM_DAM_ERR: /* Normal Data with deleted address mark with read error */ -/* DBG_PRINT(("Uncompressed Data\n")); */ - myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file); - fseek(myDisk->file, sectorSize, SEEK_CUR); +/* DBG_PRINT(("Uncompressed Data" NLP)); */ + if (sectorMap[i]-start_sect < MAX_SPT) { + myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file); + sim_fseek(myDisk->file, sectorSize, SEEK_CUR); + } + else { + printf("SIM_IMD: ERROR: Illegal sector offset %d" NLP, sectorMap[i]-start_sect); + return (SCPE_OPENERR); + } break; case SECT_RECORD_NORM_COMP: /* Compressed Normal Data */ case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */ case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */ case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */ - myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file); - myDisk->flags |= FD_FLAG_WRITELOCK; /* Write-protect the disk if any sectors are compressed. */ + if (sectorMap[i]-start_sect < MAX_SPT) { + myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file); + myDisk->flags |= FD_FLAG_WRITELOCK; /* Write-protect the disk if any sectors are compressed. */ #ifdef VERBOSE_DEBUG - DBG_PRINT(("Compressed Data = 0x%02x\n", fgetc(myDisk->file))); + DBG_PRINT(("Compressed Data = 0x%02x" NLP, fgetc(myDisk->file))); #else - fgetc(myDisk->file); + fgetc(myDisk->file); #endif + } + else { + printf("SIM_IMD: ERROR: Illegal sector offset %d" NLP, sectorMap[i]-start_sect); + return (SCPE_OPENERR); + } break; default: - printf("ERROR: unrecognized sector record type %d\n", sectRecordType); + printf("SIM_IMD: ERROR: unrecognized sector record type %d" NLP, sectRecordType); + return (SCPE_OPENERR); break; } - DBG_PRINT(("\n")); + DBG_PRINT((NLP)); } myDisk->ntracks++; - } - while (!feof(myDisk->file)); + } while (!feof(myDisk->file)); - DBG_PRINT(("Processed %d sectors\n", TotalSectorCount)); + DBG_PRINT(("Processed %d sectors" NLP, TotalSectorCount)); #ifdef VERBOSE_DEBUG for(i=0;intracks;i++) { @@ -189,31 +310,140 @@ DISK_INFO * diskOpen(FILE *fileref, int isVerbose) for(j=0;jtrack[i][0].sectorOffsetMap[j])); } - DBG_PRINT(("\n")); + DBG_PRINT((NLP)); } #endif if(myDisk->flags & FD_FLAG_WRITELOCK) { - printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress.\n"); + printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress." NLP); } - return myDisk; + return SCPE_OK; } -unsigned int diskClose(DISK_INFO *myDisk) +/* + * This function closes the IMD image. After closing, the sector read/write operations are not + * possible. + * + * The IMD file is not actually closed, we leave that to SIMH. + */ +t_stat diskClose(DISK_INFO **myDisk) { - unsigned int retval = 0; - - if(myDisk == NULL) { - return (-1); - } - - free(myDisk); - myDisk = NULL; - - return retval; + if(*myDisk == NULL) + return SCPE_OPENERR; + free(*myDisk); + *myDisk = NULL; + return SCPE_OK; } -unsigned int imdGetSides(DISK_INFO *myDisk) +#define MAX_COMMENT_LEN 256 + +/* + * Create an ImageDisk (IMD) file. This function just creates the comment header, and allows + * the user to enter a comment. After the IMD is created, it must be formatted with a format + * program on the simulated operating system, ie CP/M, CDOS, 86-DOS. + * + * If the IMD file already exists, the user will be given the option of overwriting it. + */ +t_stat diskCreate(FILE *fileref, char *ctlr_comment) +{ + DISK_INFO *myDisk = NULL; + char *comment; + char *curptr; + uint8 answer; + int32 len, remaining; + + if(fileref == NULL) { + return (SCPE_OPENERR); + } + + if(sim_fsize(fileref) != 0) { + printf("SIM_IMD: Disk image already has data, do you want to overwrite it? "); + answer = getchar(); + + if((answer != 'y') && (answer != 'Y')) { + return (SCPE_OPENERR); + } + } + + if((curptr = comment = calloc(1, MAX_COMMENT_LEN)) == 0) { + printf("Memory allocation failure.\n"); + return (SCPE_MEM); + } + + printf("SIM_IMD: Enter a comment for this disk.\n" + "SIM_IMD: Terminate with a '.' on an otherwise blank line.\n"); + remaining = MAX_COMMENT_LEN; + do { + printf("IMD> "); + fgets(curptr, remaining - 3, stdin); + if (strcmp(curptr, ".\n") == 0) { + remaining = 0; + } else { + len = strlen(curptr) - 1; + if (curptr[len] != '\n') + len++; + remaining -= len; + curptr += len; + *curptr++ = 0x0d; + *curptr++ = 0x0a; + } + } while (remaining > 4); + *curptr = 0x00; + + /* rewind to the beginning of the file. */ + rewind(fileref); + + /* Erase the contents of the IMD file in case we are overwriting an existing image. */ +#ifdef _WIN32 /* This might work under UNIX and/or VMS since this POSIX, but I haven't tried it. */ + _chsize(_fileno(fileref), ftell (fileref)); +#else + ftruncate(fileno(fileref), ftell (fileref)); +#endif + + fprintf(fileref, "IMD SIMH %s %s\n", __DATE__, __TIME__); + fputs(comment, fileref); + free(comment); + fprintf(fileref, "\n\n$Id: sim_imd.c 1999 2008-07-22 04:25:28Z hharte $\n"); + fprintf(fileref, "%s\n", ctlr_comment); + fputc(0x1A, fileref); /* EOF marker for IMD comment. */ + fflush(fileref); + + if((myDisk = diskOpen(fileref, 0)) == NULL) { + printf("SIM_IMD: Error opening disk for format.\n"); + return(SCPE_OPENERR); + } + + if(diskFormat(myDisk) != SCPE_OK) { + printf("SIM_IMD: error formatting disk.\n"); + } + + return diskClose(&myDisk); +} + + +t_stat diskFormat(DISK_INFO *myDisk) +{ + uint8 i; + uint8 sector_map[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; + uint32 flags; + + printf("SIM_IMD: Formatting disk in IBM 3740 SS/SD Format.\n"); + + for(i=0;i<77;i++) { + if((trackWrite(myDisk, i, 0, 26, 128, sector_map, IMD_MODE_500K_FM, 0xE5, &flags)) != 0) { + printf("SIM_IMD: Error formatting track %d\n", i); + return SCPE_IOERR; + } else { + putchar('.'); + } + } + + printf("\nSIM_IMD: Format Complete.\n"); + + return SCPE_OK; +} + +uint32 imdGetSides(DISK_INFO *myDisk) { if(myDisk != NULL) { return(myDisk->nsides); @@ -222,7 +452,7 @@ unsigned int imdGetSides(DISK_INFO *myDisk) return (0); } -unsigned int imdIsWriteLocked(DISK_INFO *myDisk) +uint32 imdIsWriteLocked(DISK_INFO *myDisk) { if(myDisk != NULL) { return((myDisk->flags & FD_FLAG_WRITELOCK) ? 1 : 0); @@ -232,33 +462,63 @@ unsigned int imdIsWriteLocked(DISK_INFO *myDisk) } /* Check that the given track/sector exists on the disk */ -int sectSeek(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head) +t_stat sectSeek(DISK_INFO *myDisk, + uint32 Cyl, + uint32 Head) { - if(myDisk->track[Cyl][Head].nsects == 0) { - DBG_PRINT(("%s: invalid track/head" NLP, __FUNCTION__)); - return(-1); + if(Cyl >= myDisk->ntracks) { + return(SCPE_IOERR); } - return(0); + if(Head >= myDisk->nsides) { + return(SCPE_IOERR); + } + + if(myDisk->track[Cyl][Head].nsects == 0) { + DBG_PRINT(("%s: invalid track/head" NLP, __FUNCTION__)); + return(SCPE_IOERR); + } + + return(SCPE_OK); } - -int sectRead(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned int Sector, unsigned char *buf, unsigned int buflen, unsigned int *flags, unsigned int *readlen) +/* Read a sector from an IMD image. */ +t_stat sectRead(DISK_INFO *myDisk, + uint32 Cyl, + uint32 Head, + uint32 Sector, + uint8 *buf, + uint32 buflen, + uint32 *flags, + uint32 *readlen) { - unsigned int sectorFileOffset; - unsigned char sectRecordType; - unsigned char start_sect; + uint32 sectorFileOffset; + uint8 sectRecordType; + uint8 start_sect; *readlen = 0; *flags = 0; + /* Check parameters */ + if(myDisk == NULL) { + *flags |= IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); + } + + if(sectSeek(myDisk, Cyl, Head) != SCPE_OK) { + *flags |= IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); + } + if(Sector > myDisk->track[Cyl][Head].nsects) { DBG_PRINT(("%s: invalid sector" NLP, __FUNCTION__)); - return(-1); + *flags |= IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); } if(buflen < myDisk->track[Cyl][Head].sectsize) { printf("%s: Reading C:%d/H:%d/S:%d, len=%d: user buffer too short, need %d" NLP, __FUNCTION__, Cyl, Head, Sector, buflen, myDisk->track[Cyl][Head].sectsize); - return(-1); + *flags |= IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); } start_sect = myDisk->track[Cyl][Head].start_sector; @@ -267,7 +527,7 @@ int sectRead(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned in DBG_PRINT(("Reading C:%d/H:%d/S:%d, len=%d, offset=0x%08x" NLP, Cyl, Head, Sector, buflen, sectorFileOffset)); - fseek(myDisk->file, sectorFileOffset-1, 0); + sim_fseek(myDisk->file, sectorFileOffset-1, 0); sectRecordType = fgetc(myDisk->file); switch(sectRecordType) { @@ -310,41 +570,61 @@ int sectRead(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned in break; } - return(0); + return(SCPE_OK); } - -int sectWrite(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned int Sector, unsigned char *buf, unsigned int buflen, unsigned int *flags, unsigned int *writelen) +/* Write a sector to an IMD image. */ +t_stat sectWrite(DISK_INFO *myDisk, + uint32 Cyl, + uint32 Head, + uint32 Sector, + uint8 *buf, + uint32 buflen, + uint32 *flags, + uint32 *writelen) { - unsigned int sectorFileOffset; - unsigned char sectRecordType; - unsigned char start_sect; + uint32 sectorFileOffset; + uint8 sectRecordType; + uint8 start_sect; *writelen = 0; - *flags = 0; DBG_PRINT(("Writing C:%d/H:%d/S:%d, len=%d" NLP, Cyl, Head, Sector, buflen)); - if(myDisk->flags & FD_FLAG_WRITELOCK) { - printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress." NLP); + /* Check parameters */ + if(myDisk == NULL) { + *flags = IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); + } + + if(sectSeek(myDisk, Cyl, Head) != 0) { + *flags = IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); } if(Sector > myDisk->track[Cyl][Head].nsects) { - printf("%s: invalid sector [sector %i > # of sectors %i]" NLP, - __FUNCTION__, Sector, myDisk->track[Cyl][Head].nsects); - return(-1); + DBG_PRINT(("%s: invalid sector" NLP, __FUNCTION__)); + *flags = IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); + } + + if(myDisk->flags & FD_FLAG_WRITELOCK) { + printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress." NLP); + *flags = IMD_DISK_IO_ERROR_WPROT; + return(SCPE_IOERR); } if(buflen < myDisk->track[Cyl][Head].sectsize) { printf("%s: user buffer too short [buflen %i < sectsize %i]" NLP, __FUNCTION__, buflen, myDisk->track[Cyl][Head].sectsize); - return(-1); + *flags = IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); } start_sect = myDisk->track[Cyl][Head].start_sector; sectorFileOffset = myDisk->track[Cyl][Head].sectorOffsetMap[Sector-start_sect]; - fseek(myDisk->file, sectorFileOffset-1, 0); + sim_fseek(myDisk->file, sectorFileOffset-1, 0); if (*flags & IMD_DISK_IO_ERROR_GENERAL) { sectRecordType = SECT_RECORD_UNAVAILABLE; @@ -354,6 +634,9 @@ int sectWrite(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned i else sectRecordType = SECT_RECORD_NORM_ERR; } else { + if (*flags & IMD_DISK_IO_DELETED_ADDR_MARK) + sectRecordType = SECT_RECORD_NORM_DAM; + else sectRecordType = SECT_RECORD_NORM; } @@ -361,5 +644,115 @@ int sectWrite(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned i fwrite(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file); *writelen = myDisk->track[Cyl][Head].sectsize; - return(0); + return(SCPE_OK); +} + +/* Format an entire track. The new track to be formatted must be after any existing tracks on + * the disk. + * + * This routine should be enhanced to re-format an existing track to the same format (this + * does not involve changing the disk image size.) + * + * Any existing data on the disk image will be destroyed when Track 0, Head 0 is formatted. + * At that time, the IMD file is truncated. So for the trackWrite to be used to sucessfully + * format a disk image, then format program must format tracks starting with Cyl 0, Head 0, + * and proceed sequentially through all tracks/heads on the disk. + * + * Format programs that are known to work include: + * Cromemco CDOS "INIT.COM" + * ADC Super-Six (CP/M-80) "FMT8.COM" + * 86-DOS "INIT.COM" + * + */ +t_stat trackWrite(DISK_INFO *myDisk, + uint32 Cyl, + uint32 Head, + uint32 numSectors, + uint32 sectorLen, + uint8 *sectorMap, + uint8 mode, + uint8 fillbyte, + uint32 *flags) +{ + FILE *fileref; + IMD_HEADER track_header; + uint8 *sectorData; + unsigned long i; + unsigned long dataLen; + + *flags = 0; + + /* Check parameters */ + if(myDisk == NULL) { + *flags |= IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); + } + + if(myDisk->flags & FD_FLAG_WRITELOCK) { + printf("Disk write-protected, cannot format tracks." NLP); + *flags |= IMD_DISK_IO_ERROR_WPROT; + return(SCPE_IOERR); + } + + fileref = myDisk->file; + + DBG_PRINT(("Formatting C:%d/H:%d/N:%d, len=%d, Fill=0x%02x" NLP, Cyl, Head, numSectors, sectorLen, fillbyte)); + + /* Truncate the IMD file when formatting Cyl 0, Head 0 */ + if((Cyl == 0) && (Head == 0)) + { + /* Skip over IMD comment field. */ + commentParse(myDisk, NULL, 0); + + /* Truncate the IMD file after the comment field. */ +#ifdef _WIN32 /* This might work under UNIX and/or VMS since this POSIX, but I haven't tried it. */ + _chsize(_fileno(fileref), ftell (fileref)); +#else + ftruncate(fileno(fileref), ftell (fileref)); +#endif + /* Flush and re-parse the IMD file. */ + fflush(fileref); + diskParse(myDisk, 0); + } + + /* Check to make sure the Cyl / Head is not already formatted. */ + if(sectSeek(myDisk, Cyl, Head) == 0) { + printf("SIM_IMD: ERROR: Not Formatting C:%d/H:%d, track already exists." NLP, Cyl, Head); + *flags |= IMD_DISK_IO_ERROR_GENERAL; + return(SCPE_IOERR); + } + + track_header.mode = mode; + track_header.cyl = Cyl; + track_header.head = Head; + track_header.nsects = numSectors; + track_header.sectsize = sectorLen; + + /* Forward to end of the file, write track header and sector map. */ + fseek(myDisk->file, 0, SEEK_END); + fwrite(&track_header, sizeof(IMD_HEADER), 1, fileref); + fwrite(sectorMap, 1, numSectors, fileref); + + /* Compute data length, and fill a sector buffer with the + * sector record type as the first byte, and fill the sector + * data with the fillbyte. + */ + dataLen = (128 << sectorLen)+1; + sectorData = malloc(dataLen); + memset(sectorData, fillbyte, dataLen); + sectorData[0] = SECT_RECORD_NORM; + + /* For each sector on the track, write the record type and sector data. */ + for(i=0;i= IMD_MODE_500K_MFM) typedef struct { - unsigned char mode; - unsigned char nsects; - unsigned int sectsize; - unsigned int sectorOffsetMap[MAX_SPT]; - unsigned char start_sector; + uint8 mode; + uint8 nsects; + uint32 sectsize; + uint32 sectorOffsetMap[MAX_SPT]; + uint8 start_sector; + uint8 logicalHead[MAX_SPT]; + uint8 logicalCyl[MAX_SPT]; } TRACK_INFO; typedef struct { FILE *file; - unsigned int ntracks; - unsigned char nsides; - unsigned char flags; + uint32 ntracks; + uint8 nsides; + uint8 flags; TRACK_INFO track[MAX_CYL][MAX_HEAD]; } DISK_INFO; -extern DISK_INFO *diskOpen(FILE *fileref, int isVerbose); /*char *filename); */ -extern unsigned int diskClose(DISK_INFO *myDisk); -extern unsigned int imdGetSides(DISK_INFO *myDisk); -extern unsigned int imdIsWriteLocked(DISK_INFO *myDisk); +extern DISK_INFO *diskOpen(FILE *fileref, uint32 isVerbose); +extern t_stat diskClose(DISK_INFO **myDisk); +extern t_stat diskCreate(FILE *fileref, char *ctlr_comment); +extern uint32 imdGetSides(DISK_INFO *myDisk); +extern uint32 imdIsWriteLocked(DISK_INFO *myDisk); -extern int sectSeek(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head); -extern int sectRead(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned int Sector, unsigned char *buf, unsigned int buflen, unsigned int *flags, unsigned int *readlen); -extern int sectWrite(DISK_INFO *myDisk, unsigned int Cyl, unsigned int Head, unsigned int Sector, unsigned char *buf, unsigned int buflen, unsigned int *flags, unsigned int *writelen); +extern t_stat sectSeek(DISK_INFO *myDisk, uint32 Cyl, uint32 Head); +extern t_stat sectRead(DISK_INFO *myDisk, uint32 Cyl, uint32 Head, uint32 Sector, uint8 *buf, uint32 buflen, uint32 *flags, uint32 *readlen); +extern t_stat sectWrite(DISK_INFO *myDisk, uint32 Cyl, uint32 Head, uint32 Sector, uint8 *buf, uint32 buflen, uint32 *flags, uint32 *writelen); +extern t_stat trackWrite(DISK_INFO *myDisk, + uint32 Cyl, + uint32 Head, + uint32 numSectors, + uint32 sectorLen, + uint8 *sectorMap, + uint8 mode, + uint8 fillbyte, + uint32 *flags); diff --git a/AltairZ80/vfdhd.c b/AltairZ80/vfdhd.c index 84751531..c0173e10 100644 --- a/AltairZ80/vfdhd.c +++ b/AltairZ80/vfdhd.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: vfdhd.c 1773 2008-01-11 05:46:19Z hharte $ * + * $Id: vfdhd.c 1995 2008-07-15 03:59:13Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -50,24 +50,29 @@ #include "sim_imd.h" +/* #define DBG_MSG */ + #ifdef DBG_MSG #define DBG_PRINT(args) printf args #else #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define ORDERS_MSG 0x02 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define ORDERS_MSG (1 << 7) static void VFDHD_Command(void); #define VFDHD_MAX_DRIVES 4 #define VFDHD_SECTOR_LEN 275 +#define VFDHD_RAW_LEN (40 + VFDHD_SECTOR_LEN + 128) typedef union { struct { @@ -81,7 +86,7 @@ typedef union { uint8 ecc_valid; /* 0xAA indicates ECC is being used. */ uint8 postamble[128]; } u; - uint8 raw[VFDHD_SECTOR_LEN]; + uint8 raw[VFDHD_RAW_LEN]; } SECTOR_FORMAT; @@ -119,7 +124,6 @@ typedef struct { uint8 read; uint8 ecc_enable; uint8 precomp; - uint8 floppy_sel; uint8 controller_busy; uint8 motor_on; @@ -155,8 +159,7 @@ static int32 vfdhddev(const int32 port, const int32 io, const int32 data); static uint8 VFDHD_Read(const uint32 Addr); static uint8 VFDHD_Write(const uint32 Addr, uint8 cData); -static int32 trace_level = FALSE; -static int32 hdSize = 5; +static int32 hdSize = 5; static UNIT vfdhd_unit[] = { { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) }, @@ -166,29 +169,44 @@ static UNIT vfdhd_unit[] = { }; static REG vfdhd_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, - { DRDATA (HDSIZE, hdSize, 10), }, + { DRDATA (HDSIZE, hdSize, 10), }, { NULL } }; static MTAB vfdhd_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_VFDHD_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_VFDHD_WLK, UNIT_VFDHD_WLK, "WRTLCK", "WRTLCK", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { UNIT_VFDHD_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_VFDHD_WLK, UNIT_VFDHD_WLK, "WRTLCK", "WRTLCK", NULL }, /* quiet, no warning messages */ - { UNIT_VFDHD_VERBOSE, 0, "QUIET", "QUIET", NULL }, + { UNIT_VFDHD_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* verbose, show warning messages */ - { UNIT_VFDHD_VERBOSE, UNIT_VFDHD_VERBOSE, "VERBOSE", "VERBOSE", NULL }, + { UNIT_VFDHD_VERBOSE, UNIT_VFDHD_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if(vfdhd_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB vfdhd_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "ORDERS", ORDERS_MSG }, + { NULL, 0 } +}; + DEVICE vfdhd_dev = { "VFDHD", vfdhd_unit, vfdhd_reg, vfdhd_mod, VFDHD_MAX_DRIVES, 10, 31, 1, VFDHD_MAX_DRIVES, VFDHD_MAX_DRIVES, NULL, NULL, &vfdhd_reset, NULL, &vfdhd_attach, &vfdhd_detach, - &vfdhd_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &vfdhd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + vfdhd_dt, NULL, "Vector Graphic FD-HD Controller VFDHD" }; /* Reset routine */ @@ -265,7 +283,8 @@ static t_stat vfdhd_attach(UNIT *uptr, char *cptr) if (uptr->flags & UNIT_VFDHD_VERBOSE) printf("--------------------------------------------------------\n"); vfdhd_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_VFDHD_VERBOSE)); - printf("\n"); + if (uptr->flags & UNIT_VFDHD_VERBOSE) + printf("\n"); } else { vfdhd_info->drive[i].imd = NULL; } @@ -321,10 +340,12 @@ static t_stat vfdhd_detach(UNIT *uptr) } DBG_PRINT(("Detach VFDHD%d\n", i)); - diskClose(vfdhd_info->drive[i].imd); + r = diskClose(&vfdhd_info->drive[i].imd); + if (r != SCPE_OK) + return r; r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) + if (r != SCPE_OK) return r; return SCPE_OK; @@ -400,6 +421,10 @@ static uint8 VFDHD_Read(const uint32 Addr) break; case FDHD_DATA: /* DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " RD Data" NLP, PCX)); */ + if(vfdhd_info->datacount+40 >= VFDHD_RAW_LEN) { + TRACE_PRINT(ERROR_MSG, ("VFDHD: " ADDRESS_FORMAT " Illegal data count %d." NLP, PCX, vfdhd_info->datacount)); + vfdhd_info->datacount = 0; + } cData = sdata.raw[vfdhd_info->datacount+40]; vfdhd_info->datacount++; @@ -424,7 +449,7 @@ static uint8 VFDHD_Write(const uint32 Addr, uint8 cData) switch(Addr & 0x3) { case FDHD_CTRL_STATUS0: - vfdhd_info->sel_drive = cData & 3; + vfdhd_info->sel_drive = cData & 0x03; vfdhd_info->head = (cData >> 2) & 0x7; vfdhd_info->step = (cData >> 5) & 1; vfdhd_info->direction = (cData >> 6) & 1; @@ -474,11 +499,23 @@ static uint8 VFDHD_Write(const uint32 Addr, uint8 cData) DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR Data" NLP, PCX)); #ifdef USE_VGI if(vfdhd_info->sel_drive > 0) { /* Floppy */ + if(vfdhd_info->datacount >= VFDHD_RAW_LEN) { + TRACE_PRINT(ERROR_MSG, ("VFDHD: " ADDRESS_FORMAT " Illegal data count %d." NLP, PCX, vfdhd_info->datacount)); + vfdhd_info->datacount = 0; + } sdata.raw[vfdhd_info->datacount] = cData; } else { /* Hard */ + if(vfdhd_info->datacount+10 >= VFDHD_RAW_LEN) { + TRACE_PRINT(ERROR_MSG, ("VFDHD: " ADDRESS_FORMAT " Illegal data count %d." NLP, PCX, vfdhd_info->datacount)); + vfdhd_info->datacount = 0; + } sdata.raw[vfdhd_info->datacount+10] = cData; } #else + if((vfdhd_info->datacount-13 >= VFDHD_RAW_LEN) || (vfdhd_info->datacount < 13)) { + TRACE_PRINT(ERROR_MSG, ("VFDHD: " ADDRESS_FORMAT " Illegal data count %d." NLP, PCX, vfdhd_info->datacount)); + vfdhd_info->datacount = 13; + } sdata.u.data[vfdhd_info->datacount-13] = cData; #endif /* USE_VGI */ @@ -556,7 +593,7 @@ static void VFDHD_Command(void) /* Checksum everything except the sync byte */ for(i=1;i<269;i++) { - checksum = adc(checksum, sdata.raw[i]); + checksum = adc(checksum, sdata.raw[i+40]); } sdata.u.checksum = checksum & 0xFF; @@ -566,7 +603,7 @@ static void VFDHD_Command(void) if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { - fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); fread(&sdata.u.sync, 274, /*VFDHD_SECTOR_LEN,*/ 1, (pDrive->uptr)->fileref); memset(&sdata.u.preamble, 0, 40); @@ -631,7 +668,7 @@ static void VFDHD_Command(void) pDrive->track, vfdhd_info->head, vfdhd_info->sector)); - fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); + sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); #ifdef USE_VGI fwrite(&sdata.u.sync, VFDHD_SECTOR_LEN, 1, (pDrive->uptr)->fileref); #else diff --git a/AltairZ80/wd179x.c b/AltairZ80/wd179x.c index f7394462..dc1621fb 100644 --- a/AltairZ80/wd179x.c +++ b/AltairZ80/wd179x.c @@ -1,6 +1,6 @@ /************************************************************************* * * - * $Id: wd179x.c 1907 2008-05-21 07:04:17Z hharte $ * + * $Id: wd179x.c 1999 2008-07-22 04:25:28Z hharte $ * * * * Copyright (c) 2007-2008 Howard M. Harte. * * http://www.hartetec.com * @@ -56,15 +56,25 @@ #define DBG_PRINT(args) #endif -#define SEEK_MSG 0x01 -#define CMD_MSG 0x04 -#define RD_DATA_MSG 0x08 -#define WR_DATA_MSG 0x10 -#define STATUS_MSG 0x20 -#define VERBOSE_MSG 0x80 +#define CROMFDC_SIM_100US 291 /* Number of "ticks" in 100uS, where does this come from? */ +#define CROMFDC_8IN_ROT (167 * CROMFDC_SIM_100US) +#define CROMFDC_5IN_ROT (200 * CROMFDC_SIM_100US) -#define WD179X_MAX_DRIVES 4 -#define WD179X_SECTOR_LEN 8192 +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define CMD_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define STATUS_MSG (1 << 5) +#define FMT_MSG (1 << 6) +#define VERBOSE_MSG (1 << 7) + +#define WD179X_MAX_DRIVES 4 +#define WD179X_SECTOR_LEN 8192 +/* 2^(7 + WD179X_MAX_SEC_LEN) == WD179X_SECTOR_LEN */ +#define WD179X_MAX_SEC_LEN 6 +#define WD179X_MAX_SECTOR 26 #define CMD_PHASE 0 #define EXEC_PHASE 1 @@ -81,11 +91,14 @@ #define WD179X_STAT_BUSY (1 << 0) /* Status Bits for Type II, III Commands */ -#define WD179X_STAT_REC_TYPE (1 << 5) +/*#define WD179X_STAT_NOT_READY (1 << 7) */ +/*#define WD179X_STAT_WPROT (1 << 6) */ +#define WD179X_STAT_REC_TYPE (1 << 5) /* Also Write Fault */ #define WD179X_STAT_NOT_FOUND (1 << 4) +/*#define WD179X_STAT_CRC_ERROR (1 << 3) */ #define WD179X_STAT_LOST_DATA (1 << 2) #define WD179X_STAT_DRQ (1 << 1) - +/*#define WD179X_STAT_BUSY (1 << 0) */ typedef union { uint8 raw[WD179X_SECTOR_LEN]; @@ -115,14 +128,21 @@ typedef struct { uint8 fdc_data; /* WD179X Data Register */ uint8 fdc_read; /* TRUE when reading */ uint8 fdc_write; /* TRUE when writing */ + uint8 fdc_write_track; /* TRUE when writing an entire track */ + uint8 fdc_fmt_state; /* Format track statemachine state */ + uint8 fdc_gap[4]; /* Gap I - Gap IV lengths */ + uint8 fdc_fmt_sector_count; /* sector count for format track */ + uint8 fdc_sectormap[WD179X_MAX_SECTOR]; /* Physical to logical sector map */ + uint8 fdc_header_index; /* Index into header */ uint8 fdc_read_addr; /* TRUE when READ ADDRESS command is in progress */ uint8 fdc_multiple; /* TRUE for multi-sector read/write */ - uint16 fdc_datacount; /* Read or Write data remaining transfer length */ - uint16 fdc_dataindex; /* index of current byte in sector data */ + uint16 fdc_datacount; /* Read or Write data remaining transfer length */ + uint16 fdc_dataindex; /* index of current byte in sector data */ uint8 index_pulse_wait; /* TRUE if waiting for interrupt on next index pulse. */ uint8 fdc_sector; /* R Record (Sector) */ uint8 fdc_sec_len; /* N Sector Length */ int8 step_dir; + uint8 cmdtype; /* Type of current/former command */ WD179X_DRIVE_INFO drive[WD179X_MAX_DRIVES]; } WD179X_INFO; @@ -138,7 +158,6 @@ t_stat wd179x_svc (UNIT *uptr); /* These are needed for DMA. PIO Mode has not been implemented yet. */ extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); extern uint8 GetBYTEWrapper(const uint32 Addr); -static uint8 Do1793Command(uint8 cCommand); #define UNIT_V_WD179X_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_WD179X_WLK (1 << UNIT_V_WD179X_WLK) @@ -150,6 +169,14 @@ static uint8 Do1793Command(uint8 cCommand); #define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */ #define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */ +/* Write Track (format) Statemachine states */ +#define FMT_GAP1 1 +#define FMT_GAP2 2 +#define FMT_GAP3 3 +#define FMT_GAP4 4 +#define FMT_HEADER 5 +#define FMT_DATA 6 + /* WD179X Commands */ #define WD179X_RESTORE 0x00 /* Type I */ #define WD179X_SEEK 0x10 /* Type I */ @@ -168,12 +195,10 @@ static uint8 Do1793Command(uint8 cCommand); #define WD179X_READ_TRACK 0xE0 /* Type III */ #define WD179X_WRITE_TRACK 0xF0 /* Type III */ -static int32 trace_level = 0xff; /* Disable all tracing by default. */ -static int32 bootstrap = 0; - static int32 wd179xdev(const int32 port, const int32 io, const int32 data); static t_stat wd179x_reset(DEVICE *dptr); int32 find_unit_index (UNIT *uptr); +uint8 floorlog2(unsigned int n); WD179X_INFO wd179x_info_data = { { 0x0, 0, 0x30, 4 } }; WD179X_INFO *wd179x_info = &wd179x_info_data; @@ -185,30 +210,41 @@ static UNIT wd179x_unit[] = { { UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 } }; -static REG wd179x_reg[] = { - { HRDATA (TRACELEVEL, trace_level, 16), }, - { DRDATA (BOOTSTRAP, bootstrap, 10), }, - { NULL } -}; - static MTAB wd179x_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_WD179X_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_WD179X_WLK, UNIT_WD179X_WLK, "WRTLCK", "WRTLCK", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, + { UNIT_WD179X_WLK, 0, "WRTENB", "WRTENB", NULL }, + { UNIT_WD179X_WLK, UNIT_WD179X_WLK, "WRTLCK", "WRTLCK", NULL }, /* quiet, no warning messages */ - { UNIT_WD179X_VERBOSE, 0, "QUIET", "QUIET", NULL }, + { UNIT_WD179X_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* verbose, show warning messages */ - { UNIT_WD179X_VERBOSE, UNIT_WD179X_VERBOSE, "VERBOSE", "VERBOSE", NULL }, + { UNIT_WD179X_VERBOSE, UNIT_WD179X_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { 0 } }; +#define TRACE_PRINT(level, args) if(wd179x_dev.dctrl & level) { \ + printf args; \ + } + +/* Debug Flags */ +static DEBTAB wd179x_dt[] = { + { "ERROR", ERROR_MSG }, + { "SEEK", SEEK_MSG }, + { "CMD", CMD_MSG }, + { "RDDATA", RD_DATA_MSG }, + { "WRDATA", WR_DATA_MSG }, + { "STATUS", STATUS_MSG }, + { "FMT", FMT_MSG }, + { "VERBOSE",VERBOSE_MSG }, + { NULL, 0 } +}; + DEVICE wd179x_dev = { - "WD179X", wd179x_unit, wd179x_reg, wd179x_mod, + "WD179X", wd179x_unit, NULL, wd179x_mod, WD179X_MAX_DRIVES, 10, 31, 1, WD179X_MAX_DRIVES, WD179X_MAX_DRIVES, NULL, NULL, &wd179x_reset, NULL, &wd179x_attach, &wd179x_detach, - &wd179x_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, NULL + &wd179x_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + wd179x_dt, NULL, "Western Digital FDC Core WD179X" }; /* Unit service routine */ @@ -247,11 +283,16 @@ extern int32 find_unit_index (UNIT *uptr); void wd179x_external_restore(void) { WD179X_DRIVE_INFO *pDrive; + + if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { + TRACE_PRINT(ERROR_MSG, ("WD179X: " ADDRESS_FORMAT " Illegal drive selected, cannot restore." NLP, PCX)) + return; + } + pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; if(pDrive->uptr == NULL) { - TRACE_PRINT(SEEK_MSG, - ("WD179X: " ADDRESS_FORMAT " No drive selected, cannot restore." NLP, PCX)) + TRACE_PRINT(ERROR_MSG, ("WD179X: " ADDRESS_FORMAT " No drive selected, cannot restore." NLP, PCX)) return; } @@ -290,43 +331,46 @@ t_stat wd179x_attach(UNIT *uptr, char *cptr) if(uptr->capac > 0) { fgets(header, 4, uptr->fileref); - if(!strcmp(header, "IMD")) { - uptr->u3 = IMAGE_TYPE_IMD; - } else if(!strcmp(header, "CPT")) { - printf("CPT images not yet supported\n"); - uptr->u3 = IMAGE_TYPE_CPT; - wd179x_detach(uptr); - return SCPE_OPENERR; - } else { - printf("DSK images not yet supported\n"); - uptr->u3 = IMAGE_TYPE_DSK; - wd179x_detach(uptr); + if(strncmp(header, "IMD", 3)) { + printf("WD179X: Only IMD disk images are supported\n"); + wd179x_info->drive[i].uptr = NULL; return SCPE_OPENERR; } } else { - /* creating file, must be DSK format. */ - printf("Cannot create images, must start with a WD179X IMD image.\n"); - uptr->u3 = IMAGE_TYPE_DSK; - wd179x_detach(uptr); - return SCPE_OPENERR; + /* create a disk image file in IMD format. */ + if (diskCreate(uptr->fileref, "$Id: wd179x.c 1999 2008-07-22 04:25:28Z hharte $") != SCPE_OK) { + printf("WD179X: Failed to create IMD disk.\n"); + wd179x_info->drive[i].uptr = NULL; + return SCPE_OPENERR; + } + uptr->capac = sim_fsize(uptr->fileref); } + uptr->u3 = IMAGE_TYPE_IMD; + if (uptr->flags & UNIT_WD179X_VERBOSE) printf("WD179X%d: attached to '%s', type=%s, len=%d\n", i, cptr, uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", uptr->capac); if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < WD179X_CAPACITY_SSSD) { /*was 318000 but changed to allow 8inch SSSD disks*/ - printf("IMD file too small for use with SIMH.\nCopy an existing file and format it with CP/M.\n"); - } - if (uptr->flags & UNIT_WD179X_VERBOSE) printf("--------------------------------------------------------\n"); - wd179x_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_WD179X_VERBOSE)); - wd179x_info->drive[i].ready = 1; + wd179x_info->drive[i].imd = diskOpen(uptr->fileref, uptr->flags & UNIT_WD179X_VERBOSE); if (uptr->flags & UNIT_WD179X_VERBOSE) printf("\n"); + if (wd179x_info->drive[i].imd == NULL) { + printf("WD179X: IMD disk corrupt.\n"); + wd179x_info->drive[i].uptr = NULL; + return SCPE_OPENERR; + } + + /* Write-protect the unit if IMD think's it's writelocked. */ + if(imdIsWriteLocked(wd179x_info->drive[i].imd)) { + uptr->flags |= UNIT_WD179X_WLK; + } + + wd179x_info->drive[i].ready = 1; } else { wd179x_info->drive[i].imd = NULL; } @@ -347,15 +391,17 @@ t_stat wd179x_detach(UNIT *uptr) i = find_unit_index(uptr); if (i == -1) { - return (SCPE_IERR); + return SCPE_IERR; } DBG_PRINT(("Detach WD179X%d\n", i)); - diskClose(wd179x_info->drive[i].imd); + r = diskClose(&wd179x_info->drive[i].imd); wd179x_info->drive[i].ready = 0; + if (r != SCPE_OK) + return r; r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) + if (r != SCPE_OK) return r; return SCPE_OK; @@ -374,15 +420,29 @@ static int32 wd179xdev(const int32 port, const int32 io, const int32 data) } } -static uint8 floorlog2(unsigned int n) +uint8 floorlog2(unsigned int n) { /* Compute log2(n) */ uint8 r = 0; - if(n >= 1<<16) { n >>=16; r += 16; } - if(n >= 1<< 8) { n >>= 8; r += 8; } - if(n >= 1<< 4) { n >>= 4; r += 4; } - if(n >= 1<< 2) { n >>= 2; r += 2; } - if(n >= 1<< 1) { r += 1; } + if (n >= 1<<16) { + n >>=16; + r += 16; + } + if (n >= 1<< 8) { + n >>= 8; + r += 8; + } + if (n >= 1<< 4) { + n >>= 4; + r += 4; + } + if (n >= 1<< 2) { + n >>= 2; + r += 2; + } + if (n >= 1<< 1) { + r += 1; + } return ((n == 0) ? (0xFF) : r); /* 0xFF is error return value */ } @@ -390,10 +450,14 @@ uint8 WD179X_Read(const uint32 Addr) { uint8 cData; WD179X_DRIVE_INFO *pDrive; - unsigned int flags; + unsigned int flags = 0; unsigned int readlen; int status; + if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { + return 0xFF; + } + pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; if(pDrive->uptr == NULL) { @@ -404,6 +468,17 @@ uint8 WD179X_Read(const uint32 Addr) switch(Addr & 0x3) { case WD179X_STATUS: + /* Fix up status based on Command Type */ + if((wd179x_info->cmdtype == 1) || (wd179x_info->cmdtype == 4)) { + wd179x_info->fdc_status ^= WD179X_STAT_INDEX; /* Generate Index pulses */ + wd179x_info->fdc_status &= ~WD179X_STAT_TRACK0; + wd179x_info->fdc_status |= (pDrive->track == 0) ? WD179X_STAT_TRACK0 : 0; + } else if(wd179x_info->cmdtype == 4) { + } + else { + wd179x_info->fdc_status &= ~WD179X_STAT_INDEX; /* Mask index pulses */ + wd179x_info->fdc_status |= (wd179x_info->drq) ? WD179X_STAT_DRQ : 0; + } cData = (pDrive->ready == 0) ? WD179X_STAT_NOT_READY : 0; cData |= wd179x_info->fdc_status; /* Status Register */ TRACE_PRINT(STATUS_MSG, @@ -443,8 +518,11 @@ uint8 WD179X_Read(const uint32 Addr) /* Compute Sector Size */ wd179x_info->fdc_sec_len = floorlog2( pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len == 0xF8) { /*Error calculating N*/ - printf("Invalid sector size!\n"); + if((wd179x_info->fdc_sec_len == 0xF8) || (wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN)) { /* Error calculating N or N too large */ + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Invalid sector size!" NLP, + wd179x_info->sel_drive, PCX)); + wd179x_info->fdc_sec_len = 0; + return cData; } wd179x_info->fdc_sector ++; @@ -466,9 +544,10 @@ uint8 WD179X_Read(const uint32 Addr) &flags, &readlen); - if(status != -1) { + if(status == SCPE_OK) { wd179x_info->fdc_status = (WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Set DRQ, BUSY */ wd179x_info->drq = 1; + wd179x_info->intrq = 0; wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; wd179x_info->fdc_dataindex = 0; wd179x_info->fdc_read = TRUE; @@ -504,8 +583,13 @@ static uint8 Do1793Command(uint8 cCommand) { uint8 result = 0; WD179X_DRIVE_INFO *pDrive; - unsigned int flags; + unsigned int flags = 0; unsigned int readlen; + int status; + + if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { + return 0xFF; + } pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; @@ -514,12 +598,15 @@ static uint8 Do1793Command(uint8 cCommand) } if(wd179x_info->fdc_status & WD179X_STAT_BUSY) { - if((cCommand & 0xF0) != WD179X_FORCE_INTR) { - printf("WD179X[%d]: ERROR: Command 0x%02x ignored because controller is BUSY\n", wd179x_info->sel_drive, cCommand); + if(((cCommand & 0xF0) != WD179X_FORCE_INTR)) { /* && ((cCommand & 0xF0) != WD179X_RESTORE)) { */ + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " ERROR: Command 0x%02x ignored because controller is BUSY\n" NLP, + wd179x_info->sel_drive, PCX, cCommand)); } return 0xFF; } + wd179x_info->fdc_status &= ~WD179X_STAT_NOT_READY; + /* Extract Type-specific command flags, and set initial conditions */ switch(cCommand & 0xF0) { /* Type I Commands */ @@ -531,6 +618,7 @@ static uint8 Do1793Command(uint8 cCommand) case WD179X_STEP_IN_U: case WD179X_STEP_OUT: case WD179X_STEP_OUT_U: + wd179x_info->cmdtype = 1; wd179x_info->fdc_status |= WD179X_STAT_BUSY; /* Set BUSY */ wd179x_info->fdc_status &= ~(WD179X_STAT_CRC_ERROR | WD179X_STAT_SEEK_ERROR | WD179X_STAT_DRQ); wd179x_info->intrq = 0; @@ -542,6 +630,7 @@ static uint8 Do1793Command(uint8 cCommand) case WD179X_READ_RECS: case WD179X_WRITE_REC: case WD179X_WRITE_RECS: + wd179x_info->cmdtype = 2; wd179x_info->fdc_status = WD179X_STAT_BUSY; /* Set BUSY, clear all others */ wd179x_info->intrq = 0; wd179x_info->hld = 1; /* Load the head immediately, E Flag not checked. */ @@ -550,16 +639,21 @@ static uint8 Do1793Command(uint8 cCommand) case WD179X_READ_ADDR: case WD179X_READ_TRACK: case WD179X_WRITE_TRACK: + wd179x_info->cmdtype = 3; + break; /* Type IV Commands */ case WD179X_FORCE_INTR: + wd179x_info->cmdtype = 4; + break; default: + wd179x_info->cmdtype = 0; break; } switch(cCommand & 0xF0) { /* Type I Commands */ case WD179X_RESTORE: - TRACE_PRINT(CMD_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=RESTORE" NLP, wd179x_info->sel_drive, PCX)); + TRACE_PRINT(CMD_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=RESTORE %s" NLP, wd179x_info->sel_drive, PCX, wd179x_info->verify ? "[VERIFY]" : "")); pDrive->track = 0; wd179x_info->intrq = 1; break; @@ -573,18 +667,21 @@ static uint8 Do1793Command(uint8 cCommand) case WD179X_STEP_U: TRACE_PRINT(SEEK_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=STEP_U dir=%d" NLP, wd179x_info->sel_drive, PCX, wd179x_info->step_dir)); if(wd179x_info->step_dir == 1) { - if(pDrive->track < 255) pDrive->track++; + if (pDrive->track < 255) + pDrive->track++; } else if (wd179x_info->step_dir == -1) { - if(pDrive->track > 0) pDrive->track--; + if (pDrive->track > 0) + pDrive->track--; } else { - printf("WD179X[%d]: Error, undefined direction for STEP\n", wd179x_info->sel_drive); + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " ERROR: undefined direction for STEP" NLP, wd179x_info->sel_drive, PCX)); } break; case WD179X_STEP_IN: TRACE_PRINT(SEEK_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=STEP_IN" NLP, wd179x_info->sel_drive, PCX)); break; case WD179X_STEP_IN_U: - if(pDrive->track < 255) pDrive->track++; + if (pDrive->track < 255) + pDrive->track++; wd179x_info->step_dir = 1; TRACE_PRINT(SEEK_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=STEP_IN_U, Track=%d" NLP, wd179x_info->sel_drive, PCX, pDrive->track)); @@ -596,7 +693,8 @@ static uint8 Do1793Command(uint8 cCommand) case WD179X_STEP_OUT_U: TRACE_PRINT(SEEK_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=STEP_OUT_U" NLP, wd179x_info->sel_drive, PCX)); - if(pDrive->track > 0) pDrive->track--; + if (pDrive->track > 0) + pDrive->track--; wd179x_info->step_dir = -1; break; /* Type II Commands */ @@ -605,8 +703,15 @@ static uint8 Do1793Command(uint8 cCommand) /* Compute Sector Size */ wd179x_info->fdc_sec_len = floorlog2( pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len == 0xF8) { /*Error calculating N*/ - printf("Invalid sector size!\n"); + if((wd179x_info->fdc_sec_len == 0xF8) || (wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN)) { /* Error calculating N or N too large */ + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Invalid sector size!" NLP, + wd179x_info->sel_drive, PCX)); + wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ + wd179x_info->fdc_status &= ~WD179X_STAT_BUSY; + wd179x_info->intrq = 1; + wd179x_info->drq = 0; + wd179x_info->fdc_sec_len = 0; + return 0xFF; } wd179x_info->fdc_multiple = (cCommand & 0x10) ? TRUE : FALSE; @@ -619,44 +724,61 @@ static uint8 Do1793Command(uint8 cCommand) wd179x_info->ddens ? "DD" : "SD", 128 << wd179x_info->fdc_sec_len)); - sectRead(pDrive->imd, - pDrive->track, - wd179x_info->fdc_head, - wd179x_info->fdc_sector, - sdata.raw, - 128 << wd179x_info->fdc_sec_len, - &flags, - &readlen); - if(IMD_MODE_MFM(pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].mode) != (wd179x_info->ddens)) { - printf("Sector not found\n"); wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ + wd179x_info->fdc_status &= ~WD179X_STAT_BUSY; wd179x_info->intrq = 1; + wd179x_info->drq = 0; } else { - wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ - wd179x_info->drq = 1; - wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; - wd179x_info->fdc_dataindex = 0; - wd179x_info->fdc_write = FALSE; - wd179x_info->fdc_read = TRUE; - wd179x_info->fdc_read_addr = FALSE; + + status = sectRead(pDrive->imd, + pDrive->track, + wd179x_info->fdc_head, + wd179x_info->fdc_sector, + sdata.raw, + 128 << wd179x_info->fdc_sec_len, + &flags, + &readlen); + + if(status == SCPE_OK) { + wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ + wd179x_info->drq = 1; + wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; + wd179x_info->fdc_dataindex = 0; + wd179x_info->fdc_write = FALSE; + wd179x_info->fdc_write_track = FALSE; + wd179x_info->fdc_read = TRUE; + wd179x_info->fdc_read_addr = FALSE; + } else { + wd179x_info->fdc_status = 0; /* Clear DRQ, BUSY */ + wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; + wd179x_info->fdc_status &= ~WD179X_STAT_BUSY; + wd179x_info->drq = 0; + wd179x_info->intrq = 1; + wd179x_info->fdc_read = FALSE; + wd179x_info->fdc_read_addr = FALSE; + } } break; case WD179X_WRITE_RECS: - printf("-->> Error: WRITE_RECS not implemented." NLP); + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Error: WRITE_RECS not implemented." NLP, + wd179x_info->sel_drive, PCX)); + break; case WD179X_WRITE_REC: /* Compute Sector Size */ wd179x_info->fdc_sec_len = floorlog2( pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len == 0xF8) { /*Error calculating N*/ - printf("Invalid sector size!\n"); + if((wd179x_info->fdc_sec_len == 0xF8) || (wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN)) { /* Error calculating N or N too large */ + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Invalid sector size!" NLP, + wd179x_info->sel_drive, PCX)); + wd179x_info->fdc_sec_len = 0; } TRACE_PRINT(WR_DATA_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=WRITE_REC, T:%d/S:%d/N:%d, %s." NLP, wd179x_info->sel_drive, PCX, pDrive->track, - cCommand&&0x08, + wd179x_info->fdc_head, wd179x_info->fdc_sector, (cCommand & 0x10) ? "Multiple" : "Single")); wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ @@ -664,6 +786,7 @@ static uint8 Do1793Command(uint8 cCommand) wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; wd179x_info->fdc_dataindex = 0; wd179x_info->fdc_write = TRUE; + wd179x_info->fdc_write_track = FALSE; wd179x_info->fdc_read = FALSE; wd179x_info->fdc_read_addr = FALSE; @@ -678,11 +801,17 @@ static uint8 Do1793Command(uint8 cCommand) wd179x_info->fdc_head, wd179x_info->ddens ? "DD" : "SD")); + /* For some reason 86-DOS tries to use this track, force it to 0. Need to investigate this more. */ + if (pDrive->track == 0xFF) + pDrive->track=0; + /* Compute Sector Size */ wd179x_info->fdc_sec_len = floorlog2( pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len == 0xF8) { /*Error calculating N*/ - printf("Invalid sector size!\n"); + if((wd179x_info->fdc_sec_len == 0xF8) || (wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN)) { /* Error calculating N or N too large */ + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Invalid sector size!" NLP, + wd179x_info->sel_drive, PCX)); + wd179x_info->fdc_sec_len = 0; } if(IMD_MODE_MFM(pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].mode) != (wd179x_info->ddens)) { @@ -710,11 +839,27 @@ static uint8 Do1793Command(uint8 cCommand) break; case WD179X_READ_TRACK: TRACE_PRINT(RD_DATA_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=READ_TRACK" NLP, wd179x_info->sel_drive, PCX)); - printf("-->> Error: READ_TRACK not implemented." NLP); + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Error: READ_TRACK not implemented." NLP, + wd179x_info->sel_drive, PCX)); break; case WD179X_WRITE_TRACK: TRACE_PRINT(WR_DATA_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=WRITE_TRACK" NLP, wd179x_info->sel_drive, PCX)); - printf("-->> Error: WRITE_TRACK not implemented." NLP); + TRACE_PRINT(FMT_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " CMD=WRITE_TRACK, T:%d/S:%d." NLP, + wd179x_info->sel_drive, + PCX, + pDrive->track, + wd179x_info->fdc_head)); + wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ + wd179x_info->drq = 1; + wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; + wd179x_info->fdc_dataindex = 0; + wd179x_info->fdc_write = FALSE; + wd179x_info->fdc_write_track = TRUE; + wd179x_info->fdc_read = FALSE; + wd179x_info->fdc_read_addr = FALSE; + wd179x_info->fdc_fmt_state = FMT_GAP1; /* TRUE when writing an entire track */ + wd179x_info->fdc_fmt_sector_count = 0; + break; /* Type IV Commands */ case WD179X_FORCE_INTR: @@ -724,6 +869,7 @@ static uint8 Do1793Command(uint8 cCommand) wd179x_info->drq = 0; wd179x_info->fdc_write = FALSE; wd179x_info->fdc_read = FALSE; + wd179x_info->fdc_write_track = FALSE; wd179x_info->fdc_read_addr = FALSE; wd179x_info->fdc_datacount = 0; wd179x_info->fdc_dataindex = 0; @@ -735,7 +881,10 @@ static uint8 Do1793Command(uint8 cCommand) if(cCommand & 0x04) { wd179x_info->index_pulse_wait = TRUE; - sim_activate (wd179x_unit, wd179x_info->drivetype == 8 ? 48500 : 58200); /* Generate INDEX pulse */ + if(wd179x_info->sel_drive < WD179X_MAX_DRIVES) { + sim_activate (wd179x_unit, ((wd179x_info->drive[wd179x_info->sel_drive].imd->ntracks % 77) == 0) ? CROMFDC_8IN_ROT : CROMFDC_5IN_ROT); /* Generate INDEX pulse */ +/* printf("Drive %d Num tracks=%d\n", wd179x_info->sel_drive, wd179x_info->drive[wd179x_info->sel_drive].imd->ntracks); */ + } } else { wd179x_info->intrq = 1; } @@ -743,7 +892,8 @@ static uint8 Do1793Command(uint8 cCommand) } break; default: - printf("WD179X[%d]: Unknown WD179X command 0x%02x.\n", wd179x_info->sel_drive, cCommand); + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " ERROR: Unknown command 0x%02x.\n" NLP, + wd179x_info->sel_drive, PCX, cCommand)); break; } @@ -760,9 +910,12 @@ static uint8 Do1793Command(uint8 cCommand) case WD179X_STEP_OUT_U: if(wd179x_info->verify) { /* Verify the selected track/head is ok. */ TRACE_PRINT(SEEK_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Verify ", wd179x_info->sel_drive, PCX)); - if(sectSeek(pDrive->imd, pDrive->track, wd179x_info->fdc_head) != 0) { + if(sectSeek(pDrive->imd, pDrive->track, wd179x_info->fdc_head) != SCPE_OK) { TRACE_PRINT(SEEK_MSG, ("FAILED" NLP)); wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; + } else if(IMD_MODE_MFM(pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].mode) != (wd179x_info->ddens)) { + wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ + TRACE_PRINT(SEEK_MSG, ("NOT FOUND" NLP)); } else { TRACE_PRINT(SEEK_MSG, ("Ok" NLP)); } @@ -796,12 +949,24 @@ static uint8 Do1793Command(uint8 cCommand) return result; } +/* Maximum number of sectors per track for format */ +uint8 max_sectors_per_track[2][7] = { + /* 128, 256, 512, 1024, 2048, 4096, 8192 */ + { 26, 15, 8, 4, 2, 1, 0 }, /* Single-density table */ + { 26, 26, 15, 8, 4, 2, 1 } /* Double-density table */ +}; + uint8 WD179X_Write(const uint32 Addr, uint8 cData) { WD179X_DRIVE_INFO *pDrive; - unsigned int flags; +/* uint8 disk_read = 0; */ + unsigned int flags = 0; unsigned int writelen; + if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { + return 0xFF; + } + pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; if(pDrive->uptr == NULL) { @@ -814,6 +979,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData) ("WD179X: " ADDRESS_FORMAT " WR CMD = 0x%02x" NLP, PCX, cData)) wd179x_info->fdc_read = FALSE; wd179x_info->fdc_write = FALSE; + wd179x_info->fdc_write_track = FALSE; wd179x_info->fdc_datacount = 0; wd179x_info->fdc_dataindex = 0; @@ -842,6 +1008,14 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData) wd179x_info->drq = 0; wd179x_info->intrq = 1; + TRACE_PRINT(WR_DATA_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Writing sector, T:%d/S:%d/N:%d, Len=%d" NLP, + wd179x_info->sel_drive, + PCX, + pDrive->track, + wd179x_info->fdc_head, + wd179x_info->fdc_sector, + 128 << wd179x_info->fdc_sec_len)); + sectWrite(pDrive->imd, pDrive->track, wd179x_info->fdc_head, @@ -855,6 +1029,122 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData) } } } + + if(wd179x_info->fdc_write_track == TRUE) { +/* TRACE_PRINT(FMT_MSG, */ +/* ("WD179X: " ADDRESS_FORMAT " FMT DATA[%d] = 0x%02x" NLP, PCX, wd179x_info->fdc_fmt_state, cData)); */ + + if(wd179x_info->fdc_fmt_state == FMT_GAP1) { + if(cData != 0xFC) { + wd179x_info->fdc_gap[0]++; + } else { + TRACE_PRINT(VERBOSE_MSG, + ("WD179X: " ADDRESS_FORMAT " FMT GAP1 Length = %d" NLP, PCX, wd179x_info->fdc_gap[0])); + wd179x_info->fdc_gap[1] = 0; + wd179x_info->fdc_fmt_state = FMT_GAP2; + } + } else if(wd179x_info->fdc_fmt_state == FMT_GAP2) { + if(cData != 0xFE) { + wd179x_info->fdc_gap[1]++; + } else { + TRACE_PRINT(VERBOSE_MSG, + ("WD179X: " ADDRESS_FORMAT " FMT GAP2 Length = %d" NLP, PCX, wd179x_info->fdc_gap[1])); + wd179x_info->fdc_gap[2] = 0; + wd179x_info->fdc_fmt_state = FMT_HEADER; + wd179x_info->fdc_header_index = 0; + } + } else if(wd179x_info->fdc_fmt_state == FMT_HEADER) { + if(wd179x_info->fdc_header_index == 5) { + wd179x_info->fdc_gap[2] = 0; + wd179x_info->fdc_fmt_state = FMT_GAP3; + } else { + TRACE_PRINT(VERBOSE_MSG, + ("WD179X: " ADDRESS_FORMAT " HEADER[%d]=%02x" NLP, PCX, wd179x_info->fdc_header_index, cData)); + switch(wd179x_info->fdc_header_index) { + case 0: + pDrive->track = cData; + break; + case 1: + wd179x_info->fdc_head = cData; + break; + case 2: + wd179x_info->fdc_sector = cData; + break; + case 3: + if(cData != 0x00) { + } + break; + case 4: + if(cData != 0xF7) { + } + break; + } + wd179x_info->fdc_header_index++; + } + } else if(wd179x_info->fdc_fmt_state == FMT_GAP3) { + if(cData != 0xFB) { + wd179x_info->fdc_gap[2]++; + } else { + TRACE_PRINT(VERBOSE_MSG, + ("WD179X: " ADDRESS_FORMAT " FMT GAP3 Length = %d" NLP, PCX, wd179x_info->fdc_gap[2])); + wd179x_info->fdc_fmt_state = FMT_DATA; + wd179x_info->fdc_dataindex = 0; + } + } else if(wd179x_info->fdc_fmt_state == FMT_DATA) { /* data bytes */ + if(cData != 0xF7) { + sdata.raw[wd179x_info->fdc_dataindex] = cData; + wd179x_info->fdc_dataindex++; + } else { + wd179x_info->fdc_sec_len = floorlog2(wd179x_info->fdc_dataindex) - 7; + if((wd179x_info->fdc_sec_len == 0xF8) || (wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN)) { /* Error calculating N or N too large */ + TRACE_PRINT(ERROR_MSG, ("WD179X[%d]: " ADDRESS_FORMAT " Invalid sector size!" NLP, + wd179x_info->sel_drive, PCX)); + wd179x_info->fdc_sec_len = 0; + } + if(wd179x_info->fdc_fmt_sector_count >= WD179X_MAX_SECTOR) { + TRACE_PRINT(ERROR_MSG, ("WD179X: " ADDRESS_FORMAT " Illegal sector count" NLP, PCX)); + wd179x_info->fdc_fmt_sector_count = 0; + } + wd179x_info->fdc_sectormap[wd179x_info->fdc_fmt_sector_count] = wd179x_info->fdc_sector; + wd179x_info->fdc_fmt_sector_count++; + TRACE_PRINT(VERBOSE_MSG, + ("WD179X: " ADDRESS_FORMAT " FMT Data Length = %d" NLP, PCX, wd179x_info->fdc_dataindex)); + + TRACE_PRINT(FMT_MSG, + ("WD179X: " ADDRESS_FORMAT " FORMAT T:%d/H:%d/N:%d=%d/L=%d[%d] Fill=0x%02x" NLP, PCX, + pDrive->track, + wd179x_info->fdc_head, + wd179x_info->fdc_fmt_sector_count, + wd179x_info->fdc_sectormap[wd179x_info->fdc_fmt_sector_count], + wd179x_info->fdc_dataindex, + wd179x_info->fdc_sec_len, + sdata.raw[0])); + + wd179x_info->fdc_gap[1] = 0; + wd179x_info->fdc_fmt_state = FMT_GAP2; + + if(wd179x_info->fdc_fmt_sector_count == max_sectors_per_track[wd179x_info->ddens & 1][wd179x_info->fdc_sec_len]) { + trackWrite(pDrive->imd, + pDrive->track, + wd179x_info->fdc_head, + wd179x_info->fdc_fmt_sector_count, + wd179x_info->fdc_sec_len, + wd179x_info->fdc_sectormap, + wd179x_info->ddens ? 3 : 0, /* data mode */ + sdata.raw[0], + &flags); + + wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY | WD179X_STAT_LOST_DATA); /* Clear BUSY, LOST_DATA */ + wd179x_info->drq = 0; + wd179x_info->intrq = 1; + + /* Recalculate disk size */ + pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref); + } + } + } + } + wd179x_info->fdc_data = cData; break; } diff --git a/GRI/gri_cpu.c b/GRI/gri_cpu.c index 8f86b9e8..547b2139 100644 --- a/GRI/gri_cpu.c +++ b/GRI/gri_cpu.c @@ -421,7 +421,8 @@ ao_update (); /* update AO */ while (reason == 0) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; } if (bkp) { /* breakpoint? */ @@ -435,7 +436,8 @@ while (reason == 0) { /* loop until halted */ int32 i, vec; t = dev_done & ISR; /* find hi pri */ for (i = 15; i >= 0; i--) { - if ((t >> i) & 1) break; + if ((t >> i) & 1) + break; } if ((i < 0) || ((vec = vec_map[i]) < 0)) { /* undefined? */ reason = STOP_ILLINT; /* stop */ @@ -471,7 +473,8 @@ while (reason == 0) { /* loop until halted */ 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? */ + if ((t ^ op) & 1) /* skip? */ + SC = SC + 2; SC = (SC + 1) & AMASK; /* incr SC */ } @@ -555,7 +558,8 @@ while (reason == 0) { /* loop until halted */ MA = IDX_ADD (MA); /* index? */ SC = (SC + 1) & AMASK; /* incr SC again */ t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; + if (MEM_ADDR_OK (MA)) + M[MA] = t; MA = IDX_ADD (t); /* index? */ reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ break; @@ -569,7 +573,8 @@ while (reason == 0) { /* loop until halted */ case MEM_IDF: /* immediate defer */ MA = SC; /* get ind addr */ t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; + if (MEM_ADDR_OK (MA)) + M[MA] = t; MA = IDX_ADD (t); /* index? */ SC = (SC + 1) & AMASK; /* incr SC again */ reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ @@ -592,30 +597,35 @@ 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? */ +if (op & BUS_COM) /* complement? */ + t = t ^ DMASK; 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 */ + if (t & CBIT) /* set cry out */ + MSR = MSR | MSR_BOV; 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 */ + if (t & CBIT) /* set link out */ + MSR = MSR | MSR_L; 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 */ + if (old_t & 1) /* set link out */ + MSR = MSR | MSR_L; else MSR = MSR & ~MSR_L; break; } /* end case op */ -if (dst == thwh) DR = t & DMASK; /* display dst? */ +if (dst == thwh) /* display dst? */ + DR = t & DMASK; return dev_tab[dst].Dst (dst, t & DMASK); /* store dst */ } @@ -670,7 +680,8 @@ switch (op & 3) { /* FOM link */ break; } -if (op & 4) return STOP_HALT; /* HALT */ +if (op & 4) /* HALT */ + return STOP_HALT; return SCPE_OK; } @@ -678,7 +689,8 @@ 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? */ + ((op & 2) && (MSR & MSR_BOV))) /* BOV set? */ + return 1; return 0; } @@ -691,7 +703,8 @@ return IR; t_stat ir_fo (uint32 op) { -if (op & 2) bkp = 1; +if (op & 2) + bkp = 1; return SCPE_OK; } @@ -723,8 +736,10 @@ return SCPE_OK; t_stat isr_fo (uint32 op) { -if (op & ISR_ON) dev_done = (dev_done | INT_ON) & ~INT_NODEF; -if (op & ISR_OFF) dev_done = dev_done & ~INT_ON; +if (op & ISR_ON) + dev_done = (dev_done | INT_ON) & ~INT_NODEF; +if (op & ISR_OFF) + dev_done = dev_done & ~INT_ON; return SCPE_OK; } @@ -750,7 +765,8 @@ return M[MA]; t_stat mem_wr (uint32 dst, uint32 dat) { -if (MEM_ADDR_OK (MA)) M[MA] = dat; +if (MEM_ADDR_OK (MA)) + M[MA] = dat; return SCPE_OK; } @@ -814,7 +830,8 @@ switch (af) { break; } -if ((AX + AY) & CBIT) MSR = MSR | MSR_AOV; /* always calc AOV */ +if ((AX + AY) & CBIT) /* always calc AOV */ + MSR = MSR | MSR_AOV; else MSR = MSR & ~MSR_AOV; if (SIGN & ((AX ^ (AX + AY)) & (~AX ^ AY))) /* always calc SOV */ MSR = MSR | MSR_SOV; @@ -824,7 +841,8 @@ return AO; uint32 ax_rd (uint32 src) { -if (cpu_unit.flags & UNIT_AO) return AX; +if (cpu_unit.flags & UNIT_AO) + return AX; else return 0; } @@ -840,7 +858,8 @@ return stop_opr; uint32 ay_rd (uint32 src) { -if (cpu_unit.flags & UNIT_AO) return AY; +if (cpu_unit.flags & UNIT_AO) + return AY; else return 0; } @@ -856,7 +875,8 @@ return stop_opr; uint32 ao_rd (uint32 src) { -if (cpu_unit.flags & UNIT_AO) return ao_update (); +if (cpu_unit.flags & UNIT_AO) + return ao_update (); else return 0; } @@ -876,7 +896,8 @@ uint32 ao_sf (uint32 op) if (!(cpu_unit.flags & UNIT_AO)) /* not installed? */ return (stop_opr << SF_V_REASON); if (((op & 2) && (MSR & MSR_AOV)) || /* arith carry? */ - ((op & 4) && (MSR & MSR_SOV))) return 1; /* arith overflow? */ + ((op & 4) && (MSR & MSR_SOV))) /* arith overflow? */ + return 1; return 0; } @@ -908,7 +929,8 @@ switch (op) { case EAO_ARS: /* arith right? */ t = 0; /* shift limiter */ - if (AX & SIGN) MSR = MSR | MSR_L; /* L = sign */ + if (AX & SIGN) /* L = sign */ + MSR = MSR | MSR_L; else MSR = MSR & ~MSR_L; do { /* shift one bit */ AY = ((AY >> 1) | (AX << 15)) & DMASK; @@ -938,7 +960,8 @@ return SCPE_OK; uint32 xr_rd (uint32 src) { -if (cpu_unit.flags & UNIT_GRI99) return XR; +if (cpu_unit.flags & UNIT_GRI99) + return XR; else return 0; } @@ -955,7 +978,8 @@ return stop_opr; uint32 atrp_rd (uint32 src) { -if (cpu_unit.flags & UNIT_GRI99) return TRP; +if (cpu_unit.flags & UNIT_GRI99) + return TRP; else return 0; } @@ -972,7 +996,8 @@ return stop_opr; uint32 bsw_rd (uint32 src) { -if (cpu_unit.flags & UNIT_BSWPK) return BSW; +if (cpu_unit.flags & UNIT_BSWPK) + return BSW; else return 0; } @@ -989,7 +1014,8 @@ return stop_opr; uint32 bpk_rd (uint32 src) { -if (cpu_unit.flags & UNIT_BSWPK) return BPK; +if (cpu_unit.flags & UNIT_BSWPK) + return BPK; else return 0; } @@ -1006,7 +1032,8 @@ return stop_opr; uint32 gr_rd (uint32 src) { -if (cpu_unit.flags & UNIT_GPR) return GR[src - U_GR]; +if (cpu_unit.flags & UNIT_GPR) + return GR[src - U_GR]; else return 0; } @@ -1032,10 +1059,12 @@ ISR = 0; MSR = 0; MA = IR = 0; BSW = BPK = 0; -for (i = 0; i < 6; i++) GR[i] = 0; +for (i = 0; i < 6; i++) + GR[i] = 0; dev_done = dev_done & ~INT_PENDING; scq_r = find_reg ("SCQ", NULL, dptr); -if (scq_r) scq_r->qptr = 0; +if (scq_r) + scq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1045,8 +1074,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & DMASK; return SCPE_OK; } @@ -1054,7 +1085,8 @@ 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 & DMASK; return SCPE_OK; } @@ -1066,10 +1098,12 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } diff --git a/GRI/gri_stddev.c b/GRI/gri_stddev.c index 0d773160..412cc200 100644 --- a/GRI/gri_stddev.c +++ b/GRI/gri_stddev.c @@ -224,15 +224,18 @@ return SCPE_OK; t_stat tty_fo (uint32 op) { -if (op & TTY_IRDY) dev_done = dev_done & ~INT_TTI; -if (op & TTY_ORDY) dev_done = dev_done & ~INT_TTO; +if (op & TTY_IRDY) + dev_done = dev_done & ~INT_TTI; +if (op & TTY_ORDY) + dev_done = dev_done & ~INT_TTO; return SCPE_OK; } uint32 tty_sf (uint32 op) { if (((op & TTY_IRDY) && (dev_done & INT_TTI)) || - ((op & TTY_ORDY) && (dev_done & INT_TTO))) return 1; + ((op & TTY_ORDY) && (dev_done & INT_TTO))) + return 1; return 0; } @@ -243,8 +246,10 @@ t_stat tti_svc (UNIT *uptr) int32 c; sim_activate (uptr, uptr->wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; +if (c & SCPE_BREAK) /* break? */ + uptr->buf = 0; else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); dev_done = dev_done | INT_TTI; /* set ready */ uptr->pos = uptr->pos + 1; @@ -310,16 +315,20 @@ return SCPE_OK; t_stat hsrp_fo (uint32 op) { -if (op & PT_IRDY) dev_done = dev_done & ~INT_HSR; -if (op & PT_ORDY) dev_done = dev_done & ~INT_HSP; -if (op & PT_STRT) sim_activate (&hsr_unit, hsr_unit.wait); +if (op & PT_IRDY) + dev_done = dev_done & ~INT_HSR; +if (op & PT_ORDY) + dev_done = dev_done & ~INT_HSP; +if (op & PT_STRT) + sim_activate (&hsr_unit, hsr_unit.wait); return SCPE_OK; } uint32 hsrp_sf (uint32 op) { if (((op & PT_IRDY) && (dev_done & INT_HSR)) || - ((op & PT_ORDY) && (dev_done & INT_HSP))) return 1; + ((op & PT_ORDY) && (dev_done & INT_HSP))) + return 1; return 0; } @@ -331,7 +340,8 @@ 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"); + if (hsr_stopioe) + printf ("HSR end of file\n"); else return SCPE_OK; } else perror ("HSR I/O error"); @@ -380,23 +390,27 @@ return SCPE_OK; t_stat rtc_fo (int32 op) { -if (op & RTC_OFF) sim_cancel (&rtc_unit); /* clock off? */ +if (op & RTC_OFF) /* clock off? */ + sim_cancel (&rtc_unit); 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_OV) /* clr ovflo? */ + dev_done = dev_done & ~INT_RTC; return SCPE_OK; } uint32 rtc_sf (int32 op) { -if ((op & RTC_OV) && (dev_done & INT_RTC)) return 1; +if ((op & RTC_OV) && (dev_done & INT_RTC)) + return 1; return 0; } t_stat rtc_svc (UNIT *uptr) { M[RTC_CTR] = (M[RTC_CTR] + 1) & DMASK; /* incr counter */ -if (M[RTC_CTR] == 0) dev_done = dev_done | INT_RTC; /* ovflo? set ready */ +if (M[RTC_CTR] == 0) /* ovflo? set ready */ + dev_done = dev_done | INT_RTC; sim_activate (&rtc_unit, sim_rtc_calb (rtc_tps)); /* reactivate */ return SCPE_OK; } diff --git a/GRI/gri_sys.c b/GRI/gri_sys.c index afceb2e3..5bb5c227 100644 --- a/GRI/gri_sys.c +++ b/GRI/gri_sys.c @@ -93,19 +93,23 @@ 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 */ + if (r != SCPE_OK) + return r; + if (*cptr != 0) /* no more */ + return SCPE_ARG; } else org = 0200; /* default 200 */ for (;;) { /* until EOF */ while ((c = getc (fileref)) == 0) ; /* skip starting 0's */ - if (c == EOF) break; /* EOF? done */ + if (c == EOF) /* EOF? done */ + break; 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; + 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 */ @@ -114,7 +118,8 @@ for (;;) { /* until EOF */ 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; + if (!(sim_switches & SWMASK ('C'))) + return SCPE_OK; } /* end tape for */ return SCPE_OK; } @@ -293,12 +298,14 @@ 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); + if (nfirst) + fputc (' ', of); nfirst = 1; fprintf (of, "%s", fname[i]); } } -if (op) fprintf (of, " %o", op); +if (op) + fprintf (of, " %o", op); return; } @@ -335,7 +342,8 @@ uint32 inst, src, dst, op, bop; inst = val[0]; if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } @@ -344,7 +352,8 @@ if (sw & SWMASK ('C')) { /* characters? */ fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; /* Instruction decode */ @@ -382,27 +391,30 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ 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]); + 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]); + 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]); + unsrc[src], undst[dst]); } break; case F_V_ZR: /* zero reg */ - if (bop) fprintf (of, "%s %s,%s", opcode[i], - opname[bop], undst[dst]); + 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,", - opcode[i], unsrc[src], cdname[op >> 1]); + opcode[i], unsrc[src], cdname[op >> 1]); fprint_addr (of, val[1], 0, U_SC); break; @@ -412,14 +424,16 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ break; case F_V_RM: /* reg mem */ - if (bop) fprintf (of, "%s %s,%s,", - opcode[i], unsrc[src], opname[bop]); + if (bop) + fprintf (of, "%s %s,%s,", + opcode[i], unsrc[src], opname[bop]); else fprintf (of, "%s %s,", opcode[i], unsrc[src]); fprint_addr (of, val[1], op & MEM_MOD, dst); break; case F_V_ZM: /* zero mem */ - if (bop) fprintf (of, "%s %s,", opcode[i], opname[bop]); + if (bop) + fprintf (of, "%s %s,", opcode[i], opname[bop]); else fprintf (of, "%s ", opcode[i]); fprint_addr (of, val[1], op & MEM_MOD, dst); break; @@ -427,14 +441,16 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ case F_V_MR: /* mem reg */ fprintf (of, "%s ", opcode[i]); fprint_addr (of, val[1], op & MEM_MOD, dst); - if (bop) fprintf (of, ",%s,%s", opname[bop], undst[dst]); + if (bop) + fprintf (of, ",%s,%s", opname[bop], undst[dst]); else fprintf (of, ",%s", undst[dst]); break; case F_V_MS: /* mem self */ fprintf (of, "%s ", opcode[i]); fprint_addr (of, val[1], op & MEM_MOD, dst); - if (bop) fprintf (of, ",%s", opname[bop]); + if (bop) + fprintf (of, ",%s", opname[bop]); break; } /* end case */ @@ -465,7 +481,8 @@ 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? */ + if (d & fncm) /* already filled? */ + return NULL; fncv = fncv | d; /* save */ fncm = fncm | d; /* field filled */ } @@ -473,13 +490,15 @@ while (*cptr) { 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? */ + if (fop[i].oper & fncm) /* already filled? */ + return NULL; fncm = fncm | fop[i].omask; fncv = fncv | fop[i].oper; break; } } - if (fname[i] == NULL) return NULL; + if (fname[i] == NULL) + return NULL; } /* end else */ } /* end while */ val[0] = val[0] | (fncv << I_V_OP); /* store fnc */ @@ -496,7 +515,8 @@ cptr = get_glyph (cptr, gbuf, term); /* get glyph */ if (gbuf[0] == '#') /* indexed? */ d = get_uint (gbuf + 1, 8, AMASK, &r) | INDEX; /* [0, 77777] */ else d = get_uint (gbuf, 8, DMASK, &r); /* [0,177777] */ -if (r != SCPE_OK) return NULL; +if (r != SCPE_OK) + return NULL; val[1] = d; /* second wd */ return cptr; } @@ -510,11 +530,13 @@ 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; + (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; + if (r != SCPE_OK) + return NULL; } val[0] = val[0] | (d << (src? I_V_SRC: I_V_DST)); /* or to inst */ return cptr; @@ -554,14 +576,15 @@ char *tptr, gbuf[CBUFSIZE]; while (isspace (*cptr)) cptr++; /* absorb spaces */ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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); + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; + val[0] = (((t_value) cptr[0] & 0177) << 8) | ((t_value) cptr[1] & 0177); return SCPE_OK; } @@ -569,7 +592,8 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ 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; +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 */ @@ -577,10 +601,12 @@ switch (j) { /* case on class */ case F_V_FO: /* func out */ tptr = strchr (cptr, ','); /* find dst */ - if (!tptr) return SCPE_ARG; /* none? */ + if (!tptr) /* none? */ + return SCPE_ARG; *tptr = 0; /* split fields */ cptr = get_fnc (cptr, val); /* fo # */ - if (!cptr) return SCPE_ARG; + if (!cptr) + return SCPE_ARG; cptr = get_sd (tptr + 1, val, 0, FALSE); /* dst */ break; @@ -590,7 +616,8 @@ switch (j) { /* case on class */ case F_V_SF: /* skip func */ cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; + if (!cptr) + return SCPE_ARG; case F_V_SFI: /* skip func impl */ cptr = get_fnc (cptr, val); /* fo # */ @@ -598,33 +625,40 @@ switch (j) { /* case on class */ case F_V_RR: /* reg-reg */ cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; + if (!cptr) + return SCPE_ARG; cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; + 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; + 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; + 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; + 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 (strcmp (gbuf, cdname[k]) == 0) + break; } - if (k >= 8) return SCPE_ARG; + if (k >= 8) + return SCPE_ARG; val[0] = val[0] | (k << (I_V_OP + 1)); /* or to inst */ case F_V_JU: /* jump uncond */ @@ -633,28 +667,34 @@ switch (j) { /* case on class */ case F_V_RM: /* reg mem */ cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; + if (!cptr) + return SCPE_ARG; case F_V_ZM: /* zero mem */ cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; + 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; + if (!cptr) + return SCPE_ARG; cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; + 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; + 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? */ +if (!cptr || (*cptr != 0)) /* junk at end? */ + return SCPE_ARG; return (j >= F_2WD)? -1: SCPE_OK; } diff --git a/H316/h316_cpu.c b/H316/h316_cpu.c index 07778cb5..d336ee4a 100644 --- a/H316/h316_cpu.c +++ b/H316/h316_cpu.c @@ -1,6 +1,6 @@ /* h316_cpu.c: Honeywell 316/516 CPU simulator - Copyright (c) 1999-2007, Robert M. Supnik + Copyright (c) 1999-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -393,7 +393,8 @@ int32 Operate (int32 MB, int32 AR); /* Restore register state */ -if (devtab_init ()) return SCPE_STOP; /* init tables */ +if (devtab_init ()) /* init tables */ + return SCPE_STOP; AR = saved_AR & DMASK; /* restore reg */ BR = saved_BR & DMASK; XR = saved_XR & DMASK; @@ -405,7 +406,8 @@ reason = 0; while (reason == 0) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; } /* Channel breaks (DMA and DMC) */ @@ -416,9 +418,11 @@ if (chan_req) { /* channel request? */ 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; + if (iotab[dev] == &undio) + return SCPE_IERR; chan_req = chan_req & ~(1 << i); /* clear req */ - if (Q_DMA (i)) st = dma_ad[i]; /* DMA? */ + if (Q_DMA (i)) /* DMA? */ + st = dma_ad[i]; else { /* DMC */ dmcad = DMC_BASE + ((i - DMC_V_DMC1) << 1); st = Read (dmcad); /* DMC ctrl word */ @@ -426,14 +430,18 @@ if (chan_req) { /* channel request? */ 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) != 0) return r; + if ((t & IOT_SKIP) == 0) + return STOP_DMAER; + if ((r = t >> IOT_V_REASON) != 0) + 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 ((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); @@ -441,7 +449,8 @@ if (chan_req) { /* channel request? */ 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) != 0) return r; + if ((r = t >> IOT_V_REASON) != 0) + return r; } } else { /* DMC */ @@ -450,7 +459,8 @@ if (chan_req) { /* channel request? */ 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) != 0) return r; + if ((r = t >> IOT_V_REASON) != 0) + return r; } /* end if end range */ } /* end else DMC */ } /* end if chan i */ @@ -462,7 +472,8 @@ if (chan_req) { /* channel request? */ 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 */ + if (cpu_unit.flags & UNIT_EXT) /* ext opt? extend on */ + ext = 1; dev_int = dev_int & ~INT_ON; /* intr off */ MB = 0120000 | M_INT; /* inst = JST* 63 */ } @@ -485,7 +496,8 @@ 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; + 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; @@ -498,14 +510,17 @@ if (hst_lnt) { /* instr hist? */ 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 */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; PCQ_ENTRY; /* save PC */ PC = NEWA (PC, Y); /* set new PC */ - if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */ + if (extoff_pending) /* cond ext off */ + ext = extoff_pending = 0; break; case 002: case 022: case 042: case 062: /* LDA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; if (dp) { /* double prec? */ AR = Read (Y & ~1); /* get doubleword */ BR = Read (Y | 1); @@ -515,12 +530,14 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 003: case 023: case 043: case 063: /* ANA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; AR = AR & Read (Y); break; case 004: case 024: case 044: case 064: /* STA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; Write (Y, AR); /* store A */ if (dp) { /* double prec? */ Write (Y | 1, BR); /* store B */ @@ -529,12 +546,14 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 005: case 025: case 045: case 065: /* ERA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; AR = AR ^ Read (Y); break; case 006: case 026: case 046: case 066: /* ADD */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; if (dp) { /* double prec? */ t1 = GETDBL_S (AR, BR); /* get A'B */ t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); @@ -546,7 +565,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 007: case 027: case 047: case 067: /* SUB */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; if (dp) { /* double prec? */ t1 = GETDBL_S (AR, BR); /* get A'B */ t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); @@ -558,7 +578,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 010: case 030: case 050: case 070: /* JST */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; MB = NEWA (Read (Y), PC); /* merge old PC */ Write (Y, MB); PCQ_ENTRY; @@ -566,39 +587,48 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 011: case 031: case 051: case 071: /* CAS */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; MB = Read (Y); - if (AR == MB) PC = NEWA (PC, PC + 1); - else if (SEXT (AR) < SEXT (MB)) PC = NEWA (PC, PC + 2); + 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 */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */ Write (Y, MB); - if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */ + if (MB == 0) /* skip if zero */ + PC = NEWA (PC, PC + 1); break; case 013: case 033: case 053: case 073: /* IMA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; 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 */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; Write (Y, XR); /* store XR */ break; case 035: case 075: /* LDX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; 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 */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; t1 = SEXT (AR) * SEXT (Read (Y)); PUTDBL_S (t1); sc = 0; @@ -608,14 +638,16 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ case 017: case 037: case 057: case 077: /* DIV */ if (cpu_unit.flags & UNIT_HSA) { /* installed? */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (reason = Ea (MB, &Y)) /* eff addr */ + break; 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; + if ((t1 > MMASK) || (t1 < (-SIGN))) + C = 1; else C = 0; sc = 0; } @@ -636,15 +668,18 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ 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? */ + if (t2 & IOT_SKIP) /* skip? */ + PC = NEWA (PC, PC + 1); break; case 054: /* INA */ dev = MB & DEVMASK; - if (MB & INCLRA) AR = 0; + 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? */ + if (t2 & IOT_SKIP) /* skip? */ + PC = NEWA (PC, PC + 1); AR = t2 & DMASK; /* data */ break; @@ -652,30 +687,35 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ 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? */ + if (t2 & IOT_SKIP) /* skip? */ + PC = NEWA (PC, PC + 1); break; /* Control */ case 000: if ((MB & 1) == 0) { /* HLT */ - if ((reason = sim_process_event ()) != SCPE_OK) break; + if ((reason = sim_process_event ()) != SCPE_OK) + break; reason = STOP_HALT; break; } if (MB & m14) { /* SGL, DBL */ - if (cpu_unit.flags & UNIT_HSA) dp = (MB & m15)? 1: 0; + 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; + 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 & m12) /* RMP */ + CLR_INT (INT_MPE); if (MB & m11) { /* SCA, INK */ if (MB & m15) /* INK */ AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037); @@ -732,22 +772,26 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ case 020: C = 0; /* clear C */ sc = 0; /* clear sc */ - if ((t1 = (-MB) & SHFMASK) == 0) break; /* shift count */ + if ((t1 = (-MB) & SHFMASK) == 0) /* shift count */ + break; switch (I_GETFNC (MB)) { /* case shift fnc */ case 000: /* LRL */ - if (t1 > 32) ut = 0; /* >32? all 0 */ + if (t1 > 32) /* >32? all 0 */ + ut = 0; else { ut = GETDBL_U (AR, BR); /* get A'B */ C = (ut >> (t1 - 1)) & 1; /* C = last out */ - if (t1 == 32) ut = 0; /* =32? all 0 */ + if (t1 == 32) /* =32? all 0 */ + ut = 0; else ut = ut >> t1; /* log right */ } PUTDBL_U (ut); /* store A,B */ break; case 001: /* LRS */ - if (t1 > 31) t1 = 31; /* limit to 31 */ + if (t1 > 31) /* limit to 31 */ + t1 = 31; t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */ C = (t2 >> (t1 - 1)) & 1; /* C = last out */ t2 = t2 >> t1; /* arith right */ @@ -763,7 +807,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 003: /* "long right arot" */ - if (reason = stop_inst) break; /* stop on undef? */ + if (reason = stop_inst) /* stop on undef? */ + break; for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ C = BR & 1; /* C = last out */ BR = (BR & SIGN) | ((AR & 1) << 14) | @@ -773,7 +818,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 004: /* LGR */ - if (t1 > 16) AR = 0; /* > 16? all 0 */ + if (t1 > 16) /* > 16? all 0 */ + AR = 0; else { C = (AR >> (t1 - 1)) & 1; /* C = last out */ AR = (AR >> t1) & DMASK; /* log right */ @@ -781,7 +827,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 005: /* ARS */ - if (t1 > 16) t1 = 16; /* limit to 16 */ + if (t1 > 16) /* limit to 16 */ + t1 = 16; C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */ AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */ break; @@ -793,7 +840,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 007: /* "short right arot" */ - if (reason = stop_inst) break; /* stop on undef? */ + if (reason = stop_inst) /* stop on undef? */ + break; for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ C = AR & 1; /* C = last out */ AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); @@ -801,18 +849,21 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 010: /* LLL */ - if (t1 > 32) ut = 0; /* > 32? all 0 */ + if (t1 > 32) /* > 32? all 0 */ + ut = 0; else { ut = GETDBL_U (AR, BR); /* get A'B */ C = (ut >> (32 - t1)) & 1; /* C = last out */ - if (t1 == 32) ut = 0; /* =32? all 0 */ + if (t1 == 32) /* =32? all 0 */ + ut = 0; else ut = ut << t1; /* log left */ } PUTDBL_U (ut); /* store A,B */ break; case 011: /* LLS */ - if (t1 > 31) t1 = 31; /* limit to 31 */ + if (t1 > 31) /* limit to 31 */ + t1 = 31; t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */ t3 = t2 << t1; /* "arith" left */ PUTDBL_S (t3); /* store A'B */ @@ -829,7 +880,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 013: /* "long left arot" */ - if (reason = stop_inst) break; /* stop on undef? */ + if (reason = stop_inst) /* stop on undef? */ + break; for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ AR = (AR << 1) | ((BR >> 14) & 1); BR = (BR & SIGN) | ((BR << 1) & MMASK) | @@ -840,7 +892,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 014: /* LGL */ - if (t1 > 16) AR = 0; /* > 16? all 0 */ + if (t1 > 16) /* > 16? all 0 */ + AR = 0; else { C = (AR >> (16 - t1)) & 1; /* C = last out */ AR = (AR << t1) & DMASK; /* log left */ @@ -848,7 +901,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 015: /* ALS */ - if (t1 > 16) t1 = 16; /* limit to 16 */ + if (t1 > 16) /* limit to 16 */ + t1 = 16; t2 = SEXT (AR); /* save AR */ AR = (AR << t1) & DMASK; /* "arith" left */ if ((t2 >> (16 - t1)) != /* shf out + sgn */ @@ -862,7 +916,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ break; case 017: /* "short left arot" */ - if (reason = stop_inst) break; /* stop on undef? */ + if (reason = stop_inst) /* stop on undef? */ + break; for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ if ((AR & SIGN) != ((AR << 1) & SIGN)) C = 1; AR = ((AR << 1) | (AR >> 15)) & DMASK; @@ -883,38 +938,54 @@ switch (I_GETOP (MB)) { /* case on <1:6> */ ((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? */ + ((MB & 000400) && (AR & SIGN))) /* SMI */ + skip = 1; + if ((MB & 001000) == 0) /* reverse? */ + skip = skip ^ 1; 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 */ + if (MB == 0140024) /* CHS */ + AR = AR ^ SIGN; + else if (MB == 0140040) /* CRA */ + AR = 0; + else if (MB == 0140100) /* SSP */ + AR = AR & ~SIGN; + else if (MB == 0140200) /* RCB */ + C = 0; else if (MB == 0140320) { /* CSA */ C = (AR & SIGN) >> 15; AR = AR & ~SIGN; } - else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */ + else if (MB == 0140401) /* CMA */ + AR = AR ^ DMASK; 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 == 0140500) /* SSM */ + AR = AR | SIGN; + else if (MB == 0140600) /* SCB */ + C = 1; + else if (MB == 0141044) /* CAR */ + AR = AR & 0177400; + else if (MB == 0141050) /* CAL */ + AR = AR & 0377; + else if (MB == 0141140) /* ICL */ + AR = AR >> 8; + else if (MB == 0141206) /* AOA */ + AR = Add16 (AR, 1); + else if (MB == 0141216) /* ACA */ + AR = Add16 (AR, C); + else if (MB == 0141240) /* ICR */ + AR = (AR << 8) & DMASK; else if (MB == 0141340) /* ICA */ AR = ((AR << 8) | (AR >> 8)) & DMASK; - else if (reason = stop_inst) break; + else if (reason = stop_inst) + break; else AR = Operate (MB, AR); /* undefined */ break; } /* end case op */ @@ -967,7 +1038,8 @@ if (hst_lnt) { /* history? */ hst[hst_p].ea = Y; hst[hst_p].opnd = Read (Y); } -if (i >= ind_max) return STOP_IND; /* too many ind? */ +if (i >= ind_max) + return STOP_IND; /* too many ind? */ return SCPE_OK; } @@ -986,7 +1058,8 @@ int32 Add16 (int32 v1, int32 v2) { int32 r = v1 + v2; -if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1; +if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) + C = 1; else C = 0; return (r & DMASK); } @@ -995,7 +1068,8 @@ int32 Add31 (int32 v1, int32 v2) { int32 r = v1 + v2; -if (((v1 ^ ~v2) & (v1 ^ r)) & DP_SIGN) C = 1; +if (((v1 ^ ~v2) & (v1 ^ r)) & DP_SIGN) + C = 1; else C = 0; return r; } @@ -1028,7 +1102,8 @@ switch (inst) { /* case on opcode */ case ioINA: /* INA */ if ((fnc >= 011) && (fnc <= 014)) { - if (dma_eor[ch]) return dat; /* end range? nop */ + if (dma_eor[ch]) /* end range? nop */ + return dat; return IOSKIP (0100000 | dma_wc[ch]); /* return range */ } else return IOBADFNC (dat); @@ -1121,7 +1196,8 @@ 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 */ +if (jamkn) /* jammin? xor */ + D = aleg ^ bleg; else D = (aleg + bleg + eiki7) & DMASK; /* else add */ /* Possible repeat at end of tlate - special t2, repeat tlate */ @@ -1150,13 +1226,20 @@ 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 (clatr) /* clear A */ + ARx = 0; +if (cla1r) /* clear A1 */ + ARx = ARx & ~SIGN; +if (edahs) /* D hi to A hi */ + ARx = ARx | (D & 0177400); +if (edals) /* D lo to A lo */ + ARx = ARx | (D & 0000377); +if (etahs) /* D lo to A hi */ + ARx = ARx | ((D << 8) & 0177400); +if (etals) /* D hi to A lo */ + ARx = ARx | ((D >> 8) & 0000377); +if (eda1r) /* D1 to A1 */ + ARx = ARx | (D & SIGN); if (cbitl) { /* ovflo to C */ /* Overflow calculation. Cases: @@ -1171,11 +1254,13 @@ if (cbitl) { /* ovflo to C */ */ 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 == 0077777)) || + (!bleg && eiki7 && (D == 0100000)))) + C = 1; + else C = 0; + } +if (cbite || (cbitg && (D & SIGN))) /* C = 1 */ + C = 1; return ARx; } @@ -1191,10 +1276,12 @@ dp = 0; ext = pme = extoff_pending = 0; dev_int = dev_int & ~(INT_PEND|INT_NMI); dev_enb = 0; -for (i = 0; i < DMA_MAX; i++) dma_ad[i] = dma_wc[i] = dma_eor[i] = 0; +for (i = 0; i < DMA_MAX; i++) + dma_ad[i] = dma_wc[i] = dma_eor[i] = 0; chan_req = 0; pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1206,10 +1293,13 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { int32 d; -if (addr >= MEMSIZE) return SCPE_NXM; -if (addr == 0) d = saved_XR; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (addr == 0) + d = saved_XR; else d = M[addr]; -if (vptr != NULL) *vptr = d & DMASK; +if (vptr != NULL) + *vptr = d & DMASK; return SCPE_OK; } @@ -1217,8 +1307,10 @@ 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 == 0) saved_XR = val & DMASK; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (addr == 0) + saved_XR = val & DMASK; else M[addr] = val & DMASK; return SCPE_OK; } @@ -1227,7 +1319,8 @@ return SCPE_OK; t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (MEMSIZE > (NX_AMASK + 1)) return SCPE_ARG; +if (MEMSIZE > (NX_AMASK + 1)) + return SCPE_ARG; return SCPE_OK; } @@ -1239,11 +1332,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) || (((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1)))) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } @@ -1252,9 +1347,11 @@ t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc) uint32 i, newmax; t_stat r; -if (cptr == NULL) return SCPE_ARG; +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? */ +if ((r != SCPE_OK) || (newmax == dma_nch)) /* err or no chg? */ + return r; 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; @@ -1267,7 +1364,8 @@ return SCPE_OK; t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (dma_nch) fprintf (st, "DMA channels = %d", dma_nch); +if (dma_nch) + fprintf (st, "DMA channels = %d", dma_nch); else fprintf (st, "no DMA channels"); return SCPE_OK; } @@ -1276,7 +1374,8 @@ return SCPE_OK; t_stat cpu_show_dma (FILE *st, UNIT *uptr, int32 val, void *desc) { -if ((val < 0) || (val >= DMA_MAX)) return SCPE_IERR; +if ((val < 0) || (val >= DMA_MAX)) + return SCPE_IERR; fputs ((dma_ad[val] & DMA_IN)? "Input": "Output", st); fprintf (st, ", addr = %06o, count = %06o, ", dma_ad[val] & X_AMASK, dma_wc[val]); fprintf (st, "end of range %s\n", (dma_eor[val]? "set": "clear")); @@ -1290,11 +1389,14 @@ t_stat io_set_iobus (UNIT *uptr, int32 val, char *cptr, void *desc) DEVICE *dptr; DIB *dibp; -if (val || cptr || (uptr == NULL)) return SCPE_IERR; +if (val || cptr || (uptr == NULL)) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; dibp->chan = 0; return SCPE_OK; } @@ -1306,14 +1408,19 @@ DIB *dibp; uint32 newc; t_stat r; -if ((cptr == NULL) || (uptr == NULL)) return SCPE_IERR; +if ((cptr == NULL) || (uptr == NULL)) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -if (dma_nch == 0) return SCPE_NOFNC; +if (dibp == NULL) + return SCPE_IERR; +if (dma_nch == 0) + return SCPE_NOFNC; newc = get_uint (cptr, 10, DMA_MAX, &r); /* get new */ -if ((r != SCPE_OK) || (newc == 0) || (newc > dma_nch)) return SCPE_ARG; +if ((r != SCPE_OK) || (newc == 0) || (newc > dma_nch)) + return SCPE_ARG; dibp->chan = (newc - DMA_MIN) + DMA_V_DMA1 + 1; /* store */ return SCPE_OK; } @@ -1325,14 +1432,19 @@ DIB *dibp; uint32 newc; t_stat r; -if ((cptr == NULL) || (uptr == NULL)) return SCPE_IERR; +if ((cptr == NULL) || (uptr == NULL)) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +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; +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 */ -if ((r != SCPE_OK) || (newc == 0)) return SCPE_ARG; +if ((r != SCPE_OK) || (newc == 0)) + return SCPE_ARG; dibp->chan = (newc - DMC_MIN) + DMC_V_DMC1 + 1; /* store */ return SCPE_OK; } @@ -1344,12 +1456,16 @@ t_stat io_show_chan (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -if (dibp->chan == 0) fprintf (st, "IO bus"); +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); else fprintf (st, "DMC channel %d", dibp->chan - DMC_V_DMC1); @@ -1364,19 +1480,22 @@ DEVICE *dptr; DIB *dibp; 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; 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? */ + if ((dibp == NULL) || (dptr->flags & DEV_DIS)) /* exist, enabled? */ + continue; 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); + 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 */ @@ -1385,33 +1504,34 @@ for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */ 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); + 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)); + 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); + 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; + if (iotab[i] == NULL) + iotab[i] = &undio; } return FALSE; } @@ -1424,12 +1544,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -1438,7 +1560,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -1459,14 +1582,17 @@ static uint8 has_opnd[16] = { 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) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ @@ -1474,14 +1600,16 @@ for (k = 0; k < lnt; k++) { /* print specified */ 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); + 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); + if (has_opnd[op]) + fprintf (st, " [%06o]", h->opnd); fputc ('\n', st); /* end line */ } /* end else instruction */ } /* end for */ diff --git a/H316/h316_defs.h b/H316/h316_defs.h index 510ee6ac..409342d1 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-2005, Robert M. Supnik + Copyright (c) 1999-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/H316/h316_dp.c b/H316/h316_dp.c index f90ceeb8..0a8df9af 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-2005, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -389,11 +389,13 @@ switch (inst) { /* case on opcode */ break; case FNC_RDS: /* read status */ - if (dp_sta & STA_BUSY) return dat; /* ignore if busy */ + if (dp_sta & STA_BUSY) /* ignore if busy */ + return dat; 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 */ + if (dp_dma && Q_DMA (ch)) /* DMA? set chan req */ + SET_CH_REQ (ch); break; case FNC_DMA: /* set DMA/DMC */ @@ -414,7 +416,8 @@ switch (inst) { /* case on opcode */ break; case ioINA: /* INA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (fnc) /* fnc 0 only */ + return IOBADFNC (dat); if (dp_sta & STA_RDY) { /* ready? */ dp_sta = dp_sta & ~STA_RDY; /* clear ready */ return IOSKIP (dat | dp_buf); /* ret buf, skip */ @@ -422,12 +425,15 @@ switch (inst) { /* case on opcode */ break; case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (fnc) /* fnc 0 only */ + return IOBADFNC (dat); 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? */ + if (dp_otas == OTA_CW1) /* expecting CW1? */ + dp_go1 (dat); + else if (dp_otas == OTA_CW2) /* expecting CW2? */ + dp_go2 (dat); return IOSKIP (dat); } break; @@ -437,23 +443,28 @@ switch (inst) { /* case on opcode */ switch (fnc) { case 000: /* ready */ - if (dp_sta & STA_RDY) return IOSKIP (dat); + if (dp_sta & STA_RDY) + return IOSKIP (dat); break; case 001: /* !interrupting */ - if (!TST_INTREQ (INT_DP)) return IOSKIP (dat); + if (!TST_INTREQ (INT_DP)) + return IOSKIP (dat); break; case 002: /* operational */ - if (!(dp_sta & (STA_BUSY | STA_ALLERR))) return IOSKIP (dat); + if (!(dp_sta & (STA_BUSY | STA_ALLERR))) + return IOSKIP (dat); break; case 003: /* !error */ - if (!(dp_sta & STA_ALLERR)) return IOSKIP (dat); + if (!(dp_sta & STA_ALLERR)) + return IOSKIP (dat); break; case 004: /* !busy */ - if (!(dp_sta & STA_BUSY)) return IOSKIP (dat); + if (!(dp_sta & STA_BUSY)) + return IOSKIP (dat); break; case 011: case 012: case 013: /* !not seeking 0-6 */ @@ -481,7 +492,8 @@ t_stat dp_go (uint32 fnc) { int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ -if (dp_sta & STA_BUSY) return SCPE_OK; /* ignore if busy */ +if (dp_sta & STA_BUSY) /* ignore if busy */ + return SCPE_OK; dp_fnc = fnc; /* save function */ dp_xip = 0; /* transfer not started */ dp_eor = 0; /* not end of range */ @@ -530,7 +542,8 @@ switch (dp_fnc) { /* case on function */ 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 */ + if (dp_dma && Q_DMA (ch)) /* DMA? set chan request */ + SET_CH_REQ (ch); break; } @@ -571,9 +584,11 @@ 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 */ + if (dp_cw1 & CW1_DIR) /* get desired cyl */ + dcyl = uptr->CYL - offs; else dcyl = uptr->CYL + offs; - if ((offs == 0) || (dcyl < 0) || + if ((offs == 0) || + (dcyl < 0) || (dcyl >= (int32) dp_tab[dp_ctype].cyl)) return dp_done (1, STA_SEKER); /* bad seek? */ @@ -581,13 +596,15 @@ switch (uptr->FNC) { /* case on function */ 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; + 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 */ + if (dp_sta & STA_BUSY) /* busy? queue intr */ + dp_defint = 1; else SET_INT (INT_DP); /* no, req intr */ return SCPE_OK; @@ -629,7 +646,8 @@ switch (uptr->FNC) { /* case on function */ */ case FNC_FMT: /* format */ - for (i = 0; i < DP_TRKLEN; i++) dpxb[i] = 0; /* clear track */ + for (i = 0; i < DP_TRKLEN; i++) /* clear track */ + dpxb[i] = 0; dp_xip = dp_xip | XIP_FMT; /* format in progress */ dp_rptr = 0; /* init record ptr */ dp_gap = 0; /* no gap before first */ @@ -646,7 +664,8 @@ switch (uptr->FNC) { /* case on function */ 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 */ + if (dp_dma) /* DMA/DMC? intr */ + SET_INT (INT_DP); } break; /* set up next word */ @@ -664,7 +683,8 @@ switch (uptr->FNC) { /* case on function */ } if (dp_eor) { /* record done? */ dp_eor = 0; /* clear for restart */ - if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */ + if (dp_dma) /* DMA/DMC? intr */ + SET_INT (INT_DP); 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 */ @@ -715,7 +735,8 @@ switch (uptr->FNC) { /* case on function */ 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 */ + if (dp_dma) /* if DMA/DMC, req chan */ + SET_CH_REQ (ch); } else if (Q_DMA (ch)) /* read; DMA? */ dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ @@ -727,7 +748,8 @@ switch (uptr->FNC) { /* case on function */ 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 (r = dp_wrwd (uptr, dp_buf)) /* wr word, error? */ + return r; if (dp_eor) { /* transfer done? */ dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; return dp_wrdone (uptr, 0); /* clear busy, intr req */ @@ -739,8 +761,7 @@ switch (uptr->FNC) { /* case on function */ 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)); + (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 */ @@ -752,7 +773,8 @@ switch (uptr->FNC) { /* case on function */ } /* end case */ dp_sta = dp_sta | STA_RDY; /* set ready */ -if (dp_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ +if (dp_dma) /* if DMA/DMC, req chan */ + SET_CH_REQ (ch); sim_activate (uptr, dp_xtime); /* schedule word */ return SCPE_OK; } @@ -766,7 +788,8 @@ int32 l; 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; +for ( ; l < DP_TRKLEN; l++) + buf[l] = 0; if (ferror (uptr->fileref)) { perror ("DP I/O error"); clearerr (uptr->fileref); @@ -800,9 +823,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; + 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; @@ -827,7 +853,8 @@ if (dp_wptr < (lnt + REC_MAXEXT)) { } 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 */ +if (r = dp_wrdone (uptr, STA_UNSER)) /* dump track */ + return r; return STOP_DPOVR; } @@ -845,7 +872,8 @@ 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 */ +if (req || dp_defint) /* if req, set intr */ + SET_INT (INT_DP); dp_defint = 0; /* clr def intr */ return SCPE_OK; } @@ -886,7 +914,8 @@ t_stat dp_attach (UNIT *uptr, char *cptr) { t_stat r; r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; return dp_showformat (stdout, uptr, 0, NULL); } @@ -896,7 +925,8 @@ t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 i; -if ((val < 0) || (val >= DP_NUMTYP) || (cptr != NULL)) return SCPE_ARG; +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; } @@ -910,7 +940,8 @@ return SCPE_OK; t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (dp_ctype >= DP_NUMTYP) return SCPE_IERR; +if (dp_ctype >= DP_NUMTYP) + return SCPE_IERR; fprintf (st, "%s", dp_tab[dp_ctype].name); return SCPE_OK; } @@ -945,29 +976,37 @@ uint16 tbuf[DP_TRKLEN]; float finp; t_stat r; -if (uptr == NULL) return SCPE_IERR; -if (cptr == NULL) return SCPE_ARG; -if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; +if (uptr == NULL) + return SCPE_IERR; +if (cptr == NULL) + return SCPE_ARG; +if (!(uptr->flags & UNIT_ATT)) + return SCPE_UNATT; inp = (int32) get_uint (cptr, 10, 2048, &r); -if (r != SCPE_OK) return r; -if (inp == 0) return SCPE_ARG; +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; + 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 (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; 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; + for (i = 0; i < DP_TRKLEN; i++) + tbuf[i] = 0; rptr = 0; for (i = 0; i < nr; i++) { tbuf[rptr + REC_LNT] = nw & DMASK; @@ -976,7 +1015,8 @@ for (c = cntr = 0; c < dp_tab[dp_ctype].cyl; c++) { 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; + if (r = dp_wrtrk (uptr, tbuf, c, h)) + return r; } } printf ("Formatting complete\n"); @@ -995,16 +1035,19 @@ uint32 maxsec = 0; uint16 tbuf[DP_TRKLEN]; t_stat r; -if (uptr == NULL) return SCPE_IERR; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; +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; + 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); + if (c || h) + fprintf (st, "Unformatted track, cyl = %d, head = %d\n", c, h); else fprintf (st, "Disk is unformatted\n"); return SCPE_OK; } @@ -1019,26 +1062,29 @@ for (c = 0; c < dp_tab[dp_ctype].cyl; c++) { tbuf[rptr + REC_EXT], c, h, sec); return SCPE_OK; } - if (rlnt > maxrec) maxrec = rlnt; - if (rlnt < minrec) minrec = rlnt; + 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 (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); -else if (minrec == maxrec) fprintf (st, - "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); -else fprintf (st, - "Valid variable format, records/track = %d-%d, record sizes = %d-%d\n", - minsec, maxsec, minrec, maxrec); +if ((minrec == maxrec) && (minsec == maxsec)) + fprintf (st, "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); +else if (minsec == maxsec) + fprintf (st, "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); return SCPE_OK; } diff --git a/H316/h316_fhd.c b/H316/h316_fhd.c index f27061a5..df2c9aac 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-2006, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -186,24 +186,30 @@ switch (inst) { /* case on opcode */ 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 if (fnc == 003) /* start, DMA */ + fhd_go (1); + else if (fnc == 007) /* start, IO bus */ + fhd_go (0); else return IOBADFNC (dat); break; case ioOTA: /* output */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fnc) /* only fnc 0 */ + return IOBADFNC (dat); 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? */ + if (fhd_otas == OTA_CW1) /* expecting CW1? */ + fhd_go1 (dat); + else if (fhd_otas == OTA_CW2) /* expecting CW2? */ + fhd_go2 (dat); else fhd_rdy = 0; /* normal, clr ready */ return IOSKIP (dat); } break; case ioINA: /* input */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fnc) /* only fnc 0 */ + return IOBADFNC (dat); if (fhd_rdy) { /* ready? */ fhd_rdy = 0; /* clear ready */ return IOSKIP (dat | fhd_buf); /* return data */ @@ -233,13 +239,15 @@ void fhd_go (uint32 dma) { int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ -if (fhd_busy) return; /* ignore if busy */ +if (fhd_busy) /* ignore if busy */ + return; 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? */ +if (ch >= 0) /* DMA allowed? */ + fhd_dma = dma; else fhd_dma = 0; /* no, force IO bus */ fhd_otas = OTA_CW1; /* expect CW1 */ fhd_rdy = 1; /* set ready */ @@ -259,7 +267,8 @@ 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 */ +if (fhd_dma && Q_DMA (ch)) /* DMA? set chan request */ + SET_CH_REQ (ch); return; } @@ -284,7 +293,8 @@ if ((wa >= FH_NUMWD) || /* if bad char addr */ } if (fhd_cw1 & CW1_RW) { /* write? */ fhd_rdy = 1; /* set ready */ - if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ + if (fhd_dma) /* if DMA/DMC, req chan */ + SET_CH_REQ (ch); } else { fhd_rdy = 0; /* read, clear ready */ @@ -292,7 +302,8 @@ else { 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? */ +if (t < 0) /* wrap around? */ + t = t + FH_NUMWD; sim_activate (&fhd_unit, t * fhd_time); /* schedule op */ return; } @@ -312,7 +323,8 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ } if (fhd_eor || fhd_rdy) { /* done or ready set? */ - if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */ + if (fhd_rdy) /* if ready set, data err */ + fhd_dte = 1; if (fhd_cw1 & CW1_RW) { /* write? */ if (!fhd_rdy) { /* buffer full? */ fhd_putc (uptr, fhd_buf >> 8); /* store last word */ @@ -322,7 +334,8 @@ if (fhd_eor || fhd_rdy) { /* done or ready set? */ } else { /* read */ fhd_getc (uptr, &c1); /* get csum */ - if (fhd_csum) fhd_dte = 1; /* if csum != 0, err */ + if (fhd_csum) /* if csum != 0, err */ + fhd_dte = 1; } fhd_busy = 0; /* operation complete */ SET_INT (INT_FHD); @@ -330,17 +343,22 @@ if (fhd_eor || fhd_rdy) { /* done or ready set? */ } 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; + 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; +else { /* read */ + if (fhd_getc (uptr, &c1)) + return SCPE_OK; + 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_dma) /* if DMA/DMC, req chan */ + SET_CH_REQ (ch); return SCPE_OK; } @@ -356,9 +374,11 @@ 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? */ +if (fhd_bad_wa (wa)) /* addr bad? */ + return TRUE; fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ -if (ca & 1) wd = fbuf[ba] & 0377; /* select char */ +if (ca & 1) /* select char */ + wd = fbuf[ba] & 0377; else wd = (fbuf[ba] >> 8) & 0377; fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */ *ch = wd; /* return */ @@ -377,12 +397,15 @@ 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? */ +if (fhd_bad_wa (wa)) /* addr bad? */ + return TRUE; fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ -if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */ +if (ca & 1) /* odd? low char */ + fbuf[ba] = (fbuf[ba] & ~0377) | ch; 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 */ +if (ba >= uptr->hwmark) /* update hwmark */ + uptr->hwmark = ba + 1; return FALSE; } @@ -436,7 +459,8 @@ uint32 ds_bytes = FH_WDPSF * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { sf = (sz + ds_bytes - 1) / ds_bytes; - if (sf >= FH_NUMSF) sf = FH_NUMSF - 1; + if (sf >= FH_NUMSF) + sf = FH_NUMSF - 1; uptr->flags = (uptr->flags & ~UNIT_SF) | (sf << UNIT_V_SF); } @@ -448,8 +472,10 @@ return attach_unit (uptr, cptr); t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (val < 0) + return SCPE_IERR; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = UNIT_GETSF (val) * FH_WDPSF; return SCPE_OK; } diff --git a/H316/h316_lp.c b/H316/h316_lp.c index 48c95264..809e3b3c 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-2007, Robert M. Supnik + Copyright (c) 1999-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -161,11 +161,13 @@ switch (inst) { /* case on opcode */ 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 */ + if (ch >= 0) /* try for DMA/DMC */ + lpt_dma = 1; else lpt_dma = 0; if (!sim_is_active (&lpt_unit)) { lpt_rdy = 1; - if (lpt_dma) SET_CH_REQ (ch); + if (lpt_dma) + SET_CH_REQ (ch); } CLR_INT (INT_LPT); /* clear int */ break; @@ -175,7 +177,8 @@ switch (inst) { /* case on opcode */ lpt_wdpos = 0; /* init scan pos */ lpt_eor = 0; lpt_dma = 0; /* IO bus */ - if (!sim_is_active (&lpt_unit)) lpt_rdy = 1; + if (!sim_is_active (&lpt_unit)) + lpt_rdy = 1; CLR_INT (INT_LPT); /* clear int */ break; @@ -188,43 +191,53 @@ switch (inst) { /* case on opcode */ switch (fnc) { /* case on fnc */ case 000: /* if xfer rdy */ - if (lpt_rdy) return IOSKIP (dat); + if (lpt_rdy) + return IOSKIP (dat); break; case 002: /* if !alarm */ - if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); + if (lpt_unit.flags & UNIT_ATT) + return IOSKIP (dat); break; case 003: /* if odd col */ - if (lpt_crpos) return IOSKIP (dat); + if (lpt_crpos) + return IOSKIP (dat); break; case 004: /* if !interrupt */ - if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat); + if (!TST_INTREQ (INT_LPT)) + return IOSKIP (dat); break; case 011: /* if line printed */ - if (lpt_prdn) return IOSKIP (dat); + if (lpt_prdn) + return IOSKIP (dat); break; case 012: /* if !shuttling */ - if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); + if (!(lpt_svcst & LPT_SVCSH)) + return IOSKIP (dat); break; case 013: - if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); + if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) + return IOSKIP (dat); break; case 014: /* if !advancing */ - if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); + if (!(lpt_svcst & LPT_SVCPA)) + return IOSKIP (dat); break; case 015: - if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); + if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) + return IOSKIP (dat); break; case 016: - if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat); + if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) + return IOSKIP (dat); break; case 017: @@ -238,12 +251,14 @@ switch (inst) { /* case on opcode */ break; case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fnc) /* only fnc 0 */ + return IOBADFNC (dat); 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; + if (chr < 040) + chr = chr | 0100; lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; } lpt_wdpos++; /* adv scan pos */ @@ -287,24 +302,26 @@ static const char *lpt_cc[] = { 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 */ + if (lpt_eor) /* end range? intr */ + SET_INT (INT_LPT); 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) { /* done shuttling? */ for (i = LPT_WIDTH - 1; i >= 0; i--) { /* backscan for blanks */ - if (lpt_buf[i] != ' ') break; + if (lpt_buf[i] != ' ') + break; } lpt_buf[i + 1] = 0; fputs (lpt_buf, uptr->fileref); /* output buf */ uptr->pos = ftell (uptr->fileref); /* update pos */ - for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */ + for (i = 0; i < LPT_WIDTH; i++) /* clear buf */ + lpt_buf[i] = ' '; lpt_prdn = 1; /* print done */ } } @@ -329,7 +346,8 @@ 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++) /* clear buffer */ + lpt_buf[i] = ' '; lpt_buf[LPT_WIDTH] = 0; CLR_INT (INT_LPT); /* clear int, enb */ CLR_ENB (INT_LPT); diff --git a/H316/h316_mt.c b/H316/h316_mt.c index 46ac60c3..6ec7e6df 100644 --- a/H316/h316_mt.c +++ b/H316/h316_mt.c @@ -1,6 +1,6 @@ /* h316_mt.c: H316/516 magnetic tape simulator - Copyright (c) 2003-2007, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -197,7 +197,8 @@ switch (inst) { /* case on opcode */ 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 */ + if (mt_dib.chan) /* set DMA if configured */ + mt_dma = 1; else mt_dma = 0; break; @@ -220,7 +221,8 @@ switch (inst) { /* case on opcode */ 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 (sim_is_active (uptr)) /* nop if busy */ + return dat; if (wrt_fnc[fnc] && sim_tape_wrp (uptr)) return ((STOP_MTWRP << IOT_V_REASON) | dat); uptr->FNC = fnc; @@ -234,7 +236,8 @@ switch (inst) { /* case on opcode */ break; case ioINA: /* INA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (fnc) /* fnc 0 only */ + return IOBADFNC (dat); if (mt_rdy) { /* ready? */ mt_rdy = 0; /* clear ready */ return IOSKIP (dat | mt_buf); /* ret buf, skip */ @@ -242,7 +245,8 @@ switch (inst) { /* case on opcode */ break; case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (fnc) /* fnc 0 only */ + return IOBADFNC (dat); if (mt_rdy) { /* ready? */ mt_rdy = 0; /* clear ready */ mt_buf = dat; /* store buf */ @@ -255,15 +259,18 @@ switch (inst) { /* case on opcode */ switch (fnc) { case 000: /* ready */ - if (mt_rdy) return IOSKIP (dat); + if (mt_rdy) + return IOSKIP (dat); break; case 001: /* !busy */ - if (!mt_busy) return IOSKIP (dat); + if (!mt_busy) + return IOSKIP (dat); break; case 002: /* !error */ - if (!mt_err) return IOSKIP (dat); + if (!mt_err) + return IOSKIP (dat); break; case 003: /* !BOT */ @@ -271,24 +278,28 @@ switch (inst) { /* case on opcode */ break; case 004: /* !interrupting */ - if (!TST_INTREQ (INT_MT)) return IOSKIP (dat); + if (!TST_INTREQ (INT_MT)) + return IOSKIP (dat); break; case 005: /* !EOT */ - if (!(uptr->UST & STA_EOT)) return IOSKIP (dat); + if (!(uptr->UST & STA_EOT)) + return IOSKIP (dat); break; case 006: /* !EOF */ - if (!mt_eof) return IOSKIP (dat); + if (!mt_eof) + return IOSKIP (dat); break; case 007: /* !write prot */ - if (!sim_tape_wrp (uptr)) return IOSKIP (dat); + 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); + if ((uptr->flags & UNIT_ATT) && ((uptr->FNC & 017) != FNC_REW)) + return IOSKIP (dat); break; case 012: /* skip if !chan 2 */ @@ -299,7 +310,8 @@ switch (inst) { /* case on opcode */ case 014: /* !rewinding */ uptr = mt_dev.units + (dev & 03); /* use specified unit */ - if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat); + if ((uptr->FNC & 017) != FNC_REW) + return IOSKIP (dat); break; } break; @@ -349,7 +361,8 @@ switch (uptr->FNC) { /* case on function */ 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; + if ((mt_unit[i].FNC & 017) == FNC_REW) + return SCPE_OK; } mt_updint (mt_rdy, 1); /* yes, motion done */ return SCPE_OK; @@ -399,7 +412,8 @@ switch (uptr->FNC) { /* case on function */ 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? */ + if (mt_ptr >= mt_max) /* record done? */ + break; c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */ c2 = mtxb[mt_ptr++] & 077; if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */ @@ -412,17 +426,20 @@ switch (uptr->FNC) { /* case on function */ } else c3 = 0; sim_activate (uptr, mt_xtime); /* no, sched word */ - if (mt_eor) return SCPE_OK; /* xfer done? */ + if (mt_eor) /* xfer done? */ + return SCPE_OK; 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 */ + if (mt_dma) /* DMC/DMA? req chan */ + SET_CH_REQ (ch); 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 */ + if (mt_dma) /* DMC/DMA? req chan */ + SET_CH_REQ (ch); uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ sim_activate (uptr, mt_xtime); /* sched xfer */ return SCPE_OK; /* continue */ @@ -431,7 +448,8 @@ switch (uptr->FNC) { /* case on function */ 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_rdy) /* write last word */ + mt_wrwd (uptr, mt_buf); else mt_rdy = 0; /* rdy must be clr */ if (mt_ptr) { /* any data? */ if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */ @@ -442,7 +460,8 @@ switch (uptr->FNC) { /* case on function */ 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 */ + if (mt_dma) /* DMC/DMA? req chan */ + SET_CH_REQ (ch); return SCPE_OK; /* continue */ default: /* unknown */ @@ -473,13 +492,18 @@ uint32 c1, c2; 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 (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 (mt_ptr < DBSIZE) /* store 2 char */ + mtxb[mt_ptr++] = c1; +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; + (mt_ptr < DBSIZE)) + mtxb[mt_ptr++] = mt_buf & 017; return; } @@ -505,7 +529,8 @@ switch (st) { case MTSE_IOERR: /* IO error */ mt_err = 1; /* error */ - if (mt_stopioe) return SCPE_IOERR; + if (mt_stopioe) + return SCPE_IOERR; break; case MTSE_RECE: /* record in error */ @@ -531,7 +556,8 @@ 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 */ +if ((mt_rdy && !mt_dma) || mt_mdirq) /* update int request */ + SET_INT (INT_MT); else CLR_INT (INT_MT); return; } @@ -571,7 +597,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 */ +if (r != SCPE_OK) /* update status */ + return r; uptr->UST = STA_BOT; return r; } diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index 45652777..456df262 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -1,6 +1,6 @@ /* h316_stddev.c: Honeywell 316/516 standard devices - Copyright (c) 1999-2007, Robert M. Supnik + Copyright (c) 1999-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -315,21 +315,25 @@ 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 */ + if (fnc & 016) /* only fnc 0,1 */ + return IOBADFNC (dat); ptr_motion = fnc ^ 1; - if (fnc) sim_cancel (&ptr_unit); /* fnc 1? stop */ + if (fnc) /* fnc 1? stop */ + sim_cancel (&ptr_unit); 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 & 013) /* only fnc 0,4 */ + return IOBADFNC (dat); 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 (fnc) /* only fnc 0 */ + return IOBADFNC (dat); if (TST_INT (INT_PTR)) { /* ready? */ CLR_INT (INT_PTR); /* clear ready */ if (ptr_motion) /* if motion, restart */ @@ -357,7 +361,8 @@ if (uptr->STA & LF_PEND) { /* lf pending? */ else { if ((c = getc (uptr->fileref)) == EOF) { /* read byte */ if (feof (uptr->fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); @@ -383,8 +388,10 @@ t_stat pt_attach (UNIT *uptr, char *cptr) { t_stat r; -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; -if (r = attach_unit (uptr, cptr)) return 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 */ @@ -457,7 +464,8 @@ 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 & 016) /* only fnc 0,1 */ + return IOBADFNC (dat); if (fnc) { /* fnc 1? pwr off */ CLR_INT (INT_PTP); /* not ready */ ptp_power = 0; /* turn off power */ @@ -478,7 +486,8 @@ switch (inst) { /* case on opcode */ break; case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fnc) /* only fnc 0 */ + return IOBADFNC (dat); if (TST_INT (INT_PTP)) { /* if ptp ready */ CLR_INT (INT_PTP); /* clear ready */ ptp_unit.buf = dat & 0377; /* store byte */ @@ -508,7 +517,8 @@ 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 if (c == 012) /* lf? cvt to nl */ + c = '\n'; } else c = uptr->buf & 0377; /* no, binary */ if (putc (c, uptr->fileref) == EOF) { /* output byte */ @@ -540,7 +550,8 @@ 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 & 016) /* only fnc 0,1 */ + return IOBADFNC (dat); if (fnc && (tty_mode == 0)) { /* input to output? */ if (!sim_is_active (&tty_unit[TTO])) /* set ready */ SET_INT (INT_TTY); @@ -553,7 +564,8 @@ switch (inst) { /* case on opcode */ break; case ioSKS: /* SKS */ - if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */ + if (fnc & 012) /* fnc 0,1,4,5 */ + return IOBADFNC (dat); 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]))) || @@ -564,21 +576,25 @@ switch (inst) { /* case on opcode */ break; case ioINA: /* INA */ - if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */ + if (fnc & 005) /* only 0,2 */ + return IOBADFNC (dat); if (TST_INT (INT_TTY)) { /* ready? */ - if (tty_mode == 0) CLR_INT (INT_TTY); /* inp? clear rdy */ + if (tty_mode == 0) /* inp? clear rdy */ + CLR_INT (INT_TTY); return IOSKIP (dat | (tty_buf & ((fnc & 002)? 077: 0377))); } break; case ioOTA: - if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */ + if (fnc & 015) /* only 0,2 */ + return IOBADFNC (dat); 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_buf & 040) + tty_buf = tty_buf & 0277; } if (tty_mode) { sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); @@ -602,11 +618,13 @@ 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? */ + if (c & SCPE_BREAK) /* break? */ + c = 0; else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); uptr->pos = uptr->pos + 1; } -else if (c != SCPE_OK) return c; /* error? */ +else if (c != SCPE_OK) /* error? */ + return c; else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ (ruptr->STA & RUNNING)) { /* and running? */ if (ruptr->STA & LF_PEND) { /* lf pending? */ @@ -617,7 +635,8 @@ else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ 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"); + if (ttr_stopioe) + printf ("TTR end of file\n"); else return SCPE_OK; } else perror ("TTR I/O error"); @@ -633,12 +652,14 @@ else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ ruptr->pos = ftell (ruptr->fileref); } if (ttr_xoff_read != 0) { /* reader stopping? */ - if (c == RUBOUT) ttr_xoff_read = 0; /* rubout? stop */ + if (c == RUBOUT) /* rubout? stop */ + ttr_xoff_read = 0; 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? */ + else if ((c & 0177) == XOFF) /* XOFF read? */ + ttr_xoff_read = 2; out = c; /* echo char */ } else return SCPE_OK; /* no char */ @@ -665,12 +686,15 @@ if (ttp_tape_rcvd != 0) { /* prev = tape? */ 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? */ +else if (c7b == TAPE) /* char = TAPE? */ + ttp_tape_rcvd = 2; if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */ ttp_xoff_rcvd--; /* decrement state */ - if (ttp_xoff_rcvd == 0) puptr->STA &= ~RUNNING; /* stop after delay */ + if (ttp_xoff_rcvd == 0) /* stop after delay */ + puptr->STA &= ~RUNNING; } -else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */ +else if (c7b == XOFF) /* char = XOFF? */ + ttp_xoff_rcvd = 2; if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */ ruptr->STA |= RUNNING; /* start reader */ ttr_xoff_read = 0; /* cancel stop */ @@ -679,7 +703,8 @@ 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? */ +if ((r = ttp_write (tty_buf)) != SCPE_OK) /* punch; error? */ + return r; SET_INT (INT_TTY); /* set done flag */ return SCPE_OK; } @@ -692,7 +717,8 @@ UNIT *tuptr = &tty_unit[TTO]; c = sim_tt_outcvt (c, TT_GET_MODE (tuptr->flags) | TTUF_KSR); tuptr->pos = tuptr->pos + 1; -if (c >= 0) return sim_putchar_s (c); +if (c >= 0) + return sim_putchar_s (c); else return SCPE_OK; } @@ -745,9 +771,11 @@ 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) /* not TTR, TTP */ + return SCPE_NOFNC; tty_unit[TTO].flags = (tty_unit[TTO].flags & ~TT_MODE) | val; -if (val == TT_MODE_7P) val = TT_MODE_7B; +if (val == TT_MODE_7P) + val = TT_MODE_7B; tty_unit[TTI].flags = (tty_unit[TTI].flags & ~TT_MODE) | val; return SCPE_OK; } @@ -756,8 +784,10 @@ 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 (!(val & UNIT_UASC)) uptr->STA &= ~LF_PEND; +if (!(uptr->flags & UNIT_ATTABLE)) /* TTR, TTP only */ + return SCPE_NOFNC; +if (!(val & UNIT_UASC)) + uptr->STA &= ~LF_PEND; return SCPE_OK; } @@ -765,11 +795,15 @@ 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 */ +if (!(uptr->flags & UNIT_ATTABLE)) /* TTR, TTP only */ + return SCPE_NOFNC; +if (!(uptr->flags & UNIT_ATT)) /* must be attached */ + return SCPE_UNATT; +if (val) /* start? set running */ + uptr->STA |= RUNNING; else uptr->STA &= ~RUNNING; /* stop? clr running */ -if (uptr->flags & UNIT_ROABLE) ttr_xoff_read = 0; /* TTR? cancel stop */ +if (uptr->flags & UNIT_ROABLE) /* TTR? cancel stop */ + ttr_xoff_read = 0; else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */ return SCPE_OK; } @@ -781,9 +815,11 @@ 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 */ + if (fnc & 015) /* only fnc 0,2 */ + return IOBADFNC (dat); CLR_INT (INT_CLK); /* reset ready */ - if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */ + if (fnc) /* fnc = 2? stop */ + sim_cancel (&clk_unit); else { /* fnc = 0? */ if (!sim_is_active (&clk_unit)) sim_activate (&clk_unit, /* activate */ @@ -793,7 +829,8 @@ switch (inst) { /* case on opcode */ case ioSKS: /* SKS */ if (fnc == 000) { /* clock skip !int */ - if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); + if (!TST_INTREQ (INT_CLK)) + return IOSKIP (dat); } else if ((fnc & 007) == 002) { /* mem parity? */ if (((fnc == 002) && !TST_INT (INT_MPE)) || @@ -804,7 +841,8 @@ switch (inst) { /* case on opcode */ break; case ioOTA: /* OTA */ - if (fnc == 000) dev_enb = dat; /* SMK */ + if (fnc == 000) /* SMK */ + dev_enb = dat; else if (fnc == 010) { /* OTK */ C = (dat >> 15) & 1; /* set C */ if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ @@ -831,7 +869,8 @@ 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 */ +if (M[M_CLK] == 0) /* = 0? set flag */ + SET_INT (INT_CLK); sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ return SCPE_OK; } @@ -850,8 +889,10 @@ return SCPE_OK; t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; clk_tps = val; return SCPE_OK; } diff --git a/H316/h316_sys.c b/H316/h316_sys.c index 9995a0b7..ca4ff61e 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-2005, Robert M Supnik + Copyright (c) 1999-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -239,7 +239,8 @@ 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; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } @@ -248,7 +249,8 @@ if (sw & SWMASK ('C')) { /* characters? */ fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; /* Instruction decode */ @@ -266,11 +268,13 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ disp = inst & DISP; /* displacement */ fprintf (of, "%s ", opcode[i]); /* opcode */ if (inst & SC) { /* current sector? */ - if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp); + 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"); + if ((j == I_V_MRF) && (inst & IDX)) + fprintf (of, ",1"); break; case I_V_IOT: /* I/O */ @@ -315,12 +319,14 @@ char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); while (isspace (*cptr)) cptr++; /* absorb spaces */ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = (((t_value) cptr[0] & 0177) << 8) | ((t_value) cptr[1] & 0177); return SCPE_OK; @@ -330,7 +336,8 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ 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; +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 */ @@ -342,14 +349,16 @@ switch (j) { /* case on class */ 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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */ break; @@ -363,16 +372,21 @@ switch (j) { /* case on class */ 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? */ + if (r != SCPE_OK) + return SCPE_ARG; + if (d <= DISP) /* fits? */ + val[0] = val[0] | d; 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? */ + if ((j == I_V_MRX) || (*cptr == 0)) /* indexed? */ + break; 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 */ + if (r != SCPE_OK) + return SCPE_ARG; + if (d) /* or in index */ + val[0] = val[0] | IDX; break; case I_V_SK0: case I_V_SK1: /* skips */ @@ -388,6 +402,7 @@ switch (j) { /* case on class */ break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; return SCPE_OK; } diff --git a/HP2100/hp2100_baci.c b/HP2100/hp2100_baci.c index 13a7fd58..779edf96 100644 --- a/HP2100/hp2100_baci.c +++ b/HP2100/hp2100_baci.c @@ -25,6 +25,13 @@ BACI 12966A BACI card + 25-Nov-08 JDB Revised for new multiplexer library SHOW routines + 11-Sep-08 JDB Fixed STC,C losing interrupt request on BREAK + 07-Sep-08 JDB Fixed IN_LOOPBACK conflict with netinet/in.h + Changed Telnet poll to connect immediately after reset or attach + 10-Aug-08 JDB Added REG_FIT to register variables < 32-bit size + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 17-Jun-08 JDB Moved fmt_char() function to hp2100_sys.c 13-Jun-08 JDB Cleaned up debug reporting for sim_activate calls 16-Apr-08 JDB Separated terminal I/O and Telnet poll for idle compatibility 07-Dec-07 JDB Created BACI device @@ -238,7 +245,7 @@ #define IN_SXX 0000001 /* status: SBB/SCF is on */ #define IN_MODEM (IN_CB | IN_CC | IN_CE | IN_CF | IN_SXX) -#define IN_LOOPBACK (IN_DEVINT | IN_SPARE | IN_TEST | IN_MODEM) +#define IN_DIAG (IN_DEVINT | IN_SPARE | IN_TEST | IN_MODEM) #define IN_STDIRQ (IN_DEVINT | IN_SPCHAR | IN_BREAK | IN_OVRUNPE) #define IN_FIFOIRQ (IN_BUFEMPTY | IN_BUFHALF | IN_BUFFULL) @@ -311,15 +318,14 @@ #define baci_poll baci_unit[1] /* Telnet polling unit */ -/* External variables */ - -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -extern FILE *sim_deb; - - /* BACI state variables */ +FLIP_FLOP baci_control = CLEAR; /* control flip-flop */ +FLIP_FLOP baci_flag = CLEAR; /* flag flip-flop */ +FLIP_FLOP baci_flagbuf = CLEAR; /* flag buffer flip-flop */ +FLIP_FLOP baci_srq = CLEAR; /* SRQ flip-flop */ +FLIP_FLOP baci_lockout = CLEAR; /* interrupt lockout flip-flop */ + uint16 baci_ibuf = 0; /* status/data in */ uint16 baci_obuf = 0; /* command/data out */ uint16 baci_status = 0; /* current status */ @@ -356,24 +362,22 @@ TMXR baci_desc = { 1, 0, 0, &baci_ldsc }; /* device descriptor */ /* BACI local routines */ -static int32 service_time (uint32 control_word); -static const char *fmt_char (uint8 ch); -static void update_status (void); -static void master_reset (uint32 selcode); +static int32 service_time (uint32 control_word); +static void update_status (void); +static void master_reset (void); -static uint32 fifo_get (void); -static void fifo_put (uint8 ch); +static uint32 fifo_get (void); +static void fifo_put (uint8 ch); static void clock_uart (void); /* BACI global routines */ - int32 baci_io (int32 inst, int32 IR, int32 dat); +uint32 baci_io (uint32 select_code, IOSIG signal, uint32 data); t_stat baci_term_svc (UNIT *uptr); t_stat baci_poll_svc (UNIT *uptr); t_stat baci_reset (DEVICE *dptr); t_stat baci_attach (UNIT *uptr, char *cptr); t_stat baci_detach (UNIT *uptr); -t_stat baci_show (FILE *st, UNIT *uptr, int32 val, void *desc); /* BACI data structures @@ -396,24 +400,24 @@ t_stat baci_show (FILE *st, UNIT *uptr, int32 val, void *desc); ten millisecond period. */ -DIB baci_dib = { BACI, 0, 0, 0, 0, 0, &baci_io }; +DIB baci_dib = { BACI, &baci_io }; DEVICE baci_dev; UNIT baci_unit[] = { { UDATA (&baci_term_svc, UNIT_ATTABLE | UNIT_FASTTIME, 0) }, /* terminal I/O unit */ - { UDATA (&baci_poll_svc, UNIT_DIS, POLL_WAIT) } }; /* Telnet poll unit */ + { UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } }; /* Telnet poll unit */ REG baci_reg[] = { - { ORDATA (IBUF, baci_ibuf, 16) }, - { ORDATA (OBUF, baci_obuf, 16) }, - { ORDATA (STATUS, baci_status, 16) }, + { ORDATA (IBUF, baci_ibuf, 16), REG_FIT }, + { ORDATA (OBUF, baci_obuf, 16), REG_FIT }, + { ORDATA (STATUS, baci_status, 16), REG_FIT }, - { ORDATA (EDSIW, baci_edsiw, 16) }, - { ORDATA (DSRW, baci_dsrw, 16) }, - { ORDATA (CFCW, baci_cfcw, 16) }, - { ORDATA (ICW, baci_icw, 16) }, - { ORDATA (ISRW, baci_isrw, 16) }, + { ORDATA (EDSIW, baci_edsiw, 16), REG_FIT }, + { ORDATA (DSRW, baci_dsrw, 16), REG_FIT }, + { ORDATA (CFCW, baci_cfcw, 16), REG_FIT }, + { ORDATA (ICW, baci_icw, 16), REG_FIT }, + { ORDATA (ISRW, baci_isrw, 16), REG_FIT }, { DRDATA (FIFOPUT, baci_fput, 8) }, { DRDATA (FIFOGET, baci_fget, 8) }, @@ -423,9 +427,9 @@ REG baci_reg[] = { { BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE) }, { BRDATA (SPCHAR, baci_spchar, 8, 1, 256) }, - { ORDATA (UARTTHR, baci_uart_thr, 16) }, + { ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT }, { ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ }, - { ORDATA (UARTRHR, baci_uart_rhr, 16) }, + { ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT }, { ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ }, { DRDATA (UARTCLK, baci_uart_clk, 16) }, @@ -434,11 +438,11 @@ REG baci_reg[] = { { FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO }, { DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO }, - { FLDATA (LKO, baci_dib.cmd, 0) }, - { FLDATA (CTL, baci_dib.ctl, 0) }, - { FLDATA (FLG, baci_dib.flg, 0) }, - { FLDATA (FBF, baci_dib.fbf, 0) }, - { FLDATA (SRQ, baci_dib.srq, 0) }, + { FLDATA (LKO, baci_lockout, 0) }, + { FLDATA (CTL, baci_control, 0) }, + { FLDATA (FLG, baci_flag, 0) }, + { FLDATA (FBF, baci_flagbuf, 0) }, + { FLDATA (SRQ, baci_srq, 0) }, { ORDATA (DEVNO, baci_dib.devno, 6), REG_HRO }, { NULL } }; @@ -456,9 +460,9 @@ MTAB baci_mod[] = { { MTAB_XTD | MTAB_VDV | MTAB_NC, 0, "LOG", "LOG", &tmxr_set_log, &tmxr_show_log, &baci_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NC, 0, NULL, "NOLOG", &tmxr_set_nolog, NULL, &baci_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTION", NULL, NULL, &baci_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &baci_show, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTION", NULL, NULL, &tmxr_show_cstat, &baci_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &baci_desc }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc }, { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &baci_dev }, { 0 } @@ -497,8 +501,7 @@ DEVICE baci_dev = { NULL }; /* logical device name */ - -/* I/O instruction processor. +/* I/O signal handler. The BACI processes seven types of output words and supplies two types of input words. Output word type is identified by an ID code in bits 14-12. @@ -509,63 +512,100 @@ DEVICE baci_dev = { - STC is not required to transfer a character. - Flag is not set after character transfer completes. - - FLAG and SRQ are decoupled. + - FLAG and SRQ are decoupled and are set independently. An interrupt lockout flip-flop is used to prevent the generation of multiple - interrupts until the cause of the first interrupt is identified and cleared. - CMD is used to model the lockout flip-flop. + interrupts until the cause of the first interrupt is identified and cleared + by the CPU. + + Implementation notes: + + 1. The STC handler checks to see if it was invoked for STC SC or STC SC,C. + In the latter case, the check for new interrupt requests is deferred + until after the CLF. Otherwise, the flag set by the interrupt check + would be cleared, and the interrupt would be lost. */ -int32 baci_io (int32 inst, int32 IR, int32 dat) +uint32 baci_io (uint32 select_code, IOSIG signal, uint32 data) { +const char *hold_or_clear = (signal > ioCLF ? ",C" : ""); +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ uint8 ch; uint32 mask; -uint32 dev = IR & I_DEVMASK; -switch (inst) { /* dispatch by instruction */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* set or clear flag */ - if ((IR & I_HC) == 0) { /* STF? */ - setFSR (dev); /* set flag, flag buffer, and SRQ */ - setCMD (dev); /* set lockout */ - - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [STF] Flag, SRQ, and lockout set\n", sim_deb); - } - break; /* CLF handled by H/C below */ - - - case ioSFC: /* skip if flag clear */ - if (FLG (dev) == 0) /* flag clear? */ - PC = (PC + 1) & VAMASK; /* skip next instruction */ - break; - - - case ioSFS: /* skip if flag set */ - if (FLG (dev) != 0) /* flag set? */ - PC = (PC + 1) & VAMASK; /* skip next instruction */ - break; - - - case ioCRS: /* control reset */ - master_reset (dev); /* issue master reset */ + case ioCLF: /* clear flag flip-flop */ + baci_flag = baci_flagbuf = CLEAR; /* clear flag and flag buffer */ + baci_srq = CLEAR; /* clear SRQ */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [CRS] Master reset\n", sim_deb); + fputs (">>BACI cmds: [CLF] Flag and SRQ cleared\n", sim_deb); + + update_status (); /* FLG might set when SRQ clears */ break; - case ioOTX: /* output word */ - if (DEBUG_PRI (baci_dev, DEB_CPU)) - fprintf (sim_deb, ">>BACI cpu: [OTx] Command = %06o\n", dat); + case ioSTF: /* set flag flip-flop */ + baci_flag = baci_flagbuf = SET; /* set flag and flag buffer */ + baci_lockout = SET; /* set lockout */ + baci_srq = SET; /* set SRQ */ - baci_obuf = dat; + if (DEBUG_PRI (baci_dev, DEB_CMDS)) + fputs (">>BACI cmds: [STF] Flag, SRQ, and lockout set\n", sim_deb); + break; + + + case ioENF: /* enable flag */ + baci_flag = baci_flagbuf = SET; /* set device flag and flag buffer */ + baci_lockout = SET; /* set lockout */ + break; + + + case ioSFC: /* skip if flag is clear */ + setstdSKF (baci); + break; + + + case ioSFS: /* skip if flag is set */ + setstdSKF (baci); + break; + + + case ioIOI: /* I/O data input */ + if (baci_control) { /* control set? */ + baci_ibuf = TO_CHARCNT (baci_fcount); /* get FIFO count */ + + if (IO_MODE == RECV) /* receiving? */ + baci_ibuf = baci_ibuf | fifo_get (); /* add char and validity flag */ + + data = baci_ibuf; /* return received data */ + + if (DEBUG_PRI (baci_dev, DEB_CPU)) + fprintf (sim_deb, ">>BACI cpu: [LIx%s] Received data = %06o\n", hold_or_clear, data); + } + + else { /* control clear? */ + data = baci_status; /* return status */ + + if (DEBUG_PRI (baci_dev, DEB_CPU)) + fprintf (sim_deb, ">>BACI cpu: [LIx%s] Status = %06o\n", hold_or_clear, data); + } + break; + + + case ioIOO: /* I/O data output */ + if (DEBUG_PRI (baci_dev, DEB_CPU)) + fprintf (sim_deb, ">>BACI cpu: [OTx%s] Command = %06o\n", hold_or_clear, data); + + baci_obuf = data; if (baci_obuf & OUT_MR) { /* master reset? */ - master_reset (dev); /* do before processing */ + master_reset (); /* do before processing */ + baci_io (select_code, ioSIR, 0); /* set interrupt request */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [OTx] Master reset\n", sim_deb); + fprintf (sim_deb, ">>BACI cmds: [OTx%s] Master reset\n", hold_or_clear); } switch (GET_ID (baci_obuf)) { /* isolate ID code */ @@ -578,8 +618,8 @@ switch (inst) { /* dispatch by instructi if (baci_term.flags & UNIT_ATT) { /* attached to network? */ if (DEBUG_PRI (baci_dev, DEB_CMDS) && /* debugging? */ (sim_is_active (&baci_term) == 0)) /* service stopped? */ - fprintf (sim_deb, ">>BACI cmds: [OTx] Terminal service scheduled, " - "time = %d\n", baci_term.wait); + fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, " + "time = %d\n", hold_or_clear, baci_term.wait); if (baci_fcount == 1) /* first char to xmit? */ sim_activate_abs (&baci_term, /* start service with full char time */ @@ -611,7 +651,7 @@ switch (inst) { /* dispatch by instructi baci_cfcw = baci_obuf; /* load new frame word */ break; - case 4: /* interface control */ + case 4: /* interface control */ if ((baci_icw ^ baci_obuf) & OUT_BAUDRATE) { /* baud rate change? */ baci_term.wait = service_time (baci_obuf); /* set service time to match rate */ @@ -621,15 +661,16 @@ switch (inst) { /* dispatch by instructi baci_term.wait); if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [OTx] Terminal service scheduled, " - "time = %d\n", baci_term.wait); + fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, " + "time = %d\n", hold_or_clear, baci_term.wait); } else { /* external rate */ sim_cancel (&baci_term); /* stop I/O service */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [OTx] Terminal service stopped\n", sim_deb); + fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service stopped\n", + hold_or_clear); } } @@ -654,71 +695,63 @@ switch (inst) { /* dispatch by instructi ((baci_obuf & OUT_SPFLAG) != 0); break; } - break; - case ioLIX: /* load word */ - dat = 0; + case ioPOPIO: /* power-on preset to I/O */ + /* fall into CRS handler */ - case ioMIX: /* merge word */ - if (CTL (dev)) { /* control set? */ - baci_ibuf = TO_CHARCNT (baci_fcount); /* get FIFO count */ + case ioCRS: /* control reset */ + master_reset (); /* issue master reset */ - if (IO_MODE == RECV) /* receiving? */ - baci_ibuf = baci_ibuf | fifo_get (); /* add char and validity flag */ - - dat = dat | baci_ibuf; /* return received data */ - - if (DEBUG_PRI (baci_dev, DEB_CPU)) - fprintf (sim_deb, ">>BACI cpu: [LIx] Received data = %06o\n", dat); - } - - else { /* control clear? */ - dat = dat | baci_status; /* return status */ - - if (DEBUG_PRI (baci_dev, DEB_CPU)) - fprintf (sim_deb, ">>BACI cpu: [LIx] Status = %06o\n", dat); - } + if (DEBUG_PRI (baci_dev, DEB_CMDS)) + fputs (">>BACI cmds: [CRS] Master reset\n", sim_deb); break; - case ioCTL: /* control set/clear */ - if (IR & I_CTL) { /* CLC */ - clrCTL (dev); /* clear control */ + case ioCLC: /* clear control flip-flop */ + baci_control = CLEAR; /* clear control */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [CLC] Control cleared\n", sim_deb); - } + if (DEBUG_PRI (baci_dev, DEB_CMDS)) + fprintf (sim_deb, ">>BACI cmds: [CLC%s] Control cleared\n", hold_or_clear); + break; - else { /* STC */ - setCTL (dev); /* set control */ - clrCMD (dev); /* clear lockout */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [STC] Control set and lockout cleared\n", sim_deb); + case ioSTC: /* set control flip-flop */ + baci_control = SET; /* set control */ + baci_lockout = CLEAR; /* clear lockout */ + if (DEBUG_PRI (baci_dev, DEB_CMDS)) + fprintf (sim_deb, ">>BACI cmds: [STC%s] Control set and lockout cleared\n", hold_or_clear); + + if (signal == ioSTC) /* STC without ,C ? */ update_status (); /* clearing lockout might interrupt */ - } break; - default: /* all others */ - break; /* do nothing */ + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, baci); /* set standard PRL signal */ + setstdIRQ (select_code, baci); /* set standard IRQ signal */ + setSRQ (select_code, baci_srq); /* set SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + baci_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ } -if (IR & I_HC) { /* H/C option */ - clrFSR (dev); /* clear flag and SRQ */ +if (signal > ioCLF) /* multiple signals? */ + baci_io (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + baci_io (select_code, ioSIR, 0); /* set interrupt request */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [%s] Flag and SRQ cleared\n", - (inst == ioFLG ? "CLF" : "x,C")); - - update_status (); /* FLG might set when SRQ clears */ - } - -return dat; +return data; } @@ -871,9 +904,13 @@ if (recv_loop && /* ok to process? */ while (recv_loop && /* OK to process? */ (baci_uart_rr = tmxr_getc_ln (&baci_ldsc))) { /* and new character available? */ - if (baci_uart_rr & SCPE_BREAK) /* break detected? */ + if (baci_uart_rr & SCPE_BREAK) { /* break detected? */ baci_status = baci_status | IN_BREAK; /* set break status */ + if (DEBUG_PRI (baci_dev, DEB_XFER)) + fputs (">>BACI xfer: Break detected\n", sim_deb); + } + data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */ data_mask = (1 << data_bits) - 1; /* generate mask for data bits */ baci_uart_rhr = baci_uart_rr & data_mask; /* mask data into holding register */ @@ -894,7 +931,7 @@ while (recv_loop && /* OK to process? */ baci_uart_rhr = CLEAR_HR; /* clear RHR */ update_status (); /* update FIFO status (may set flag) */ - recv_loop = fast_timing && !FLG (baci_dib.devno); /* loop if fast mode and no IRQ */ + recv_loop = fast_timing && !IRQ (baci_dib.devno); /* loop if fast mode and no IRQ */ } else { /* xmit or ENQ/ACK, leave char in RHR */ @@ -950,7 +987,11 @@ if (baci_term.flags & UNIT_ATT) { /* attached to network? sim_activate (&baci_term, baci_term.wait); /* activate I/O service */ } -uptr->wait = sync_poll (SERVICE); /* synchronize poll */ +if (uptr->wait == POLL_FIRST) /* first poll? */ + uptr->wait = sync_poll (INITIAL); /* initial synchronization */ +else /* not first */ + uptr->wait = sync_poll (SERVICE); /* continue synchronization */ + sim_activate (uptr, uptr->wait); /* continue polling */ return SCPE_OK; @@ -961,16 +1002,11 @@ return SCPE_OK; t_stat baci_reset (DEVICE *dptr) { -master_reset (0); /* do master reset */ - -baci_dib.ctl = 0; /* clear control */ -baci_dib.flg = 1; /* set flag */ -baci_dib.fbf = 1; /* set flag buffer */ -baci_dib.srq = 1; /* set SRQ */ -baci_dib.cmd = 1; /* set lockout */ +baci_io (baci_dib.devno, ioPOPIO, 0); /* send POPIO signal */ baci_ibuf = 0; /* clear input buffer */ baci_obuf = 0; /* clear output buffer */ +baci_uart_rhr = CLEAR_HR; /* clear receiver holding register */ baci_enq_seen = FALSE; /* reset ENQ seen flag */ baci_enq_cntr = 0; /* clear ENQ counter */ @@ -978,8 +1014,8 @@ baci_enq_cntr = 0; /* clear ENQ counter */ baci_term.wait = service_time (baci_icw); /* set terminal I/O time */ if (baci_term.flags & UNIT_ATT) { /* device attached? */ - baci_poll.wait = sync_poll (INITIAL); /* synchronize poll */ - sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll */ + baci_poll.wait = POLL_FIRST; /* set up poll */ + sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll immediately */ } else sim_cancel (&baci_poll); /* else stop Telnet poll */ @@ -997,8 +1033,8 @@ t_stat status = SCPE_OK; status = tmxr_attach (&baci_desc, uptr, cptr); /* attach to socket */ if (status == SCPE_OK) { - baci_poll.wait = sync_poll (INITIAL); /* synchronize poll */ - sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll */ + baci_poll.wait = POLL_FIRST; /* set up poll */ + sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll immediately */ } return status; } @@ -1015,31 +1051,12 @@ sim_cancel (&baci_poll); /* stop Telnet poll */ return status; } -/* Show connection status and statistics */ - -t_stat baci_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (baci_ldsc.conn) - if (val) - tmxr_fconns (st, &baci_ldsc, -1); - else - tmxr_fstats (st, &baci_ldsc, -1); -else - fprintf (st, "terminal disconnected\n"); - -return SCPE_OK; -} - - /* Local routines */ /* Master reset. This is the programmed card master reset, not the simulator reset routine. - It is called from the simulator reset routine with "selcode" = 0; the latter - routine will take care of setting the card flip-flops appropriately. - Master reset normally clears the UART registers. However, if we are in "fast timing" mode, the receiver holding register may hold a deferred character. In this case, we do not clear the RHR, unless we are called from the @@ -1049,7 +1066,7 @@ return SCPE_OK; An examination of the schematic, though, shows that it sets SRQ instead. */ -static void master_reset (uint32 selcode) +static void master_reset (void) { baci_fput = baci_fget = 0; /* clear FIFO indexes */ baci_fcount = 0; /* clear FIFO counter */ @@ -1057,7 +1074,7 @@ memset (baci_fifo, 0, sizeof (baci_fifo)); /* clear FIFO data */ baci_uart_thr = CLEAR_HR; /* clear transmitter holding register */ -if (!(baci_term.flags & UNIT_FASTTIME) || !selcode) /* real time mode or power-on init? */ +if (!(baci_term.flags & UNIT_FASTTIME)) /* real time mode? */ baci_uart_rhr = CLEAR_HR; /* clear receiver holding register */ baci_uart_tr = CLEAR_R; /* clear transmitter register */ @@ -1066,12 +1083,10 @@ baci_uart_rr = CLEAR_R; /* clear receiver regist baci_uart_clk = 0; /* clear UART clock */ baci_bcount = 0; /* clear break counter */ -if (selcode) { - clrCTL (selcode); /* clear control */ - setFLG (selcode); /* set flag and flag buffer */ - setSRQ (selcode); /* set SRQ */ - setCMD (selcode); /* set lockout flip-flop */ - } +baci_control = CLEAR; /* clear control */ +baci_flag = baci_flagbuf = SET; /* set flag and flag buffer */ +baci_srq = SET; /* set SRQ */ +baci_lockout = SET; /* set lockout flip-flop */ baci_edsiw = 0; /* clear interrupt enables */ baci_dsrw = 0; /* clear status reference */ @@ -1107,7 +1122,7 @@ return; static void update_status (void) { if (baci_term.flags & UNIT_DIAG) { /* diagnostic mode? */ - baci_status = baci_status & ~IN_LOOPBACK; /* prepare loopback flags */ + baci_status = baci_status & ~IN_DIAG; /* clear loopback flags */ if (baci_icw & OUT_SXX) /* SCA to SCF and CF */ baci_status = baci_status | IN_SXX | IN_CF; @@ -1135,19 +1150,18 @@ if ((baci_status & IN_STDIRQ) || /* standard interrupt? * (baci_edsiw & OUT_ENCM) && /* and char mode */ (baci_fget != baci_fput)) { /* and FIFO not empty? */ - if (CMD (baci_dib.devno)) { /* interrupt lockout? */ + if (baci_lockout) { /* interrupt lockout? */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) fputs (">>BACI cmds: Lockout prevents flag set", sim_deb); } - else if (SRQ (baci_dib.devno)) { /* SRQ? */ + else if (baci_srq) { /* SRQ set? */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) fputs (">>BACI cmds: SRQ prevents flag set", sim_deb); } else { - setFLG (baci_dib.devno); /* set device flag and flag buffer */ - setCMD (baci_dib.devno); /* set lockout */ + baci_io (baci_dib.devno, ioENF, 0); /* set flag */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) fputs (">>BACI cmds: Flag and lockout set", sim_deb); @@ -1161,13 +1175,14 @@ if ((baci_icw & OUT_DCPC) && /* DCPC enabled? */ ((IO_MODE == XMIT) && (baci_fcount < 128) || /* and xmit and room in FIFO */ (IO_MODE == RECV) && (baci_fcount > 0))) { /* or recv and data in FIFO? */ - if (CMD (baci_dib.devno)) { /* interrupt lockout? */ + if (baci_lockout) { /* interrupt lockout? */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) fputs (">>BACI cmds: Lockout prevents SRQ set", sim_deb); } else { - setSRQ (baci_dib.devno); /* set SRQ */ + baci_srq = SET; /* set SRQ */ + baci_io (baci_dib.devno, ioSIR, 0); /* set interrupt request */ if (DEBUG_PRI (baci_dev, DEB_CMDS)) fputs (">>BACI cmds: SRQ set", sim_deb); @@ -1201,42 +1216,6 @@ return ticks [GET_BAUDRATE (control_word)]; /* return service time f } -/* Format a character into a printable string. - - Control characters are translated to readable strings. Printable characters - retain their original form but are enclosed in single quotes. Characters - outside of the ASCII range are represented as escaped octal values. -*/ - -static const char *fmt_char (uint8 ch) -{ -static const char *const ctl[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", - "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", - "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", - "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" }; -static char rep[5]; - -if (ch <= '\037') /* ASCII control character? */ - return ctl [ch]; /* return string representation */ - -else if (ch == '\177') /* ASCII delete? */ - return "DEL"; /* return string representation */ - -else if (ch > '\177') { /* beyond printable range? */ - sprintf (rep, "\\%03o", ch); /* format value */ - return rep; /* return escaped octal code */ - } - -else { /* printable character */ - rep[0] = '\''; /* form string */ - rep[1] = ch; /* containing character */ - rep[2] = '\''; - rep[3] = '\0'; - return rep; /* return quoted character */ - } -} - - /* FIFO manipulation routines. The BACI is a half-duplex device that has a single 128-byte FIFO that is used diff --git a/HP2100/hp2100_bugfixes.txt b/HP2100/hp2100_bugfixes.txt new file mode 100644 index 00000000..71448791 --- /dev/null +++ b/HP2100/hp2100_bugfixes.txt @@ -0,0 +1,5353 @@ + HP 2100 SIMULATOR BUG FIX WRITEUPS + ================================== + Last update: 2008-09-30 + + + 1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756 + (000400)". However, [77755] is HLT 77 (102077), [77756] is ALF,ALF (001727). + + VERSION: 3.2-0 + + OBSERVATION: The value 000400 is supposed to be "ALF,ALF", i.e., the + decoded memory value at P. + + CAUSE: "fprint_stopped" in "scp.c" calls "cpu_ex" in "hp2100_cpu.c", which + calls "dms_cons" to display the virtual (logical) address. However, at the + halt in the mag tape boot loader, DMS is not enabled, so the map registers + are meaningless (they happen to be zeros, so the access is to physical + address 001756). + + RESOLUTION: Alter "dms_cons" in "hp2100_cpu.c" to condition DMS mapping on + "dms_enb". + + STATUS: Fixed in version 3.2-1. + + + + 2. PROBLEM: Terminal output from RTE is indented three spaces, e.g., "START + RECONFIGURATION" appears as " START RECONFIGURATION", and the "- " prompts + after answering "YES" to "I/O RECONFIGURATION?" do not appear. + + VERSION: 3.2-0 + + OBSERVATION: Use of a debugger reveals that the output sequence to the TTY + is - . + + CAUSE: RTE is outputting nulls to allow the (physical) TTY carriage time to + move, but these are overwriting the prompt character in the simulation (note + that a real TTY absorbs nulls, i.e., they don't affect the printed output). + The TTY emulator should strip nulls from output to console. + + RESOLUTION: Alter "tto_out" in "hp2100_stddev.c" to suppress nulls sent to + the TTY printer. + + STATUS: Fixed in version 3.2-1. + + + + 3. PROBLEM: Completing the reconfiguration and exiting hangs the system after + printing the first few characters of the output line. RTE is stuck in a + loop in $CIC. + + VERSION: 3.2-0 + + OBSERVATION: At the entry to $CIC (system map address 43221), RTE uses the + undocumented instruction "SFS 0,C" to both test and turn off the interrupt + system. This is confirmed in the "RTE-6/VM Technical Specifications" manual + (HP 92084-90015), section 2.3.1 "Process the Interrupt", subsection "A.1 + $CIC": + + "Test to see if the interrupt system is on or off. This is done with the + SFS 0,C instruction. In either case, turn it off (the ,C does it)." + + ...and in section 5.8, "Parity Error Detection": + + "Because parity error interrupts can occur even when the interrupt system + is off, the code at $CIC must be able to save the complete system status. + The major hole in being able to save the complete state is in saving the + interrupt system state. In order to do this in both the 21MX and the 21XE + the instruction 103300 was used to both test the interrupt system and + turn it off." + + CAUSE: The simulator does not respond to the "H/C bit" on the "SFS 0" + instruction, so the interrupt system is not turned off. + + RESOLUTION: Modify "hp2100_cpu.c" and the various devices to respond to the + "H/C bit" on the "SFS" and "SFC" instructions, and modify "hp2100_sys.c" to + decode the "H/C bit" on those instructions (note that while the + documentation refers specifically only to "SFS 0", the schematics of the + 21MX appear to indicate that the bit will work on any SFS instruction -- and + the SFC instruction too, for that matter). + + STATUS: Fixed in version 3.2-1. + + + + 4. PROBLEM: RTE sits in the idle loop. TBG/TTY interrupts are not occurring, + so "SET TIME" is not output. + + VERSION: 3.2-0 + + OBSERVATION: The memory protect flag is set, inhibiting all lower-priority + interrupts, such as the TBG and TTY. If the MP flag is cleared manually, + RTE prints "SET TIME" and comes up sufficiently to respond to operator + attention commands. The system time is seen to increment properly. + + Unlike most other I/O devices, the MP flag flip-flop is cleared + automatically when the interrupt is acknowledged and not by a programmed + instruction (CLF and STF affect the parity error enable FF instead). + Section 4.4.3 "Memory Protect and I/O Interrupt Generation" of the "HP 1000 + M/E/F-Series Computers Engineering and Reference Documentation" (HP + 92851-90001) says: + + "When IAK occurs and IRQ5 is asserted, the FLAGBFF is cleared, FLAGFF + clocked off at next T2, and IRQ5 will no longer occur." + + CAUSE: The MP flag flip-flop is not being cleared automatically when the + interrupt is acknowledged. + + RESOLUTION: Modify "hp2100_cpu.c" to reset the MP flag on IAK5. + + STATUS: Fixed in version 3.2-1. + + + OBSERVATION: The MEV flag indicates the source of the interrupt (set for + DMS violation, clear for MP violation). If this is tested with a SFS or SFC + instruction after an MP interrupt, it is observed that DMS interrupts are + not being indicated properly. SFS 05 never skips. + + CAUSE: The MP flag is being used to condition the response for SFS 05 and + SFC 05. Examination of the schematics for the MP card in the engineering + documentation shows that the SFS and SFC I/O backplane signals gate the + output of the MEVFF onto the SKF line unconditionally. + + RESOLUTION: Modify "hp2100_cpu.c" to remove conditioning on MP flag for SFS + 05, SFC 05. + + STATUS: Fixed in version 3.2-1. + + + + 5. PROBLEM: Attempting to run any program causes a DM violation. + + VERSION: 3.2-0 + + OBSERVATION: BCKOF is scheduled when the system starts and is the first + program to DM abort. Examining the DMS maps seems to indicate that the user + and system maps are set up reasonably. However, examining memory with + the "ex -u" and "ex -s" commands reveals the same data in both sets of + locations. The "ex" command isn't using the DMS maps properly. + + CAUSE: String constants are used instead of character constants, preventing + the DMS map switches from being recognized. + + RESOLUTION: Modify "hp2100_cpu.c" to use character constants rather than + string constants in "dms_cons" so that DMS map switches work correctly. + + STATUS: Fixed in version 3.2-1. + + + OBSERVATION: The DM abort is occurring when JSB EXEC is done from a user + program. The EXEC target is below the MP fence, and the expected action is + an MP violation interrupt that is recognized and processed by the system as + a legal call to the system executive. However, the MP violation isn't + occurring, so the SJP instruction at the actual EXEC entry point (present to + catch EXEC calls made with the interrupt system off) is attempted, and that + causes the DM violation, due to execution of a protected instruction from + the user map. + + CAUSE: Memory writes aren't being checked for an MP violation if DMS is + enabled, i.e., if DMS is enabled, and the page is writable, then whether the + target is below the MP fence is not checked. + + RESOLUTION: Modify "hp2100_cpu.c" to do MP check on all writes after DMS + translation and violation checks are done (so, to pass, the page must be + writable AND the target must be above the MP fence). + + STATUS: Fixed in version 3.2-1. + + + + 6. PROBLEM: The "WHZAT" program isn't showing the current time, program type, + priority, etc. + + VERSION: 3.2-0 + + OBSERVATION: Running the program with "RU,WHZAT" shows that the current + time (etc.) is simply missing, as though zero-length strings are being + written, or all characters in the string are being written to the same + location. + + CAUSE: The SBT instruction isn't incrementing the B register, so all + characters are being overwritten. + + RESOLUTION: Modify the processing of the SBT instruction in "hp2100_cpu.c" + to increment B. + + STATUS: Fixed in version 3.2-1. + + + + 7. PROBLEM: The simulator may abort with an access exception when examining + memory. + + VERSION: 3.2-0 + + OBSERVATION: If DMS is enabled but a map register contains a page greater + than defined memory, attempting to examine the logical address corresponding + to that page register causes an access exception. + + CAUSE: The "cpu_ex" and "cpu_dep" routines attempt to prevent this, but the + validation is being made on the logical, not the physical address. + + RESOLUTION: Modify "cpu_ex" and "cpu_dep" in "hp2100_cpu.c" to check the + physical addresses against the physical memory limit. + + STATUS: Fixed in version 3.2-1. + + + + 8. PROBLEM: Pressing a key during output does not give an RTE prompt. + + VERSION: 3.2-0 + + OBSERVATION: Running, e.g., WHZAT and pressing a key during the listing + does not interrupt the system as expected. Pressing a key when the system + is idle does give a prompt. + + CAUSE: Detection of key presses during output is accomplished by DVR00 with + the 12531C card by reading the data register after output is complete. If + no key was pressed, the register will have the value of 377 octal. If a key + was pressed, the value will be something other than this. SIMH is not + passing the keystrokes into the output data register. + + RESOLUTION: Modify tty routines in "hp2100_stddev.c" to simulate the shift + of a character into the data register concurrently with an output operation. + + STATUS: Fixed in version 3.2-1. + + + + 9. ENHANCEMENT: Programmed halt should report the halt code (i.e., the numeric + HLT instruction). + + VERSION: 3.2-0 + + OBSERVATION: When a programmed halt occurs on the actual 21MX, the T + register (current memory contents) is automatically selected on the CPU + front panel. The T register displays the numeric HLT instruction. Many HP + programs communicate program status via the numeric halt instruction codes + themselves. For example, a HLT 77 (102077) is universally used to mean + "proper operation completed." The mag tape boot loader, for instance, will + HLT 11 (102011) if a checksum error is detected and HLT 00 (102000) if the + mag tape status is anything unexpected. The HP diagnostics also make + extensive use of halt codes, and their numeric values are tabulated in the + diagnostic manuals to correspond with certain results. + + Currently, the simulator displays only the P register value (which points to + HLT + 1) and the contents of the memory location at P (which displays the + instruction one beyond the HLT), e.g.: + + HALT instruction, P: 77756 (ALF,ALF) + sim> + + This, however, fails to communicate the status implied by the HLT code, + which must be obtained by entering "ex 77755" after the halt. + + RESOLUTION: Modify "hp2100_sys.c" to make the halt status message a + variable instead of a constant string, and modify "hp2100_cpu.c" to format + the status message with the halt code, as follows: + + HALT instruction 102077, P: 77756 (ALF,ALF) + sim> + + STATUS: Fixed in version 3.2-1. + + + + 10. ENHANCEMENT: Add an M register (current pointer to memory) and a T register + (contents of the memory location at P). + + VERSION: 3.2-0 + + OBSERVATION: The 21MX computer presents eight hardware registers: A, B, M, + T, P, S, O, and E. From the 21MX M-Series Computer Operating and Reference + Manual (02108-90037): + + "The M-register hold the address of the memory cell currently being read + from or written into by the CPU. + + "The data transferred into or out of memory is routed through the + T-register. When displayed, the T-register indicates the contents of the + memory location currently pointed to by the M-register. The A- or + B-register contents are displayed if the M-register contents are 000000 + or 000001, respectively." + + However, the simulator does not expose these registers as part of the CPU + state. Internally, they are not needed, but the simulation user would + expect to be able to view and set their contents, so they should be + implemented. + + When the machine halts, the front panel microroutines display the T + register after initiating a read of memory via the M register. So T always + reflects the contents of memory addressed by M. For machine halts due to + the front panel HALT button being pressed or due to execution of a HLT + instruction not in an interrupt trap cell, M is set to P-1. If, however, + the machine halts due to the execution of a HLT instruction in an interrupt + trap cell, M is set instead to the address of the trap cell (P still points + to the next instruction to be executed). + + RESOLUTION: Modify "hp2100_cpu.c" to add M and T registers to the CPU + state. T must be read-only, because there is no way to determine positively + when a store into T has been done. + + STATUS: Fixed in version 3.2-1. + + + + 11. ENHANCEMENT: Change the DMS map register contents to display and enter in + the format as documented by the HP hardware manual. + + VERSION: 3.2-0 + + OBSERVATION: The simulated DMS map registers are stored in an internal + format that does not correspond to the real DMS hardware. Specifically, the + physical page address is shifted left by ten bits, and the read- and + write-protect bits are in bits 1-0 rather than 15-14. This is done for + performance reasons and is reasonable and proper. However, this internal + format is exposed as the external representation, which is unfamiliar to the + simulation user. The user expects to be able to view and set the DMS map + registers in the same format as the real machine. + + RESOLUTION: Modify "hp2100_cpu.c" and "hp2100_defs.h" to use the documented + format. + + STATUS: Fixed in version 3.2-1. + + + + 12. ENHANCEMENT: Provide map-specific simulation breakpoints. + + VERSION: 3.2-0 + + OBSERVATION: When DMS is enabled, separate address spaces exist for system + and user programs. In debugging, one may have to set breakpoints in either + address space. Currently, breakpoints are map-agnostic, i.e., only the + address needs to match. This leads to the potential for breaking when not + intended and can be frustrating if, for example, the desired user-mode break + location happens to correspond with the TBG handling code in the system. + + RESOLUTION: Modify "hp2100_cpu.c" to add map-specific breakpoints. + + STATUS: Fixed in version 3.2-1. + + + + 13. ENHANCEMENT: Rename the F register to MPFR. + + VERSION: 3.2-0 + + OBSERVATION: There is no F register defined in the 21MX register set. Its + name is confusing to the new simulation user. Moreover, there is an MPVR + (memory protect violation register), but the memory protect fence register + appears to be missing. Renaming makes the exposed register set more + consistent with HP nomenclature. + + RESOLUTION: Modify "hp2100_cpu.c" to change the name of the register from + "F" to "MPFR", and move the location in the CPU state to precede the memory + protect violation register "MPVR", so that these two MP-related values + appear together. + + STATUS: Fixed in version 3.2-1. + + + + 14. ENHANCEMENT: Rename the IADDR register to CIR. + + VERSION: 3.2-0 + + OBSERVATION: The address of the currently interrupting device is contained + in the Central Interrupt Register (CIR) in HP documentation. Renaming makes + the exposed register set more consistent with HP nomenclature. + + RESOLUTION: Modify "hp2100_cpu.c" to change the name of the register from + "IADDR" to "CIR". + + STATUS: Fixed in version 3.2-1. + + + + 15. PROBLEM: Under RTE, the backspace key deletes the entire line, rather than + just the last character entered. + + VERSION: 3.2-0 + + OBSERVATION: Pressing the backspace key should delete the last character + entered. Pressing the DEL key (CTRL+BACKSPACE) should delete the entire + line. RTE is behaving as though DEL were being sent when the backspace key + is pressed. + + CAUSE: The simulator is unconditionally translating backspace (CTRL+H) to + DEL (CTRL+BACKSPACE), ostensibly for the convenience of some DEC operating + system. + + STATUS: Fixed in version 3.2-1. + + + + 16. ENHANCEMENT: Provide a settable "auto linefeed" mode so that the TTY will + follow each CR with LF (DSGEN and DOS itself require that lines end with CR + and LF, contrary to RTE, which uses CR only). + + VERSION: 3.2-0 + + OBSERVATION: Always following ENTER with CTRL+J is awkward. An "AUTO LF" + mode is desirable. + + RESOLUTION: Implement a "SET TTY AUTOLF" command to implement "auto + linefeed" mode. + + STATUS: Fixed in version 3.2-1. + + + + 17. PROBLEM: Loading an absolute binary paper tape image with "BOOT PTR" causes + the boot loader to hang. + + VERSION: 3.2-0 + + OBSERVATION: BOOT PTR looks for 12 feed frames (nulls) to signify EOT. A + real paper tape would have feed frames punched after the file data for a + trailer. + + CAUSE: At the end of the attached file, "ptr_svc" (hp2100_stddev.c) fails + if STOP_IOE is set, otherwise silently does nothing. SIMH wrongly requires + that the feed frames appear in the attached file, rather than supplying the + feed frames from the PTR simulation. If they are not in the file, the + simulation hangs, just as the real paper tape reader would do if the tape + ran out. + + RESOLUTION: Alter "ptr_svc" (hp2100_stddev.c) to fail if STOP_IOE is set, + or to supply feed frames upon encountering the end of the attached file. + "SET PTR TRLLIM" sets the maximum number of feed frames to supply. Note + that RTE needs at least 30 feed frames before signalling EOT. + + STATUS: Fixed in version 3.2-1. + + + + 18. PROBLEM: The 7900 boot loader fails to load any data from the disc into + memory. + + VERSION: 3.2-0 + + OBSERVATION: The loader completes, but memory is untouched. + + CAUSE: There is a transcription error in the boot loader code. + + RESOLUTION: Alter "dp_rom" (hp2100_dp.c) to change the erroneous "OTA 6,C" + to the correct "SFS 6,C". + + STATUS: Fixed in version 3.2-1. + + + + 19. PROBLEM: Using the DOS-III D2607 (DVR12) driver with the LPT (2607/12845) + simulation results in garbled output. + + VERSION: 3.2-0 + + OBSERVATION: Doing an "ATTACH LPT 2607.printer" and then a ":JOB,FRED" in + DOS results in the following: + + 00000000 0C 0A 4A 4F 20 52 44 20-32 4D 59 37 20 54 4D 3D ..JO RD 2MY7 TM= + 00000010 30 33 4D 4E 20 32 34 53-43 2E 4A 61 46 56 46 7F 03MN 24SC.JaFVF. + 00000020 7F 7F 7F 47 18 73 43 46-21 4D 09 1A 0B 31 1C 67 ...G.sCF!M...1.g + 00000030 0A . + + ...instead of the expected: + + 00000000 4A 4F 42 20 46 52 45 44-20 20 31 32 2D 4D 41 59 JOB FRED 12-MAY + 00000010 2D 37 35 20 20 54 49 4D-45 3D 31 30 35 33 20 4D -75 TIME=1053 M + 00000020 49 4E 2E 20 33 32 2E 31-20 53 45 43 53 2E 0D 0A IN. 32.1 SECS... + + CAUSE: The intercharacter wait time is too long (1000 instructions). The + driver waits a maximum of 300 instructions before exiting to wait for the + interrupt. However, there is a bug in the driver that garbles output if the + wait time expires. It never does when using a real printer, so the bug + wasn't seen. + + Note that the interline time (100 instructions) is actually shorter than the + intercharacter time! Also, the interline time appears to be set to the + "serial output time," which bears no relation to the parallel line printer! + + RESOLUTION: Change the intercharacter time to 5 instructions and the interline + time to 10,000 instructions in hp2100_lpt.c. + + STATUS: Fixed in version 3.2-1. + + + + 20. PROBLEM: Issuing a read on a magnetic tape for fewer words than are in the + pending record (e.g., doing ":LI,8,B" when there are more than 128 words in + the next record) results in a parity error ("IOPE L 8 E 8 S 0 22"). + + VERSION: 3.2-0 + + OBSERVATION: FMGR only reads the first 128 words of a record. Records + longer than 256 bytes should be truncated when listing. Instead, timing + errors (status 22) are reported. Records shorter than 128 words are listed + properly. + + CAUSE: DMA termination before the end-of-record is not being handled + properly by the 7970E simulator. The RTE driver sets up DMA control word 1 + with the STC bit (bit 15) clear and the CLC bit (bit 13) set. The DMA + transfer proceeds apace until DMA control word 3 (word count) goes to zero. + At this point, the last cycle logic in "dma_cycle" (hp2100_cpu.c, lines + 2477-2480) issues a CLC to the mag tape data channel. In "msdio" + (hp2100_ms.c, lines 272-275), the command and control flags are cleared in + response. + + The catch here is that the next I/O data transfer is still pending; it was + set in "msc_svc" (hp2100_ms.c, lines 461-467) via "sim_activate", because + there were still words in the buffer to transfer. When that time expires, + "msc_svc" is called again, and because the data flag is still set (the CLC + to the data channel issued by DMA to end the transfer occurred _instead_ of + the CLF that is issued between data transfers), the parity error and timing + overrun bits are set into the return status at line 462 of hp2100_ms.c. + + RESOLUTION: Alter "msc_svc" (hp2100_ms.c) to terminate a read if the + control flip-flop is reset (by DMA termination). + + STATUS: Fixed in version 3.2-1. + + + + 21. PROBLEM: Switching pending line edit modes (under EDIT or EDITR) by + entering the appropriate control codes (e.g., CTRL+I or CTRL+C) print + graphic characters that disrupt the one-for-one alignment needed for + editing. + + VERSION: 3.2-1 + + OBSERVATION: Output of control characters that normally do not print or + cause observable actions (e.g., CR or BEL) should be suppressed, so that + simulated behavior mimics the action of a real terminal. + + CAUSE: All characters except NULs are output by the TTY routine. + + RESOLUTION: Alter "tto_out" (hp2100_stddev.c) to suppress output for all + control characters (characters < 40 octal), except for BEL, BS, LF, and CR. + + STATUS: Fixed in version 3.2-2. + + + + 22. PROBLEM: Doing an EDIT pending line character insert with CTRL+S doesn't + work. + + VERSION: 3.2-1 + + OBSERVATION: CTRL+S is not passed through to the simulated program. + Instead, pressing CTRL+S and typing simply absorbs the first character, and + the editor stays in "replace" mode for the succeeding characters. + + CAUSE: The keyboard "peek" routine that checks for a pending input + character does not operate in "raw" mode. The simulator calls "_kbhit" to + determine if an input character is pending and "_getch" to retrieve that + character. "_getch" calls the Windows routine "SetConsoleMode" to set the + input mode to "raw" (i.e., no processing of the input characters). However, + "_kbhit" does not, and so the CTRL+S is intercepted and processed by + Windows. + + RESOLUTION: Modify "sim_ttrun" and "sim_ttcmd" (sim_console.c) to switch + the console into and out of "raw" mode. This inhibits "_kbhit" from + interpreting the input character stream. As an added benefit, CTRL+C is no + longer interpreted as SIGINT, so all of the associated signal-handling code + ("win_handler", etc.) may be removed. + + STATUS: Fixed in version 3.2-2. + + + + 23. PROBLEM: The documentation for the DMSMAP register set is wrong. + + VERSION: 3.2-1 + + OBSERVATION: "hp2100_doc.txt" says: + + CPU registers include the visible state of the processor as well as the + control registers for the interrupt system. + + name models size comments + + DMSMAP[4][16] 21MX 16 DMS maps + + should be: + + DMSMAP[4][32] 21MX 16 DMS maps + + ...as there are 32 map registers (1 per 1K page) per set. + + RESOLUTION: Fix the text. + + STATUS: Fixed in version 3.2-2. + + + + 24. PROBLEM: The documentation for the 7900 disc boot is wrong. + + VERSION: 3.2-1 + + OBSERVATION: "hp2100_doc.txt" says: + + The 12557A/13210A supports the BOOT command. BOOT DPC copies the IBL + for 7900 class disks into memory and starts it running. BOOT -R DP + boots from the removable platter (head 2). + + Entering "boot -r dp" gives "Non-existent device." The correct command + is "boot -r dpc". + + RESOLUTION: Fix the text. + + STATUS: Fixed in version 3.2-2. + + + + 25. PROBLEM: Logging console output to a file produces CR CR LF as line + terminators. + + VERSION: 3.2-1 + + OBSERVATION: When console logging is enabled, simulator messages as well as + the console output from the simulated system are written to the log file. + The former outputs CR LF at the end of each line. The latter outputs CR CR + LF. + + CAUSE: The log file is opened in "text mode" by default, which translates + LFs (C newlines) to CR LF sequences. Simulator messages terminate with + newlines, and these are translated to CR LF sequences. When the simulated + system writes characters to the console, they are also written to the log + file. When the simulated system outputs a CR, it is output verbatim. When + it follows that with an LF, however, that gets translated into a CR LF, so + the log file then has CR CR LF as the end of line sequence. + + RESOLUTION: Flush the accumulated file stream buffer and change the file + mode from TEXT to BINARY in "sim_ttrun" (sim_console.c) when the simulation + starts, and then back to TEXT in "sim_ttcmd" when the simulation ends. + + STATUS: Fixed in version 3.2-2. + + + + 26. ENHANCEMENT: For certain errors that stop the simulation, reset the PC to + report the instruction causing the error, rather than reporting the next + instruction. + + VERSION: 3.2-2 + + OBSERVATION: Some stops are triggered by the attempted execution of + instructions. In these cases, it is more helpful to report the instruction + causing the error than the next instruction. Currently, all stops report + the instruction beyond the cause of the stop (i.e., "P + 1"). The table + below indicates those stops where it would be more helpful to report the + instruction causing the stop (i.e., "P"): + + PC Code Message Text + ===== =========== ==================================== + P STOP_RSRV Unimplemented instruction + P STOP_IODV Non-existent I/O device + P STOP_IND Indirect address loop + P STOP_NOCONN No connection on interprocessor link + + RESOLUTION: Before exiting "sim_instr" (hp2100_cpu.c), reset "PC" to + "err_PC" for the above cases. + + STATUS: Fixed in version 3.2-3. + + + + 27. ENHANCEMENT: Add an "echo" command to print arbitrary strings on the + simulation console for use in simulation command files. + + VERSION: 3.2-2 + + OBSERVATION: Simulation command files allow automation of complex or + tedious simulator setups. Because of the potentially lengthy sequence, it + would be helpful if the command file had a way to inform the user where it + was in the process. Providing a command to do this allows messages such as + "Loading diagnostic," "Configuring diagnostic," etc., to be printed during + command file execution. + + RESOLUTION: Implement an "echo " command (scp.c). + + STATUS: Fixed in version 3.2-3. + + + + 28. PROBLEM: Booting 2000E TSB hangs after printing "READY". + + VERSION: 3.2-2 + + OBSERVATION: The code is stuck in a loop, waiting for the 7900 disc data + channel flag to set. + + CAUSE: To perform a disc read, the TSB disc driver issues a seek command + but does not wait for seek completion before issuing the read command to the + interface. This is allowed by the interface manual. The eventual interrupt + signifies the completion of both the seek and the read commands. + + However, the "drive attention" flag that is normally generated at the end of + the seek isn't set if the commands overlap in this manner. When a read + command is received with a seek in progress, the simulator cancels the seek + timer and establishes a read timer of a longer duration in its place. But + the cancellation of the seek timer also cancels the setting of the "drive + attention" bit that would have occurred had the seek completed normally, and + the simulator doesn't supply it explicitly in this case. + + The HP "7900A Disc Drive Operating and Service Manual" (07900-90002) says, + in section 4-67, "Attention is set high everytime a seek has been completed + and Access Ready comes high." + + TSB code loads the "drive attention" word from the command channel to create + a "request status" command. The code assumes that either bit 0 or bit 1 + will be set, so an "ADA =D-1" is done to transform the retrieved 000001 or + 000010 into 000000 or 000001, respectively. This effectively becomes a + "request status for unit 0/1" command, which is output to the drive as a + command. + + However, the simulator bug causes the drive attention word to be 0, so the + ADA makes the value 177777. This is an illegal command, so the data channel + flag never sets. + + RESOLUTION: Alter "dp_goc" (hp2100_dp.c) to set drive attention when seek + completion is simulated. + + STATUS: Fixed in version 3.2-3. + + + + 29. PROBLEM: Running 2000/Access, the 7900 disc fails to format. + + VERSION: 3.2-2 + + OBSERVATION: The code is hung in a loop, waiting for a drive attention flag + after the execution of an "Initialize Data" command. + + CAUSE: The 13210A disc interface passes through attention flags that the + drives generate as a result of seek completions. However, the interface + also generates its own drive attention flag at the conclusion of every + command except "Status Check." This internally generated flag is not being + provided by the 7900 simulator. + + The schematics and flowcharts in the 13210A manual indicate that a local + attention bit, derived from the unit number in the last command, is provided + at the conclusion of every command issued except: + + * "Status Check" -- executing this command clears the attention bit. + + * "Seek" -- if the drive is not ready, then a local attention bit is + provided immediately, else the attention bit from the drive is provided + when the seek completes. + + RESOLUTION: Alter (hp2100_dp.c) to provide the needed attention bits. + + STATUS: Fixed in version 3.2-3. + + + + 30. PROBLEM: Booting 2000/Access reports "CAN'T USE TAPE" when loading from + 7970. + + VERSION: 3.2-2 + + OBSERVATION: No data is returned in response to reading the first tape + record. + + CAUSE: Rewind at BOT should return immediately but is not. Access does not + wait for rewind to complete, so it issues the read command while the + transport is busy. The command is rejected, so Access tries a CLEAR and + then a retry, but a bug in Access causes DMA to be started after the CLEAR + is sent. When CLEAR completes, READ is attempted again, but DMA is not + reset. + + Also, the simulator is processing rejected commands when STC CC,C follows a + rejection. This should be a NOP. + + RESOLUTION: Change hp2100_ms.c to do immediate completion for REWIND at + BOT and to NOP an STC CC,C after a command reject. + + Note that this "fixes" the problem as long as the tape is at load point when + the Access bootstrap is run. This would normally be the case, but it + appears as though Access wouldn't work if the tape had to be rewound! + + STATUS: Fixed in version 3.2-3. + + + + 31. PROBLEM: Running the 7970 diagnostic reports "Unit not attached, P: 02741 + (CLF 77)" when executing Test 0. + + VERSION: 3.2-2 + + OBSERVATION: The error is occurring in the basic I/O test for the command + channel. The test for the data channel is succeeding. + + CAUSE: The diagnostic does a STC CC as part of the I/O test. The last + command sent was to the interface was SL3. Unit selects are not supposed to + be executed, but examination of the card schematics reveals that this will + set the command FF and the card busy bit and take no further action. The + simulator, however, is scheduling an I/O event in response, and when the + event occurs, unit 3 is not attached, so an error is reported. + + RESOLUTION: Modify "mscio" (hp2100_ms.c) to not schedule an I/O event if + the last command was a unit select. + + STATUS: Fixed in version 3.2-3. + + + + 32. PROBLEM: Running the 7970 diagnostic reports "Magtape library I/O error: + Invalid argument" when executing Test 4. + + VERSION: 3.2-2 + + OBSERVATION: The error occurs when a write is aborted with a clear command. + + CAUSE: If a CLR command is issued with a write in progress, the simulator + attempts to mark the record as bad on the tape by adding the "MTR_ERF" flag + to the "sim_tape_wrrecf" call. Unfortunately, that function does not remove + the flag before calling "sim_fwrite", and so the eventual OS call sees the + equivalent of a very large record length and therefore returns EINVAL. + + RESOLUTION: Modify "sim_tape_wrrecf" (sim_tape.c) to mask off the "MTR_ERF" + flag when determining the record length. + + STATUS: Fixed in version 3.2-3. + + + OBSERVATION: The library error is not stopping the simulator, even though + the STOP_IOE variable is set. + + CAUSE: "sim_tape_ioerr" is returning "SCPE_IOERR" instead of "MTSE_IOERR", + and "ms_map_err" maps this to "SCPE_OK", so the simulator isn't halted. + + RESOLUTION: Modify "sim_tape_ioerr" (sim_tape.c) to return "MTSE_IOERR" + instead of "SCPE_IOERR". + + STATUS: Fixed in version 3.2-3. + + + + 33. PROBLEM: Running the 7970 diagnostic reports a number of timing errors, + with events taking longer or shorter than expected. + + VERSION: 3.2-2 + + OBSERVATION: The diagnostic times certain tape functions (e.g., the time + from issuing a WRITE command until the first data is requested). Most of + these are reported as diagnostic failures. + + CAUSE: I/O time modelling is not done properly. In some cases, the times + indicated are incorrect. In others, certain characteristics (e.g., that + operations from BOT take longer, due to the initial gap) aren't modelled at + all. + + RESOLUTION: Revise "mscio" and "msc_svc" (hp2100_ms.c) to model actual I/O + timing characteristics correctly. + + STATUS: Fixed in version 3.2-3. + + + + 34. ENHANCEMENT: Provide a method of selecting between realistic and fast + (optimized) command execution times for the 7970 simulator. + + VERSION: 3.2-2 + + OBSERVATION: The 7970 diagnostic checks command execution times, so to + pass, the simulator must model these times. However, they are generally + much longer than are required by the various operating systems. + + RESOLUTION: Modify "hp2100_ms.c" to add SET MSC REALTIME, SET MSC FASTTIME, + and SHOW MSC TIMING commands. Timing is now set according to the timing + and interface models in use. + + STATUS: Fixed in version 3.2-3. + + + + 35. ENHANCEMENT: Provide a means of printing the internal state of the 7970 + tape simulator. + + VERSION: 3.2-2 + + OBSERVATION: Debugging tape errors would be easier if the tape interface + commands and status were observable and recordable. SIMH provides a "DEBUG" + mode command set to allow devices to provide this information. + + RESOLUTION: Modify "hp2100_ms.c" to add debug-mode calls. + + STATUS: Fixed in version 3.2-3. + + + + 36. PROBLEM: The 7970 tape diagnostic fails Test 12, Subtest 4. + + VERSION: 3.2-2 + + OBSERVATION: Test 12 forces data and timing errors. Execution reports: + + H154 UNIT 000000 + H102 RECORD 000103 + H054 COMMAND 000223 + H155 STATUS IS 1 000 100 010 000 010 + H155 AND SHOULD BE 1 000 000 010 010 010 + + TEST 12 + E100 DATA OR ODD BYTE ERROR + + In test 12, step 3, a 100-word WRITE is interrupted after 64 words with a + CLEAR command, followed by a WRITE FILE MARK. The diagnostic manual says, + "This procedure creates a record with a known parity error." The simulator + CLEAR command processing detects the write-in-progress and writes a + simulated tape record with the MTR_ERF flag to indicate a bad record. + + In step 4, the records are backspaced, and a READ UNTIL FILE MARK command is + issued without transferring any data. This should set the timing error bit + (bit 4) in the status word. In the status word reported, it is not set. + + CAUSE: The simulator implementation of the CLEAR command erroneously clears + the data channel command FF. When the READ UNTIL FILE MARK command is + issued, no data transfer is attempted, so the timing error does not occur. + + RESOLUTION: Modify the CLR command in "mscio" (hp2100_ms.c) to leave the + data channel control and flag FFs untouched. + + STATUS: Fixed in version 3.2-3. + + + + 37. PROBLEM: Running the RTE off-line disc backup program DBKUP and doing a + save to tape with verify hangs after printing "VERIFYING." + + VERSION: 3.2-2 + + OBSERVATION: Using the 7970 debug mode reveals that the program does a + rewind in preparation for verifying. Then, after the command completes but + while the rewind is in progress, a read is issued. This is rejected due to + REW + TBUSY being set (rewind still in progress). After rejection, a clear + is issued and completes. At this point, the program appears to hang. + + CAUSE: The RTE tape driver retries rejected commands by clearing the + interface and reissuing the originally rejected command. However, the + simulator erroneously clears both command and data channel control FFs and + sets both flag FFs in response to the CLR command. Clearing the control FFs + means that no completion interrupt is generated as a result of the CLR, so + the driver is never reentered to reissue the rejected command, and the + program stays in the I/O suspend state forever. + + RESOLUTION: Modify the CLR command in "mscio" (hp2100_ms.c) to set both + the command control and data FFs. + + STATUS: Fixed in version 3.2-3. + + + + 38. PROBLEM: The 13183A (7970) simulator reports "odd byte" status when an EOF + is detected. + + VERSION: 3.2-2 + + OBSERVATION: For the NRZI (13181A) interface, an EOF is a single special + character in the data stream, so odd byte status is set when it is detected. + For the PE (13183A) interface, EOF is an erasure pattern that is detected by + the drive itself and communicated to the interface as a status line. Odd + byte status is not set when the 13183A interface indicates an EOF. + + CAUSE: Odd byte status on EOF is not conditional on interface type. + + RESOLUTION: Modify "ms_map_err" (hp2100_ms.c) to condition odd byte status + with EOF on interface type. + + + OBSERVATION: The FSF and BSF processors in "msc_svc" treat EOF separately + from other tape errors, but the separate code takes precisely the same + action as does the generic error mapper. + + RESOLUTION: Modify "msc_svc" (hp2100_ms.c) to remove the separate + treatment and call the generic error mapper unconditionally. + + STATUS: Fixed in version 3.2-3. + + + + 39. PROBLEM: The 7970 simulator does not report "odd byte" status when a tape + record with an odd byte length is read. + + VERSION: 3.2-2 + + OBSERVATION: A tape record containing an odd number of bytes is read, but + the odd byte status bit isn't set at completion of the read. + + CAUSE: The RC and RFF processors in "msc_svc" are not testing for this + condition. + + RESOLUTION: Modify "msc_svc" (hp2100_ms.c) to set the odd byte status bit + if the last record read contained an odd number of bytes and to zero the + unused byte (as specified on page 4-11 of the 13181B manual). + + STATUS: Fixed in version 3.2-3. + + + + 40. PROBLEM: The 7970 simulator fails Test 12, Subtest 2 when configured as a + 13183A interface. + + VERSION: 3.2-2 + + OBSERVATION: The test issues a RFF command and waits for the first data + flag. It then reads status in a loop and waits for the odd byte bit to set + before continuing. If this bit doesn't set within 65K iterations, the test + fails. + + CAUSE: The 13183A hardware passes the odd/even byte FF output through as + the odd byte status bit, so this bit will be seen to toggle as data is + received. The simulator, by contrast, sets the odd byte flag only at the + end of the transfer. While the interface manual states that the odd byte + status is only valid after the command flag FF sets, the diagnostic depends + on seeing this bit toggle once during the transfer. + + The 13181A hardware enables the odd byte status bit only when the + end-of-record is detected. However, because odd byte status occurs when EOF + is detected, the diagnostic test will still succeed, albeit at the end of + the RFF command rather than at the beginning. + + RESOLUTION: Modify "msc_svc" (hp2100_ms.c) to set the odd byte status bit + at the beginning of the transfer if configured as a 13183A interface and + then to set or clear it as appropriate at the end of the transfer. + + STATUS: Fixed in version 3.2-3. + + + + 41. ENHANCEMENT: Add a configurable reel length setting to the 7970 simulator + and provide end-of-tape status returns. + + VERSION: 3.2-2 + + OBSERVATION: The 7970 diagnostic provides an option to inhibit rewinds + during test loops to allow the EOT status to be tested. The simulated tape, + however, is effectively infinite; EOT is never returned, as there is no + predefined tape length. An option to provide a simulated end-of-tape + indication would be helpful. + + RESOLUTION: Modify "hp2100_ms.c" to add SET MSCn REEL= and SHOW + MSCn REEL and to return EOT status if motion beyond the defined tape length + is attempted. Reel lengths may be set to 600, 1200, or 2400 (feet). + Setting the length to 0 inhibits EOT, i.e., the reel length is effectively + unlimited. + + Modify "mscio" to return EOT status when current tape position is beyond a + calculated end-of-tape marker position (marker position is calculated as the + ideal tape reel capacity, i.e., the number of bytes per inch times the + length of the tape in inches). + + STATUS: Fixed in version 3.2-3. + + + + 42. PROBLEM: Running the RTE off-line disc backup program PSAVE and doing a + save to a new tape gives an initial "IOPE" after specifying the tape label. + + VERSION: 3.2-2 + + OBSERVATION: Upping the driver causes the program to continue properly. + Saving to a "used" tape does not exhibit this problem. + + CAUSE: The PSAVE program is attempting to read the new tape. The tape + simulation library is reporting MTSE_EOM (end of medium), as the newly + created tape image file is zero-length. This is translated to STA_PAR by + "ms_map_err". In response, the RTE tape driver retries the read ten times + and then gives up and reports the parity error. + + RESOLUTION: End-of-medium has no hardware analog; one cannot have a + physical tape of zero length. So the translation to simulated tape status + is arbitrary. A new physical tape will "run away," i.e., never return data. + Some programs, e.g., the RTE tape driver, are written to detect this. + However, those that aren't will simply hang. A more useful translation is + to return EOF marks when a motion is attempted beyond the end of the medium, + as many programs interpret two successive EOFs as "logical end-of-medium." + + Modify "ms_map_err" (hp2100_ms.c) to return EOF status for MSTE_EOM. + + STATUS: Fixed in version 3.2-3. + + + + 43. PROBLEM: EDIT/1000 uses the HT character (CTRL+I) to insert a tab, but + printing of this character is suppressed. + + VERSION: 3.2-2 + + OBSERVATION: There is no visual indication that the TAB key was pressed to + insert a HT character. + + CAUSE: "CNTL_SET" does not include the HT character. + + RESOLUTION: Modify "hp2100_stddev.c" to add "HT_FLAG", defined as + "CHAR_FLAG('\t')", to "CNTL_SET". + + STATUS: Fixed in version 3.2-3. + + + + 44. PROBLEM: The 7900 disc diagnostic fails Step 55 if two or more units are + connected. + + VERSION: 3.2-2 + + OBSERVATION: Altering the unit table at the start of the diagnostic to + include two units (e.g., "0,1") and then running a short pass produces this + output: + + H65 SHORT PASS 0004,HEADS 0/1,UNIT 00, 0000 ERRORS + H44 SEEK IN STEP 55 + E10 NO COMMAND FLAG + H33 ATTENTION/SEEK-STATUS + 000002 000000 + H51 CYL 0202 HEAD 01 SECTOR 19 WORD COUNT 0128 UNIT 00 + + The step tests overlapping seeks. + + CAUSE: The command channel flag set that normally indicates seek command + completion is not being deferred by the CLC CC issued in preparation for + sending another command. The simulator must defer the flag set until a + subsequent STATUS CHECK command is issued (this command normally does not + set the command channel flag but will do so if a pending drive attention + bit is set). + + RESOLUTION: Add a "poll attention" state to the simulator and set the + command channel flag if polling is enabled and one or more drive attention + bits are set. + + STATUS: Fixed in version 3.2-3. + + + + 45. PROBLEM: The 7900 disc diagnostic fails the not-ready tests in Step 14. + + VERSION: 3.2-2 + + OBSERVATION: Running the 7900 diagnostic with S bit 4 set to execute the + interactive part of Section 1 causes this failure: + + H70 UNLOAD UNIT 0,PUSH RUN + + HALT instruction 102002, P: 03364 (JSB 1430) + sim> detach dpc0 + sim> go + H46 READ IN STEP 14 + E64 STATUS IS 000101 SHOULD BE 000105 + H51 CYL 0202 HEAD 00 SECTOR 00 WORD COUNT 1024 UNIT 00 + + The diagnostic is expecting the DRIVE BUSY bit to be set. + + CAUSE: The "unit not attached" simulator state maps to the "drive not + ready" hardware state. In this state, both the NOT READY and the DRIVE BUSY + status bits should be set. + + Referring to the "Drive Control Assembly A9" schematic on page 5-43 of the + "7900A Disc Drive Operating and Service Manual" (HP 07900-90002), the "Drive + Ready" signal is forced low via U22B if the "Load Switch Off" signal is + asserted (setting the "Load Switch" off unloads the heads). Also, the + "Access Ready" signal is forced low via U35A if the "Drive Ready" signal is + low. Schematic "Input/Output Multiplex Assembly A7" on page 5-39 shows that + these signals are inverted and driven onto the cable to the CPU interface. + + The 13210A interface manual schematic for "Disc Interface PCA 1" shows that + both signals are inverted twice and presented to the CPU as status bits 6 + and 2, respectively. So "not Drive Ready" becomes NOT READY, and "not + Access Ready" becomes DRIVE BUSY. + + RESOLUTION: Modify "dpd_svc" (hp2100_dp.c) to set both the NOT READY and + DRIVE BUSY bits when the unit is not attached. + + STATUS: Fixed in version 3.2-3. + + + + 46. PROBLEM: The 7900 disc diagnostic loops forever in Step 15. + + VERSION: 3.2-2 + + OBSERVATION: Running the 7900 diagnostic with S bit 4 set to execute the + interactive part of Section 1 causes this failure: + + H40 PROTECT U/D THEN READY UNIT 0 + + [CTRL+E] + Simulation stopped, P: 76734 (TIMER) + sim> set dpc0 locked + sim> att dpc0 7900-U0.scratch.disc + sim> go + + H40 PROTECT U/D THEN READY UNIT 0 + H40 PROTECT U/D THEN READY UNIT 0 + H40 PROTECT U/D THEN READY UNIT 0 + + The diagnostic is waiting for the CC flag to set when the drive becomes + ready (i.e., when the unit is attached). + + CAUSE: Section 4-67 of the "7900A Disc Drive Operating and Service Manual" + (HP 07900-90002) says, "Attention is set high everytime a seek has completed + and Access Ready comes high." This includes the initial head-loading seek + when the drive becomes ready. The "Troubleshooting Diagrams (Sheet 2 of 4)" + on page 5-17 show that after the heads load, Drive Ready, First Status, + Access Ready (a.k.a. not Busy), and Attention are asserted. The + corresponding code in "dpc_attach" sets First Status but not Attention. + + In addition, the last diagnostic command prior to the loop is a STATUS + CHECK. This leaves the 13210A interface polling for attention bits, and + when one is asserted, the command channel flag FF is set. However, the + simulator makes no provision for this; the flag is checked once at the end + of the status command, but no further checks are made thereafter. + + RESOLUTION: Modify "dpc_attach" (hp2100_dp.c) to set the ATN flag when the + unit is attached and, if drive polling is enabled, to set the command + channel flag. + + STATUS: Fixed in version 3.2-3. + + + + 47. PROBLEM: The 7900 disc diagnostic fails the write-protect tests in Step 16. + + VERSION: 3.2-2 + + OBSERVATION: Running the 7900 diagnostic with S bit 4 set to execute the + interactive part of Section 1 causes this failure: + + H40 PROTECT U/D THEN READY UNIT 0 + + [CTRL+E] + Simulation stopped, P: 76734 (TIMER) + sim> set dpc0 locked + sim> attach dpc0 7900-U0.scratch.disc + sim> go + + H44 SEEK IN STEP 16 + E64 STATUS IS 040001 SHOULD BE 042001 + H51 CYL 0000 HEAD 00 SECTOR 00 WORD COUNT 0128 UNIT 00 + + The diagnostic is expecting the DATA PROTECT bit to be set. + + CAUSE: The UNIT_WPRT flag is being checked in the FNC_STA processing in + "dpd_svc", but the referenced unit is the data channel unit, not the command + channel unit where the flag is actually set. + + RESOLUTION: Alter "dpd_svc" (hp2100_dp.c) to check the command channel unit + instead of the data channel unit when looking for write-protect indication. + + STATUS: Fixed in version 3.2-3. + + + + 48. PROBLEM: The 7970E diagnostic hangs in test 33 if the tape is not at BOT. + + VERSION: 3.2-2 + + OBSERVATION: The test issues a REWIND/OFFLINE to each unit in turn and + looks for the REW status bit to deny before proceeding. + + CAUSE: The simulator resets this bit for the REWIND command but not for + REWIND/OFFLINE. More generically, though, the simulator is reporting unit + status (REW, BOT) when the unit is off-line. + + RESOLUTION: Modify "mscio" (hp2100_ms.c) to remove unit-specific status + from the status return when the unit is not attached. + + STATUS: Fixed in version 3.2-3. + + + OBSERVATION: The status for REWIND/OFFLINE when not at BOT isn't quite + correct. The hardware indicates "Rewinding" (bit 10) for a short time + before going off-line. + + CAUSE: The simulator is detaching (i.e., going off-line) immediately upon + command execution. + + RESOLUTION: Modify "mscio" (hp2100_ms.c) to detach after the interface + execution delay. + + STATUS: Fixed in version 3.2-3. + + + OBSERVATION: The status for REWIND and REWIND/OFFLINE when at BOT isn't + quite correct. The hardware does not indicate "Tape Unit Busy" (bit 9) if + the unit is at BOT, because the tape never moves. + + CAUSE: The simulator generates "Tape Unit Busy" whenever a service event is + scheduled, but this status should not occur if a rewind is issued at BOT. + + RESOLUTION: Modify "mscio" (hp2100_ms.c) to condition STA_TBSY on rewind at + BOT. + + STATUS: Fixed in version 3.2-3. + + + + 49. PROBLEM: The "do" command does not obey the "-v" ("verbose") option switch + when console logging is in effect. + + VERSION: 3.2-2 + + OBSERVATION: Command file commands are always written to the console log + file, regardless of the setting of the "-v" switch. Commands are only + displayed on the console when "-v" is specified. The console log file, + therefore, is not a copy of what appeared on the console. + + CAUSE: Output of the file commands is not conditional on the "-v" switch. + + RESOLUTION: Modify "do_cmd" (scp.c) to condition writing file commands to + the console log on the "-v" switch. + + STATUS: Fixed in version 3.2-3. + + + + 50. PROBLEM: The "echo" command does not echo to the console log file. + + VERSION: 3.2-2 + + OBSERVATION: The "echo" command writes its argument only to the console. + If logging is in effect, the echoed strings will not appear in the file. + + CAUSE: This action was omitted. + + RESOLUTION: Modify "echo_cmd" (scp.c) to copy the echoed argument string to + the console log file if logging is in effect. + + STATUS: Fixed in version 3.2-3. + + + + 51. PROBLEM: The diagnostic configurator mis-identifies the host CPU. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic configurator in conversational mode + produces these hardware detection results using various CPU settings (note + that STOP_INST must first be set to 0 to prevent unimplemented instruction + traps): + + set cpu 2116 --> "2114, DMA, NO MPRT, 32K MEMORY" + set cpu 2100 --> "21MX E, DMA, NO MPRT, 32K MEMORY" + set cpu 21MX --> "21MX E, DMA, MPRT, 32K MEMORY" + + CAUSE: Two model-specific behaviors are not implemented: + + * The S-register is read-only on the 2115/2116. + + * LIA 6/7 (actually, the "floating" state of the internal S-bus) returns + -1 on the 21MX, and 0 on the 2114/2115/2116/2100. + + These behaviors are tested by the configurator to determine the CPU type. + + NOTE: the 21MX is detected as a "E-Series" model. This is due to the + presence of the TIMER instruction (TIMER is not implemented on the + "M-Series" and is decoded as an MPY instruction on that system). + + RESOLUTION: Modify "ovfio", "dmpio", and "nulio" (hp2100_cpu.c) to + implement the above behaviors. + + STATUS: Fixed in version 3.3-0. + + + + 52. PROBLEM: Displaying the CCA, CCB, and CCE instructions via "examine -m" + prints "CLA,CMA", "CLB,CMB", and "CLE,CME" respectively. + + VERSION: 3.2-3 + + OBSERVATION: While "CLA,CMA" (e.g.) is logically what the "CCA" instruction + does, it is invalid assembler syntax (although it is accepted by the + "deposit" routine). + + CAUSE: The "mtab" array contains values to mask the instruction under + consideration to the significant bits. For the CLA/B, CMA/B, and CCA/B + instructions, the mask values are 006400, 007000, and 007400, respectively. + They should all be 007400. For the CLE, CME, and CCE instructions, the mask + values are 002100, 002200, and 002300. They should all be 002300. + + RESOLUTION: Modify "mtab" (hp2100_sys.c) to use the proper masks for these + alter-skip group instructions. + + STATUS: Fixed in version 3.3-0. + + + + 53. PROBLEM: The paper tape diagnostic has several tests that depend on + creating and using a tape loop. + + VERSION: 3.2-3 + + OBSERVATION: Tests 4, 5, and 11 use a loop of tape. The pattern for the + loop is punched by test 7. To run tests 4, 5, and 11, multiple copies of + the pattern must be stored in a "loop" file, and the tests must be exited + before the "loop" runs out. A better solution would be to have a settable + "loop mode" that rewinds the tape image file when EOF is encountered. + + RESOLUTION: Modify "ptr_mod" (hp2100_stddev.c) to add SET PTR DIAG and + SET PTR READER commands, and modify "ptr_svc" to add support for loop mode. + + STATUS: Fixed in version 3.3-0. + + + + 54. PROBLEM: The time base generator (CLK) cannot be disabled. + + VERSION: 3.2-3 + + OBSERVATION: The TBG was an option for HP systems, and certain DOS + operating system features behave differently, depending on the presence or + absence of the TBG. It is desirable to allow those features to be observed + during simulation. + + CAUSE: The "clk_dev" structure lacks the DEV_DISABLE flag. + + RESOLUTION: Modify "clk_dev" (hp2100_stddev.c) to add the DEV_DISABLE flag. + + STATUS: Fixed in version 3.3-0. + + + + 55. ENHANCEMENT: Move the memory protect simulation from the CPU to a new MP + device, allow MP to be disabled, and add the 12892B memory protect feature + jumpers W5 (JSB), W6 (INT), and W7 (SEL1). + + VERSION: 3.2-3 + + OBSERVATION: Memory protect is an option card in 2116/21MX systems and + should have its own device entry in the simulator. The device should be + disabled to indicate that the card is absent. + + Setting the CPU model to 2100 or 21MX should enable MP, although it may be + subsequently disabled if desired. Setting the CPU model to 2116 should + disable MP. The simulator should initialize with MP disabled. + + The "B" version of the 21MX memory protect card added three jumpers to + modify the "standard" memory protect behavior. The W5 (JSB) option + prohibited JSB to locations 0 and 1. The W6 (INT) option inhibited the + indirect interrupt holdoff. The W7 (SEL1) option allowed I/O instructions + referencing select codes other than 1. + + RESOLUTION: Modify "hp2100_cpu.c" to create the MP device and add commands + for setting the above options and support for the associated features. + + STATUS: Fixed in version 3.3-0. + + + + 56. ENHANCEMENT: Allow DMA to be disabled. + + VERSION: 3.2-3 + + OBSERVATION: DMA is an option card on all machines, so disabling it should + be allowed. Note that disabling DMA0 should disable DMA1 and vice-versa. + (There was no single-channel DMA option except on the 2114.) + + RESOLUTION: Modify "hp2100_cpu.c" to permit DMA to be disabled. + + STATUS: Fixed in version 3.3-0. + + + + 57. PROBLEM: Setting the CPU to 21MX and a memory size > 32K and then changing + the CPU to either 2100 or 2116 does not reset the memory size to a legal + value. + + VERSION: 3.2-3 + + OBSERVATION: The 2100 and 2116 machines have a maximum memory size of 32K. + This limit is enforced when setting the memory size, i.e., "Invalid + argument" is reported when attempting to set these machines to a memory size + > 32K. However, if the machine is first set to 21MX, the memory size is + increased beyond 32K, and then the machine is reset to 2100 or 2116, the + memory size will remain larger than 32K. + + CAUSE: No check on memory size is made when the machine type is set. + + RESOLUTION: Modify "cpu_mod[]" (hp2100_cpu.c) to call "cpu_set_opt" when + changing the CPU model, and modify "cpu_set_opt" to call "cpu_set_size" + if the current memory size is > 32K and the new model is 2100 or 2116. If + the memory above 32K is not empty, and the "Really truncate memory" question + is answered in the negative, "Command not completed" is printed, and the CPU + change is aborted. + + STATUS: Fixed in version 3.3-0. + + + + 58. PROBLEM: According to the HELP display, SET , SET , and SET + CONSOLE should allow a comma-separated list of parameters, but such commands + are rejected with "Non-existent parameter." + + VERSION: 3.2-3 + + OBSERVATION: Doing HELP SET lists the following syntax for the above + commands: + + set console arg{,arg...} set console options + set arg{,arg...} set device parameters + set arg{,arg...} set unit parameters + + None of these work, however, as each accepts only a single argument. Note + that the corresponding SHOWs do accept multiple arguments. + + CAUSE: The "get_glyph" routines that parse the command parameters are + missing the option to indicate that commas are glyph separators. + + RESOLUTION: Modify the appropriate calls to "get_glyph" (scp.c, + sim_console.c) to specify ',' as the the "optional end of glyph character" + parameter. + + STATUS: Fixed in version 3.3-0. + + + + 59. ENHANCEMENT: The 2607 line printer simulator (LPT) now supports local + OFFLINE/ONLINE and POWEROFF/POWERON settings. + + VERSION: 3.2-3 + + OBSERVATION: The 2607 printer returns different status for power-off and + offline conditions. A local "power off" command is needed to simulate the + power-off or cable-disconnected state, and a local offline command is needed + to simulate the PRINT button up state. This allows proper status to be + returned to programs that expect it (e.g., RTE, diagnostics). + + RESOLUTION: Modify "lptio" (hp2100_lpt.c) to implement local power off and + offline settings and to return proper status for these conditions. + + STATUS: Fixed in version 3.3-0. + + + + 60. PROBLEM: The 2607 line printer simulator (LPT) does not supply the proper + status for the paper-out condition. + + VERSION: 3.2-3 + + OBSERVATION: Paper-out is simulated by detaching the printer image file. + When detached, the simulator returns status 040000 (paper out). However, + the 12845 Line Printer Operating and Service Manual (HP 12845-90001) states + in section 2-33, "[The paper-out] signal is asserted only when the format + tape in the line printer has reached the bottom of form." So the expected + status should be 000000 unless the printer is positioned at BOF. + + CAUSE: "lptio" is not checking for BOF before returning paper-out status. + + RESOLUTION: Modify "lptio" (hp2100_lpt.c) to set the paper-out status bit + only if the current print location is BOF. + + STATUS: Fixed in version 3.3-0. + + + + 61. PROBLEM: Issuing a TOF to the 2607 line printer (LPT) leaves the paper on + the second line instead of the first. + + VERSION: 3.2-3 + + OBSERVATION: The RTE driver for the 2607 printer implements a top-of-form + request by issuing a VFU call to channel zero. On a real printer, this + leaves the paper positioned at the first line on the page. The simulator, + however, leaves the paper positioned at the second line. Examining the LPT + registers shows that LCNT is 0 immediately after an ATTACH but is 1 after a + TOF request. + + CAUSE: The TOF is simulated by sending a form-feed to the printer image + file. This is being incorrectly followed by a line-feed and a line counter + increment. + + RESOLUTION: Modify "lpt_svc" (hp2100_lpt.c) to suppress the line-feed and + line counter increment after a TOF request. + + STATUS: Fixed in version 3.3-0. + + + + 62. ENHANCEMENT: The 2767 line printer simulator (LPS) now supports local + OFFLINE/ONLINE and POWEROFF/POWERON settings. + + VERSION: 3.2-3 + + OBSERVATION: The 2767 printer returns different status for power-off and + offline conditions. A local "power off" command is needed to simulate the + power-off or cable-disconnected state, and a local offline command is needed + to simulate the PRINT button up state. This allows proper status to be + returned to programs that expect it (e.g., RTE, diagnostics). + + RESOLUTION: Modify "lpsio" (hp2100_lps.c) to implement local power off and + offline settings and to return proper status for these conditions. + + STATUS: Fixed in version 3.3-0. + + + + 63. PROBLEM: Command files that reduce CPU memory size cannot run unattended. + + VERSION: 3.2-3 + + OBSERVATION: Command files that change CPU settings will pause for operator + intervention if memory size is being reduced, previous memory size was more + than 32K, and the memory being truncated contained non-zero data. In this + case, a prompt ("Really truncate memory?") is issued to the console. As the + response is not taken from the command file, there is no way to continue + without user intervention. + + CAUSE: The "cpu_set_size" routine calls "get_yn", which reads from "stdin." + + RESOLUTION: Modify "cpu_set_size" (hp2100_cpu.c) to respond to a new "-F" + switch that indicates that truncation should be forced without prompting. + + STATUS: Fixed in version 3.3-0. + + + + 64. PROBLEM: Attempting to output to the 2767 simulator (LPS) via RTE-IVB + causes not-ready and illegal interrupt errors. + + VERSION: 3.2-3 + + OBSERVATION: With the 2767 printer assigned to select code 21 and logical + unit 12, attempting to print results in "IONR L 12 E12 S 0 0", followed by + one "ILL INT 21" error for each character output. + + CAUSE: The RTE driver understands that the 2767 prints in four 20-character + zones and that character output within a zone is buffered. It therefore + assumes that a buffered character will be accepted within three instruction + times. If the printer is still busy after that, the printer is declared "not + ready" and is downed. Subsequent interrupts are not expected (the printer + is assumed to be malfunctioning), resulting in the illegal interrupt + messages. + + The 2767 simulator defines the character transfer time as four instructions + and has no provision for detecting print zones. The driver assumes that it + can fill a zone rapidly within the driver and will have to exit the driver + to wait for an interrupt at the end of each zone. + + RESOLUTION: Modify "lpsio" and "lps_svc" (hp2100_lps.c) to reduce the + buffer transfer time to two instructions and to determine the end of a zone + in order to take an appropriately longer time before interrupting. + + STATUS: Fixed in version 3.3-0. + + + + 65. ENHANCEMENT: Provide a method of selecting between realistic and fast + (optimized) command execution times for the 2767 simulator. + + VERSION: 3.2-3 + + OBSERVATION: The 2767 diagnostic checks command execution times, so to + pass, the simulator must model these times. However, they are generally + much longer than are required by the various operating systems. + + RESOLUTION: Modify "hp2100_lps.c" to add SET LPS REALTIME and SET LPS + FASTTIME commands. Timing is now set according to the timing model in use. + + STATUS: Fixed in version 3.3-0. + + + + 66. ENHANCEMENT: Provide a means of printing the internal state of the 2767 + printer simulator. + + VERSION: 3.2-3 + + OBSERVATION: Debugging printer errors would be easier if the printer + interface commands and status were observable and recordable. SIMH provides + a "DEBUG" mode command set to allow devices to provide this information. + + RESOLUTION: Modify "hp2100_lps.c" to add debug-mode printouts. + + STATUS: Fixed in version 3.3-0. + + + + 67. PROBLEM: The console "break" and "delete" character settings are not saved + across a simulation SAVE/RESTORE. + + VERSION: 3.2-3 + + OBSERVATION: The console interrupt character set via SET CONSOLE WRU= + is preserved when the simulation is SAVEd and then later RESTOREd. However, + the values set via SET CONSOLE BRK= and SET CONSOLE DEL= are lost + and revert to their default settings. + + CAUSE: Only "sim_int_char" is included in the hidden CPU state. + + RESOLUTION: Modify "cpu_reg" (hp2100_cpu.c) to include BRK and DEL + registers corresponding to "sim_brk_char" and "sim_del_char". + + STATUS: Fixed in version 3.3-0. + + + + 68. PROBLEM: Attached device output files and debug log files cannot be + examined after a simulation stop. + + VERSION: 3.2-3 + + OBSERVATION: After stopping simulation, either via a breakpoint or CTRL+E, + viewing attached device output files or the device debug log file reveals + incomplete data, limiting the ability to determine what has been output at + the point of interruption. + + CAUSE: All files are buffered, and the last bytes output haven't been + flushed to disk. + + RESOLUTION: Modify "run_cmd" (scp.c) to flush the console log file, the + debug log file, and any attached output files before returning. + + STATUS: Fixed in version 3.3-0. + + + + 69. PROBLEM: Attempting to disable the DP controller by doing SET DPD DISABLED + is rejected with "Command not allowed." Attempting to disable the DR + controller by doing SET DRD DISABLED is accepted, but the controller remains + enabled. + + VERSION: 3.2-3 + + OBSERVATION: Section 2.3 of "hp2100_doc.txt" states, "For devices with more + than one device number, disabling or enabling any device in the set disables + all the devices." This is not true, however, for most multiple-card + devices. SET DISABLED is rejected for the DPD, DQD, MSD, MUXL, and + MUXM devices. For the DRD, IPLI, and MTD devices, the command is accepted + but does not disable the device. + + CAUSE: The "DEV_DISABLE" flag is missing from the "DEVICE" structures of + the DPD, DQD, MSD, MUXL, and MUXM devices. Also, for all multiple devices, + the device "dev_reset" function must call "hp_enbdis_pair" with the + appropriate parameter to synchronize the enable/disable state of both + devices. + + RESOLUTION: Modify the "DEVICE" structures and "dev_reset" routines as + needed to the affected source files (hp2100_dp.c, hp2100_dq.c, hp2100_dr.c, + hp2100_ipl.c, hp2100_ms.c, hp2100_mt.c, and hp2100_mux.c). + + STATUS: Fixed in version 3.3-0. + + + + 70. PROBLEM: The 2871 disc diagnostic fails Status Checks in Step 1. The + checks are related to the ANY ERROR bit. + + VERSION: 3.2-3 + + OBSERVATION: Running the 2871 diagnostic causes this failure: + + H44 SEEK IN S1 + E64 STATUS IS 000001 SHOULD BE 000000 + H51 CYL 0000 HEAD 00 SECTOR 00 WORD COUNT 0000 UNIT 00 + + The diagnostic is not expecting the ANY ERROR bit (bit 0) to be set with the + ATTENTION bit (bit 15). The simulator is returning status 100001 from the + seek operation (bit 15 is always masked by the diagnostic before reporting). + + Resuming the diagnostic produces this error: + + H44 SEEK IN S1 + E64 STATUS IS 000005 SHOULD BE 000004 + H51 CYL 0001 HEAD 00 SECTOR 00 WORD COUNT 0000 UNIT 00 + + The diagnostic is not expecting the ANY ERROR bit (bit 0) to be set with the + BUSY bit (bit 2). + + CAUSE: The ANY ERROR bit is set by the simulator if any status bit is set + other than bit 10 (HUNTING) or bit 7 (unused). This is correct for the + 13210A interface but not for the 12557A interface. + + From the "12557A Cartridge Disc Interface Operating and Service Manual" (HP + 12557-90001, September 1970), Table 2.6, "Disc Status Word" lists the + following meanings for the status bits: + + Bit 0: ANY ERROR. A "1" indicates that any of the remaining 15 bits + (except bits 2, 3, and 7) is a "1". + + Bit 15: ATTENTION. A "1" indicates that an operation previously in + progress on the selected disc drive unit has terminated either + through normal completion or due to occurrence of an error or + other unusual condition. During execution of all commands except + Status Check, the condition is generated when command execution + terminates regardless of the cause for termination. + + This would imply that the ANY ERROR bit would set with the ATTENTION bit. + However, on page 2-16, Section 2.50, "Design Considerations," this + statement appears: + + Following each interrupt, the program must issue a Status Check command to + the disc drive unit that executed the storage command and verify that the + ANY ERROR bit (bit 0) is not a "1" in the disc status word. + + Given that the ATTENTION bit sets for each command completion, and given + that the ANY ERROR bit is expected to be zero after a normal command + completion, the implication is that ATTENTION does not set ANY ERROR. + + RESOLUTION: Modify "dpcio" (hp2100_dp.c) to set the ANY ERROR bit for all + status bits except bits 2, 3, 7, and 15 if the 12557A interface is selected. + + STATUS: Fixed in version 3.3-0. + + + + 71. PROBLEM: The 2871 disc diagnostic fails not-ready Status Checks in Step 0. + + VERSION: 3.2-3 + + OBSERVATION: Running the 2871 diagnostic causes this failure: + + H43 UNIT 0 NOT READY CHECK IN S0 + E64 STATUS IS 000105 SHOULD BE 000101 + H51 CYL 0202 HEAD 00 SECTOR 00 WORD COUNT 3072 UNIT 00 + + The diagnostic is not expecting the DRIVE BUSY bit (bit 2) to be set when + the drive is not ready. + + CAUSE: The simulator is returning both NOT READY and DRIVE BUSY. This is + correct for the 13210A interface but not for the 12557A interface. + + RESOLUTION: Modify "dpd_svc" (hp2100_dp.c) to set the DRIVE BUSY bit for + the "drive not ready" condition only if the 13210A interface is selected. + + STATUS: Fixed in version 3.3-0. + + + + 72. PROBLEM: The 2871 disc diagnostic fails the head-load test in Step 0. + + VERSION: 3.2-3 + + OBSERVATION: Running the 2871 diagnostic reports this message to test for + head loading: + + H40 READY UNIT 0 + + After stopping the simulation, attaching a disc image file, and resuming, + the above message continues to repeat. The diagnostic is expecting the + command-channel flag to set and drive status to return ATTENTION (bit 15) + and FIRST SEEK (bit 14). + + CAUSE: To prepare the interface to poll for drive attention, the diagnostic + issues a Status Check command to the interface. However, because the + returned status word is not of interest, the diagnostic does not precede + this with an STC,C to the data channel. As the data command flip-flop is + not set, the simulator waits in "dpd_svc" in state "FNC_STA", rather than + proceeding to state "FNC_STA1", where the poll flag is set. With the poll + flag clear, the subsequent file attach does not set the command-channel flag + or the associated drive status. + + Figure 3-7, "Status Check Operation Flow Diagram", on page 3-17 of the + "12557A Cartridge Disc Interface Operating and Service Manual" (HP + 12557-90001, September 1970) implies that the data-channel command flip-flop + must be set before the command-channel control flip-flop is set to initiate + the command. However, there is no hardware interlock on the interface to + require this. Moreover, the diagnostic clearly expects the drive attention + to be detected, so the drive poll must occur, even without the data + transfer. + + The STC DC asserts the "data encode" signal to the disc controller, and the + STC CC asserts the "command encode" signal. The latter initiates the Status + Check operation, but there is no indication as to what happens if the "data + encode" assertion does not precede it. Typical operation would be that + "device encode" initiates the operation and "device flag" signals the + termination. Without "device encode", "device flag" wouldn't occur. Based + on the diagnostic expectation, the implication is that the data-channel flag + does not set, but the Status Check command does complete, and drive polling + does start. + + RESOLUTION: Modify "dpd_svc" (hp2100_dp.c) to complete the Status Check + command and proceed to polling without setting the data-channel flag if the + command flip-flop is not set, and the 12557A interface is selected. + + STATUS: Fixed in version 3.3-0. + + + + 73. PROBLEM: The 2883 diagnostic fails the cyclic-check test in Step 4. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H22 CYCLIC CHECK IN S4 + E10 NO COMMAND FLAG + H51 CYL 0000 HEAD 00 SECTOR 00 WORD COUNT 0000 UNIT 00 + + The error is a result of the diagnostic executing a Cyclic Check command + with a sector count of 0. Coupled with an initial seek to cylinder 0, + head 0, and sector 0, this should check the maximum of 460 sectors before + terminating with an End of Cylinder status. + + CAUSE: The diagnostic is timing out. The "12565A Disc Interface Kit + Operating and Service Manual" (HP 12565-90003, August 1973) states in + Section 2-45 on page 2-11, "The data rate of the disc drive is 156,000 words + per second," giving a transfer time of 6.41 microseconds. At an average of + 2 microseconds per instruction, the transfer time should be 3 instructions. + It is currently set to 5. + + RESOLUTION: Change "dqc_xtime" (hp2100_dq.c) from 5 to 3. + + STATUS: Fixed in version 3.3-0. + + + + 74. PROBLEM: The 2883 disc diagnostic fails not-ready Status Checks in Step 0. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H43 UNIT 0 NOT READY CHECK IN S0 + E64 STATUS IS 000104 SHOULD BE 000101 + H51 CYL 0202 HEAD 19 SECTOR 00 WORD COUNT 0046 UNIT 00 + + The diagnostic is expecting the ANY ERROR bit (bit 0) and is not expecting + the POSITIONER BUSY bit (bit 2) to be set when the drive is not ready. + + CAUSE: The simulator is returning both NOT READY and POSITIONER BUSY. From + the "12565A Disc Interface Kit Operating and Service Manual" (12565-90003, + Aug-1973), page 2-12, Table 2-5, "Disc Status Word," we have: + + Bit 6, NOT READY. A "1" indicates that the selected disc drive unit is + not connected to the disc controller, or is not sequenced up with disc + spinning and heads loaded, or is in an unsafe condition. + + Bit 2, POSITIONER BUSY. A "1" indicates the selected drive is busy + executing a Position command. + + Bit 0, ANY ERROR. A "1" indicates that "PL0 unsafe" condition has been + detected or that one or more of the remaining 7 bits is a "1". + + RESOLUTION: Modify "dqd_svc" (hp2100_dq.c) to set the ANY ERROR bit and + remove the POSITIONER BUSY bit for the "drive not ready" condition. + + STATUS: Fixed in version 3.3-0. + + + + 75. PROBLEM: Doing an OTA/OTB to the command channel of the 13210A interface + fails to clear the control and command flip-flops. + + VERSION: 3.2-3 + + OBSERVATION: From the "13210A Disc Drive Interface Kit Operating and + Service Manual" (13210-90003, Nov-1974), examination of Figure 5-2, "Disc + Interface 1 PCA Schematic Diagram" shows that doing an OTA or OTB to the + command channel will clear the control and command flip-flops. Gate U16C + feeds both the qualified CLC and IOO signals to the reset side of the + command-channel control flip-flop. Therefore, an output operation + additionally will act as though a CLC had been done. + + CAUSE: The action was omitted. + + RESOLUTION: Modify "dpcio" (hp2100_dp.c) to perform a CLC CC if an OTA or + OTB CC occurs, and the 13210A interface is selected. + + STATUS: Fixed in version 3.3-0. + + + + 76. PROBLEM: The 2883 disc diagnostic fails the multi-unit Cyclic Check test in + Step 5. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H22 CYCLIC CHECK IN S5 + E64 STATUS IS 000000 SHOULD BE 000021 + H51 CYL 0001 HEAD 00 SECTOR 00 WORD COUNT 0128 UNIT 00 + + The diagnostic does a seek to CHS 0/0/0 of unit 0, followed by a seek to CHS + 1/0/0 of unit 1, followed by a Cyclic Check of one sector of unit 0. This + should cause ADDRESS ERROR, because the second seek sets the controller + Record Address Register (RAR) to 1/0/0, the read of unit 0 is done from + 0/0/0 (set by the first seek), and the two do not compare. However, the + simulator returns NO ERROR. + + CAUSE: The DQ simulator has separate RARs for each unit. The 12565A + controller has a single RAR that is shared between all units. (Note that + the DP simulator has the same problem.) + + RESOLUTION: Modify "hp2100_dq.c" and "hp2100_dp.c" to implement a single, + shared RAR and per-unit current positions. + + STATUS: Fixed in version 3.3-0. + + + + 77. PROBLEM: The 2773 (DR) drum diagnostic is unable to determine the number of + sectors per track during initialization. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H46 DEVICE PARAMETER DETERMINATION + E47 UNABLE TO DETERMINE SECTORS PER TRACK + H44 TRACK 0000 SECTOR 00 WORD COUNT 0000 + + The diagnostic is attempting to determine the number of sectors per track by + repeatedly reading the disc status word and examining the current sector + field. + + CAUSE: The disc status word is malformed. The next sector address should + appear in bits 14-8, but instead they are ORed with the lower-byte status + flags, corrupting the status return value. + + RESOLUTION: Modify "drcio" (hp2100_dr.c) to shift the next sector address + to the upper byte before merging the status flags. + + STATUS: Fixed in version 3.3-0. + + + + 78. PROBLEM: The 2773 (DR) drum diagnostic reports read/write status failures. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H41 WRITE IN ST + E35 STATUS IS 0 000 110 010 000 000 + SHOULD BE D DDD DDD D10 D00 1D0 + H44 TRACK 0000 SECTOR 00 WORD COUNT 0064 + + The diagnostic is expecting the Writing Enabled Flag bit to be set. + + CAUSE: The simulation fails to return Writing Enabled status on tracks for + which writing is permitted (all tracks). + + RESOLUTION: Modify "drcio" (hp2100_dr.c) to set the Writing Enabled status + when the track control word is output. + + STATUS: Fixed in version 3.3-0. + + + + 79. PROBLEM: The 7900 disc drive (DP) fails to seek check if an invalid sector + is supplied. + + VERSION: 3.2-3 + + OBSERVATION: From the "13210A Disc Drive Interface Kit Operating and + Service Manual" (13210-90003, Nov-1974), section 3-55 states that Seek Check + status is set during a Seek command for three conditions: the cylinder + addressed is greater than 202, the sector addressed is greater than 23, or a + head-positioning operation is still in progress. The simulator fails to + implement the second condition. + + CAUSE: The check is omitted. + + RESOLUTION: Modify "dpd_svc" (hp2100_dp.c) to set Seek Check status if the + sector is out of range and the 13210A interface is selected. + + STATUS: Fixed in version 3.3-0. + + + + 80. PROBLEM: The 2773 (DR) drum diagnostic fails the read test in Step 2. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H42 READ IN S2 + E43 DATA WORD 0063 IS 000000 SHOULD BE 046160 + H44 TRACK 0000 SECTOR 00 WORD COUNT 0064 + + Examination of the data file reveals that the failure is occurring on write. + The last word of the buffer is not being written to the drum (64 words are + to be transferred via DMA, but only 63 are output). + + CAUSE: The DMA control word is set up to do a CLC on the last word. On all + words but the last, DMA dispatches an OTA DC followed by a CLF DC. On the + last word, DMA dispatches OTA DC followed by CLC DC,C. This does a + "sim_cancel", causing the scheduled transfer of the last word to be aborted. + + RESOLUTION: Modify "hp2100_dr.c" to add "drc_run" to model the "Run + Flip-Flop" from the hardware interface, and call "sim_cancel" in "drdio" + only if "drc_run" is zero (i.e., not during a transfer). + + STATUS: Fixed in version 3.3-0. + + + + 81. PROBLEM: If a partial sector is written to the 2773 drum, the remainder of + the sector is filled with zeroes instead of replicating the last word + written. + + VERSION: 3.2-3 + + OBSERVATION: The "12606B Disc Memory Interface Kit Operating and Service + Manual" (12606-90012, Mar-1970) and "12610B Drum Memory Interface Kit + Operating and Service Manual" (12610-9001, Feb-1970) state in Section 4-91 + and 4-92, respectively, that "...The last word will be repeated on the drum + until the end of the sector is reached." The simulator replicates zeros + instead. + + CAUSE: The wrong value was used. + + RESOLUTION: Modify "drc_svc" (hp2100_dr.c) to use "drd_obuf" instead of "0" + to fill out the remainder of a sector. + + STATUS: Fixed in version 3.3-0. + + + + 82. PROBLEM: The 2773 (DR) diagnostic fails the sector address check in Step 1. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H21 SECTOR ADDRESS CHECK IN S1 + E55 SECTOR 27 MISSING IN STATUS + H44 TRACK 0000 SECTOR 00 WORD COUNT 0000 + + The number of the missing sector is random. + + The diagnostic checks to ensure that each sector in the track is detected by + checking current sector field of the status word. The loop to read status + words is 13 instructions long. The simulator computes a current sector + number from the current time; this sector changes every 10 instructions. + Therefore, in a 13-instruction loop, a sector eventually will be skipped. + + CAUSE: The timing model of the drum is incorrect. Sectors should increment + about every 256 instructions for the 2770/2771 and every 384 instructions + for the 2773/2774/2775. + + RESOLUTION: Modify "dr_set_size" (hp2100_dr.c) to set the per-word transfer + time to reflect the model in use, and modify "GET_CURSEC" to determine the + sector number properly from the current simulation time. + + STATUS: Fixed in version 3.3-0. + + + + 83. PROBLEM: The 2770 (DR) diagnostic fails the write test in step T. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H41 WRITE IN ST + E7 PARITY BIT ERROR + H44 TRACK 0000 SECTOR 00 WORD COUNT 0064 + + The diagnostic is expecting the parity error bit (bit 1) to be set at the + conclusion of writes when using the 12606 interface. This is an artifact of + the interface design. + + CAUSE: The status return from the 12606 interface is not modelled properly. + + RESOLUTION: Modify "drv_svc" (hp2100_dr.c) to return DRS_PER at the + conclusion of writes when configured as a 2770/2771 disk. + + STATUS: Fixed in version 3.3-0. + + + + 84. PROBLEM: The 2770 (DR) diagnostic fails the track origin test in step T. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + E2 CLF OR SFS FAILED-CHANNEL 27 + + The diagnostic is expecting an SFS CC instruction to skip when the track + origin is detected. Section 3-62 of the "12606B Disc Memory Interface Kit + Operating and Service Manual" (12606-90012, March 1970) states, "If the + track origin has been passed since performance of the CLF instruction, a + program skip occurs." This is not occurring. + + CAUSE: The track origin detection feature of the 12606 interface is not + implemented. + + RESOLUTION: Modify "drcio" (hp2100_dr.c) to schedule an "origin passed" + event on the data channel when CLF is executed and to check to see if that + event timer is still running when SFS is executed to determine if the track + origin has passed. + + STATUS: Fixed in version 3.3-0. + + + + 85. PROBLEM: The 2770 (DR) diagnostic fails the SCP flip-flop test in step T. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + E3 SFC FAILED WITH FLAG CLEAR-CHANNEL 27 + + The diagnostic is expecting an SFC CC instruction to skip when the SCP + (Sector Clock Phase) flip-flop is clear. Section 3-65 of the "12606B Disc + Memory Interface Kit Operating and Service Manual" (12606-90012, March 1970) + states, "If the SCP flip-flop is clear, a program skip takes place. If the + flip-flop is in the set state, no skip occurs." This is not occurring. + + Also, the SCP flip-flop state is not being reflected in status bit 15 + ("Sector Flag"). + + Finally, the 12610 command-channel interface does not drive the SKF + backplane signal, so SFC CC on that interface should never skip. + + CAUSE: The SCP test feature of the 12606 interface is not implemented. + + RESOLUTION: Modify "drcio" (hp2100_dr.c) to skip when SFC CC is executed if + the simulated head position is more than three words from the end of the + current sector and the 12606 interface is selected, not to skip when SFC CC + is executed and the 12610 interface is selected, and to reflect the SCP + flip-flop state in bit 15 of the status word for both interfaces. + + STATUS: Fixed in version 3.3-0. + + + + 86. PROBLEM: The 2770 (DR) diagnostic fails the read inhibit test in step 1. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H53 READ INHIBIT CHECK IN S1 + E35 STATUS IS 0 011 001 110 000 100 + SHOULD BE D DDD DDD D11 D00 100 + H44 TRACK 0000 SECTOR 00 WORD COUNT 0000 + + The diagnostic is expecting the read inhibit bit (bit 6) to be set for one + sector time after an OTA/OTB instruction specifies a read operation when + using the 12606 interface. Section 4-113 of the "12606B Disc Memory + Interface Kit Operating and Service Manual" (12606-90012, March 1970) + states, "...The RI [Read Inhibit] signal from the disc ensures that at least + a full sector elapses between the occurrence of sector coincidence and the + setting of the SAC FF." This is not occurring. + + CAUSE: The read-inhibit feature of the 12606 interface is not implemented. + + RESOLUTION: Modify "drcio" (hp2100_dr.c) to save the simulation time when + an OTA/OTB is executed that specifies a read operation and to compare that + to the current simulation time when LIA/LIB is executed and set the Read + Inhibit status bit if one sector time has not elapsed. + + STATUS: Fixed in version 3.3-0. + + + + 87. PROBLEM: The 2770 (DR) diagnostic fails the sector address check in step + 1. + + VERSION: 3.2-3 + + OBSERVATION: Running the diagnostic causes this failure: + + H66 BEGIN S1 + H21 SECTOR ADDRESS CHECK IN S1 + E55 SECTOR 90 MISSING IN STATUS + H44 TRACK 0000 SECTOR 00 WORD COUNT 0000 + + The diagnostic checks to ensure that each sector in the track is detected by + checking current sector field of the status word. The sector counter is one + ahead of the sector currently under the head. For the 90-sector 2770/2771 + disk, sector numbers are expected to range from 0 to 90, with the 90 state + being provided while the last sector is under the head, and the 0 state + being provided transiently between the "Track Origin" signal and the start + of the first sector. + + Note that this problem does not occur on the 32-sector 2773/2774/2775 drum, + because the sector counter is only five bits long, so instead of indicating + sector 32 while sector 31 is under the head, the counter wraps around to + zero while the last sector is under the head, and the 0 state persists a + bit longer than the others. + + CAUSE: The simulated sector counter is calculated incorrectly. + + RESOLUTION: Replace the previous "GET_CURSEC" macro with a new "dr_seccntr" + function (hp2100_dr.c) to model the sector counter accurately. + + STATUS: Fixed in version 3.3-0. + + + + 88. ENHANCEMENT: Add a TRACKPROT=n modifier to specify the number of protected + tracks and PROTECTED and UNPROTECTED modifiers to change the protection + state of the designated tracks to the 277x (DR) simulator. + + VERSION: 3.2-3 + + OBSERVATION: The 12606/12610 interfaces provide a track protection switch + on the data channel card and specification of the number of tracks to be + protected. The simulation should provide this feature. + + RESOLUTION: Modify "drc_mod" (hp2100_dr.c) to add track protection features + to the command channel (Bob says that this is a "controller" feature). + + STATUS: Fixed in version 3.3-0. + + + + 89. PROBLEM: The 2767 line printer should not print non-printing characters. + + VERSION: 3.2-3 + + OBSERVATION: The 2767 printer repertoire is the 64 character ASCII subset + from codes 32 to 95 (SPACE to "_"). Section 4-6 of the "2767A Line Printer + Operating and Service Manual" (HP 02767-90002) says, in part, "On entering + the print cycle, the characters in memory are checked for nonprintable + characters and scanned and compared against the output of the character + counter. Nonprintable characters are immediately erased from memory." This + does not occur with the LPS simulator; all characters are passed through to + the line printer image file. + + CAUSE: There is no check for non-printing characters. + + RESOLUTION: Modify "lps_svc" (hp2100_lps.c) to replace non-printing + characters with blanks (equivalent to the hardware not firing the associated + print hammer). + + STATUS: Fixed in version 3.3-0. + + + + 90. PROBLEM: The 2767 line printer should overprint the current line if sent + more than 80 characters. + + VERSION: 3.2-3 + + OBSERVATION: The 2767 printer drum is 80 columns wide. Section 4-4 of the + "2767A Line Printer Operating and Service Manual" (HP 02767-90002) says, in + part, "The 80 print positions are divided into four zones, each having 20 + consecutive print positions," and Section 4-5 says, in part, "Up to 20 + characters can be received and stored in this manner, and the print cycle is + started on receipt of either the 20th character or a format control + character." Section 4-8 says, "If the print cycle is originally initiated + on receipt of the 20th printable character, then signal ZCAV is generated + upon completion of printing. The zone control register is incremented by 1 + and DEMAND LINE enabled. The next printable character received will be + printed in the leftmost position of zone 2." The implication is that + the 81st printable character sent will be printed in zone 1, column 1. + + CAUSE: There is no check for the maximum character count per line. + + RESOLUTION: Modify "lps_svc" (hp2100_lps.c) to output a CR after every 80 + characters sent without an intervening LF or FF to simulate overprinting. + + STATUS: Fixed in version 3.3-0. + + + + 91. PROBLEM: The DO command does not report errors to the log file. + + VERSION: 3.3-0 + + OBSERVATION: Commands contained in a DO file that cause errors do not + report the errors to the console log file. They are reported to the + console. For example: + + sim> set console log=wibble.log + Logging to file "wibble.log" + sim> wibble + Unknown command + sim> do wibble.sim (contains "wibble" as a command) + Unknown command + sim> quit + Goodbye + Log file closed + + But wibble.log contains: + + Logging to file "wibble.log" + sim> wibble + Unknown command + sim> do wibble.sim + sim> quit + Goodbye + Log file closed + + Note that the second "Unknown command" message is missing from the log file. + + CAUSE: "do_cmd" reports errors "stdout" only. + + RESOLUTION: Modify "do_cmd" to report errors to "sim_log" if it is not + null. + + STATUS: Fixed in version 3.3-1. + + + + 92. ENHANCEMENT: The T register now reflects changes to the M register made + during simulation stop. + + VERSION: 3.3-0 + + OBSERVATION: On a real HP 21xx, the T (memory contents) register is updated + automatically after changing the M (memory address) register while the CPU + is halted. Under simulation during a simulation stop, this does not occur. + Providing it would very useful, though, as it would allow the ASSERT command + to test the contents of memory locations. In particular, it would allow the + diagnostics command file to test the Diagnostic Serial Number of the loaded + program to ensure that the expected value is present. + + RESOLUTION: Modify "hp2100_cpu.c" to add a "sim_vm_post" routine that + updates the T register. + + STATUS: Fixed in version 3.3-1. + + + + 93. PROBLEM: The 2767 and 2607 (LPS and LPT) simulators do not respond properly + to output operations initiated when the printers are powered off, offline, + or out of paper. + + VERSION: 3.3-0 + + OBSERVATION: On the hardware, issuing an STC to start a print operation + with the power off or with the printer offline or out of paper sets the + control and command flip-flops, sending the "device command" signal to the + printer. The operation then "hangs" until the error is corrected, at which + point the "device flag" signal is returned to the card. This causes the + flag buffer and flag flip-flops to set, completing the operation. + + On the simulator, the operation hangs forever if the paper is out, or + completes normally if the printer is powered off or offline. Both actions + are wrong. + + CAUSE: There is no provision for detecting the correction of the foregoing + situations and rescheduling the I/O event. + + RESOLUTION: Modify "lpt_svc" and "lps_svc" to stop execution if STOP_IOE is + set and the printer is powered off, offline, or out of paper. Add + "lpt_restart" and "lps_restart" routines to restart a hung I/O operation + when the printer is powered on, set online, or attached. + + Modify "hp2100_defs.h" and "sim_stop_messages" (hp2100_sys.c) to add support + for STOP_OFFLINE and STOP_PWROFF simulator stop codes. + + STATUS: Fixed in version 3.3-1. + + + + 94. PROBLEM: The column count on the 2767 printer doesn't increment when blanks + are substituted for non-printing characters. + + VERSION: 3.3-0 + + OBSERVATION: Control characters sent to the printer are replaced by blanks + before being output to the file. However, the column counter does not + increment for the replaced characters. + + CAUSE: Logic error in "lpsio". + + RESOLUTION: Modify "lpsio" (hp2100_lps.c) to count replaced non-printing + characters in the column count. + + STATUS: Fixed in version 3.3-1. + + + + 95. PROBLEM: Attempting to reboot RTE-IVB after a successful boot fails with + HLT 02. + + VERSION: 3.3-0 + + OBSERVATION: Starting SIMH and booting RTE-IVB works as expected. However, + if the simulation is halted, and an attempt is made to boot RTE a second + time, the boot fails. Examination of memory shows that the bootstrap + extension is being loaded at the wrong address. + + The 7900 boot loader outputs DMA control word 2 to select code 2, then sets + the control flip-flop on select code 2, then outputs DMA control word 3. + This sequence depends on the select code 2 control flip-flop (CTL2FF) being + clear before the loader executes. Examination shows that the BOOT command + is not clearing this flip-flop, so both outputs write to control word 3, + leaving control word 2 (the target address) set to 0. + + CAUSE: The "dma0_reset" function is not clearing CTL2FF (on the hardware, + the front panel PRESET button clears CTL2FF). + + RESOLUTION: Modify "dma0_reset" and "dma1_reset" (hp2100_cpu.c) to clear + the control flip-flops on select codes 2 and 3, respectively, as well as + clearing the control flip-flops on select codes 6 and 7. + + STATUS: Fixed in version 3.3-1. + + + + 96. PROBLEM: The control flip-flops on select codes 2 and 3 (the DMA + initialization channels) are not visible. + + VERSION: 3.3-0 + + OBSERVATION: Displaying the DMA channels shows the values of the control + (and flag, etc.) flip-flops for select codes 6 and 7. The control + flip-flops of channels 2 and 3 are not visible and may not be altered via + the simulator user interface. + + CAUSE: CTL(2) and CTL(3) have no register assignments in the DMA devices. + + RESOLUTION: Modify "dma0_dev" and "dma1_dev" (hp2100_cpu.c) to add + registers for the control flip-flops on select codes 2 and 3. + + STATUS: Fixed in version 3.3-1. + + + + 97. PROBLEM: RESET erroneously clears the DMA control words 1-3. + + VERSION: 3.3-0 + + OBSERVATION: Attempting to slow-boot RTE from a 7905 disc fails with a + "Data Overrun" error from the disc controller. Examination shows that the + disc read isn't performed because DMA Control Word 1 (select code) is zero. + + CAUSE: The RESET (preset) that is done as part of the slow-boot process is + calling "dma0_reset", which is clearing the three DMA control words. The + 12897B schematic shows that CRS does not alter the control registers. + + RESOLUTION: Modify "dma0_reset" and "dma1_reset" (hp2100_cpu.c) to clear + the control words only on power-on reset. + + STATUS: Fixed in version 3.3-1. + + + + 98. PROBLEM: DMA transfers to addresses 0/1 erroneously overwrite the A/B + register contents. + + VERSION: 3.3-0 + + OBSERVATION: Attempting to boot RTE from a 7905 disc fails with a "Indirect + address loop" simulation halt. Examination shows that the B register, which + is being used as an address pointer, is corrupted by a DMA transfer from the + disc to address 00001. The disc read succeeds but overwrites the A and B + register contents in the process. + + Section I, Paragraph 4-17, "Store Field", of the "HP 1000 M/E/F-Series + Computers Engineering and Reference Documentation" (HP 92851-90001) says: + + "The A and B addressable flip-slops (ABFF) [38A] can be clocked at the + end of every microcycle. Addresses 0 and 1 are detected on the M-bus and + the flip-flops are set accordingly. When DCPC uses the M-bus the ABFFST + signal is suppressed." + + CAUSE: The "ReadIO" and "WriteIO" routines, used by DMA, are not separating + accesses to locations 0/1 from accesses to A/B. + + RESOLUTION: Modify hp2100_cpu.c to separate the A/B registers from memory + locations 0/1 and to map them equivalently, except during DMA accesses. + + STATUS: Fixed in version 3.3-1. + + + + 99. ENHANCEMENT: Add SET CPU modifiers for 21MX-M and 21MX-E variants. + + VERSION: 3.3-0 + + OBSERVATION: The RTE-6/VM startup routine ($STRT) determines whether it is + executing on a M-series or E-series by executing the TIMER instruction and + seeing if the B register is incremented. If it is, then OS microcode + instructions are used, but these are not supported by SIMH, and an + "Unimplemented instruction" simulation stop occurs. RTE-6/VM will boot if + the CPU is detected as an M-series. + + RESOLUTION: Modify hp2100_cpu.c to add SET CPU 21MX-M and SET CPU 21MX-E + modifiers, and enable the TIMER instruction only if the E-series variant is + selected. + + STATUS: Fixed in version 3.3-1. + + + +100. PROBLEM: The JPY instruction does not work. + + VERSION: 3.3-0 + + OBSERVATION: JPY is supposed to add the contents of P+1 to the Y register + and use the result as the jump target address. Actually, JPY is adding the + contents of P+2. + + CAUSE: The "e_inst" array that indicates how to process operands for the + extended instructions has the wrong value for the JPY entry. + + RESOLUTION: Modify "e_inst" (hp2100_cpu.c) to replace the erroneous "X_MR" + value with the correct "X_NO" value. + + STATUS: Fixed in version 3.3-1. + + + +101. PROBLEM: The JRS instruction does not perform a memory protect check on + the jump target. + + VERSION: 3.3-1 + + OBSERVATION: A JRS to a location below the MP fence is allowed, presuming + that DMS conditions are satisfied. + + CAUSE: The JRS simulation routine is missing a memory protect check on the + target address. + + RESOLUTION: Add a call to "mp_dms_jmp" in the JRS simulator routine + (hp2100_cpu1.c) to validate the target address. + + STATUS: Fixed in version 3.3-2. + + + +102. PROBLEM: The EXECUTE instruction was never implemented on the 21MX-E. + + VERSION: 3.3-1 + + OBSERVATION: Section 5.7, "Special Instructions," of the "HP 1000 + M/E/F-Series Computers Engineering and Reference Documentation" (HP + 92851-90001) documents three "unsupported" instructions added to the 21MX-E + series CPU: DIAG, TIMER, and EXECUTE. Examination of the microcode reveals + that the EXECUTE instruction (100120) was never implemented; the microcode + executes a NOP for this instruction code. + + CAUSE: Improper documentation. + + RESOLUTION: Alter "cpu_eau" (hp2100_cpu1.c) to handle EXECUTE as an + undefined instruction. + + STATUS: Fixed in version 3.3-2. + + + +103. PROBLEM: Rounding negative unpacked floating-point numbers may yield + unnormalized results. + + VERSION: 3.3-1 + + OBSERVATION: The floating-point pack routine first rounds by adding +/- + 1/2 LSB to the mantissa. If rounding causes a carry, the resulting value + is unnormalized. An overflow check is made on positive numbers (i.e., + "011..." becoming "100..."), but no check for carry into the MSB-1 is made + for negative numbers ("101..." becoming "110..."). + + CAUSE: The case was omitted. + + RESOLUTION: Modify "StoreFP" (hp2100_fp.c) to add a normalization check + for negative numbers. + + STATUS: Fixed in version 3.3-2. + + + +104. ENHANCEMENT: Add a command to abort command file execution if a specified + simulator condition is not met. + + VERSION: 3.3-1 + + OBSERVATION: Command files need a means of reacting to unexpected program + behavior. Currently, if a program deviates from expected behavior, e.g., + if a diagnostic fails, the command file will become unsynchronized with the + program, leading to nonsensical operation. + + To provide an escape mechanism for this situation, a command that tests + assertions of the simulator state and aborts a running command file if the + assertion fails is needed. The syntax is: + + ASSERT {} {} + + If is not specified, CPU is assumed. is a register (scalar or + subscripted) belonging to the indicated device. The and + optional are the same as those provided by the "examine" and + "deposit" commands. The s are expressed in the radix specified for + , not in the radix for the device. + + If the and are specified, the target register value is + first altered as indicated. The result is then compared to the via + the . If the result is false, an "Assertion failed" + message is printed, and any running command file is aborted. Otherwise, + the command has no effect. + + RESOLUTION: Modify "scp.c" to add "assert_cmd" and associated command + table entries. + + STATUS: Fixed in version 3.3-2. + + + +105. ENHANCEMENT: The option flags for the various CPU models and options were + reorganized. + + VERSION: 3.3-2 + + OBSERVATION: To simplify handling of optional instruction sets, the flags + describing the configuration of the simulated system are reorganized into + CPU type, model, and options. This allows simple testing of a class of + machines (e.g., all 21MX models) or installed options (e.g., IOP microcode + on any CPU), without having to test each possible machine/option + combination. + + RESOLUTION: Modify option flags in "hp2100_cpu.c" and "hp2100_cpu.h" to + reflect logical hardware grouping and change "cpu_set_opt" accordingly. + + STATUS: Fixed in version 3.4-0. + + + +106. ENHANCEMENT: Modularize the handling of optional instruction sets to allow + for future microcode option simulations. + + VERSION: 3.3-2 + + OBSERVATION: The current CPU simulation decodes all UIG instructions + inline, so that microcode options that share instruction codes (e.g., the + 2100 IOP and the 2100 FP/FFP) must have tests for CPU type at each code + point. Also, tabular instruction operand processing is complicated when + instructions with differing requirements share code points. + + RESOLUTION: Split optional CPU instruction (EAU/UIG) processing into its + own source file (hp2100_cpu1.c), represent each option as a function that + determines CPU applicability and decodes its own instructions, and + restructure operand processing so that it is per-option-module, rather than + global for all options. + + STATUS: Fixed in version 3.4-0. + + + +107. ENHANCEMENT: Add the Fast FORTRAN Processor (FFP) microcode option. + + VERSION: 3.3-2 + + OBSERVATION: The Pascal/1000 compiler will not load in an RTE system with + a three-page driver partition if the FFP option is not present (required to + reduce code size to fit the logical address space). Also, RTE systems + generated with the FFP option will not run unless the option is present. + + RESOLUTION: Add a simulation of the FFP to "hp2100_cpu1.c", add a new + extended-precision floating point module "hp2100_fp1.c", and add FFP + helpers to "hp2100_fp.c" for single-precision operations. + + STATUS: Fixed in version 3.4-0. + + + +108. ENHANCEMENT: Separate the online/offline and attach/detach functions for + the magnetic tape and disc drive simulations. + + VERSION: 3.3-2 + + OBSERVATION: Currently, devices that have loadable media and an offline + mode simulate both via attach and detach, i.e., attached implies online, + and detached implies offline. It is desirable to separate the two, so that + performing a magnetic tape "rewind/offline" command or disc "head unload" + action does not detach the image file. + + The RTE tape backup programs set the tape units offline when they are + exited, and it is awkward to have to respecify the image filename in an + attach command in order to put the unit back online for a succeeding + operation (the real tape drive merely requires pressing the "ONLINE" + button). Also, being able to "down" untargeted disc drives when performing + certain read/write operations, e.g., new system installation, is a useful + safety measure (simply toggling the "UNLOAD" switch accomplishes this on a + real disc drive). + + RESOLUTION: Modify "hp2100_ms.c" to add SET OFFLINE/ONLINE and + "hp2100_dp.c", "hp2100_dq.c", and "hp2100_ds.c" to add SET UNLOADED/LOADED + commands, as well as to decouple setting a device offline from detaching + the associated image file. + + STATUS: Fixed in version 3.4-0. + + + +109. ENHANCEMENT: Allow the DO command to nest to some finite level. + + VERSION: 3.3-2 + + OBSERVATION: Allowing a limited depth of nested DO invocations is useful + for modularizing simulator command files. The current prohibition is not + necessary, as "do_cmd" is reentrant. + + RESOLUTION: Modify "do_cmd" (scp.c) to allow DO command nesting, provide a + recursion counter to disallow infinite nesting, and alter the text of the + SCPE_NEST error to reflect allowed nesting. + + STATUS: Fixed in version 3.4-0. + + + +110. PROBLEM: SET DEBUG=n1,n2,... doesn't work. + + VERSION: 3.3-2 + + OBSERVATION: For devices with multiple debug flags, trying to set more + than one with the above command fails with "Non-existent parameter." + Setting the flags one at a time with separate commands works as expected. + + CAUSE: The command parser breaks SET commands at commas, so "n2" is + interpreted as the next top-level SET command, rather than as another debug + flag. + + RESOLUTION: Alter the debug flag separator from "," to ";". + + STATUS: Fixed in version 3.4-0. + + + +111. ENHANCEMENT: Allow SET DEBUG to mean "set all debug flags." + + VERSION: 3.3-2 + + OBSERVATION: Currently, if a device has multiple debug flags, SET + DEBUG is rejected. To set all flags, they must be specified individually. + + RESOLUTION: Alter "set_dev_debug" (scp.c) to set all debug flags if none + are specified in the SET DEBUG command. + + STATUS: Fixed in version 3.4-0. + + + +112. ENHANCEMENT: Improve reporting of conflicting I/O assignments. + + VERSION: 3.5-1 + + OBSERVATION: The current "dev_conflict" (hp2100_cpu.c) routine has + three behaviors that might be improved: + + 1. It reports only the first device conflict encountered. + 2. It reports the name and select code of only one of the two + conflicting devices. + 3. It reports the select code in decimal. + + Here is a console log demonstrating these behaviors: + + sim> set ds dev=12 + sim> set muxm dev=12 + sim> set lpt dev=13 + sim> run + DS device number conflict, devno = 10 + + Simulation stopped, P: 00000 (NOP) + + We altered the default configuration to place PTP, DS, and MUXM at + select code 12 (octal), and CLK and LPT at select code 13 (octal). + Note that the above reported select code (10) is decimal. + + RESOLUTION: Modify "dev_conflict" behavior as follows: + + 1. Report all device conflicts in ascending select code order. + 2. Report device names for all conflicting devices. + 3. Report conflicting select codes in octal. + + Here is the same console log demonstrating the enhanced behaviors: + + sim> set ds dev=12 + sim> set muxm dev=12 + sim> set lpt dev=13 + sim> run + Select code 12 conflict: PTP and DS and MUXM + Select code 13 conflict: CLK and LPT + + Simulation stopped, P: 00000 (NOP) + + STATUS: Fixed in version 3.5-2. + + + +113. PROBLEM: "SET CONSOLE DEBUG" with no parameter crashes the simulator. + + VERSION: 3.6-0 + + OBSERVATION: Entering "SET CONSOLE DEBUG" without the "=" + causes the simulator to crash with an access error. + + CAUSE: Null pointer dereferenced in "sim_set_debon". + + RESOLUTION: Return SCPE_2FARG if "cptr" is null (no parameter supplied) or + points to a null character (empty parameter supplied). + + STATUS: Fixed in version 3.6-1. + + + +114. PROBLEM: Nested command files do not abort on assertion failure. + + VERSION: 3.6-0 + + OBSERVATION: While a failed assertion will abort a running command file, + it will not abort if the assertion is in a nested command file invocation. + + CAUSE: "do_cmd" is always passing back SCPE_OK, regardless of whether an + invoked command returns an error status. This is apparently an attempt to + avoid duplicate error messages if the last command in a command file fails + (the error is printed within "do_cmd" and then again in the main command + loop). + + RESOLUTION: Modify "do_cmd" (scp.c) to return all command error codes and + to return SCPE_OK on command file EOF. + + STATUS: Fixed in version 3.7-0. + + + +115. ENHANCEMENT: Provide an -E switch to DO to abort a command file on any + error. + + VERSION: 3.6-0 + + OBSERVATION: Current DO processing ignores command errors. That is, if a + command returns an error, the error message is printed, but processing + continues with the next command in the file. This is inherently risky, as + command files must be written with the expectation that every command will + succeed (because there is no error trapping or conditional execution). + + RESOLUTION: Add a new -E switch to cause command file execution to be + aborted at the first error encountered. Note that SCPE_STEP is not + considered an error, and simulator-specific errors, e.g., "infinite + indirect loop," does not cause an error abort (simulator limitation). + + STATUS: Fixed in version 3.7-0. + + + +116. ENHANCEMENT: Two gcc compiler warnings are corrected. + + VERSION: 3.6-0 + + OBSERVATION: Running gcc in strict ISO C99 standard mode (-std=c99 -Wall + -pedantic) reveals two warnings: + + HP2100/hp2100_mux.c:160: warning: missing braces around initializer + HP2100/hp2100_mux.c:160: warning: (near initialization for `mux_ldsc[0]') + + and: + + sim_ether.c: In function `eth_mac_scan': + sim_ether.c:271: warning: short unsigned int format, short int arg (arg 3) + + CAUSE: The first warning is due to an incompletely specified declaration. + The variable is an array of structures, so the (partial) initializer should + be "{ { 0 } }" but is actually "{ 0 }". + + The second warning is due to a mismatch between a "sscanf" format and the + corresponding parameter type. The format, "%hx", requires a short unsigned + int parameter, but the parameter is declared as short int. + + RESOLUTION: The code causing the warnings is corrected. + + STATUS: Fixed in version 3.7-0. + + + +117. PROBLEM: The 7970 magnetic tape simulator defaults tape capacity to a + 300-foot reel instead of to an unlimited-size reel. + + VERSION: 3.6-0 + + OBSERVATION: In the absence of an explicit size command, the 7970 tape + drive reel size is intended to default to an unlimited size, wherein EOT + never occurs. In fact, EOT occurs after 300 feet. + + CAUSE: The logic was inadvertently broken on February 16, 2006 when the + "revision for new EOT test" was made. + + RESOLUTION: Remove the "capac" assignments in "mscio" and "msc_svc" and + add an assignment to "ms_set_reelsize" (hp2100_ms.c), allowing the default + capacity to remain as 0 (a zero capacity causes "sim_tape_eot" to return + FALSE). + + STATUS: Fixed in version 3.6-1. + + + +118. ENHANCEMENT: Add CAPACITY to 7970 simulator as an alternate to REEL. + + VERSION: 3.6-0 + + OBSERVATION: Other magnetic tape simulators allow setting a CAPACITY to + indicate the number of megabytes to read or write before returning EOT. + The 7970 simulator REEL size predated CAPACITY, but it's desirable for + commonality if both were allowed. + + RESOLUTION: Alter hp2100_ms.c to support SET CAPACITY in addition to + SET REEL, and enhance SHOW to display the capacity in MB or feet as + appropriate. + + STATUS: Fixed in version 3.6-1. + + + +119. PROBLEM: The RTE off-line magnetic tape restore program (DSKUP) hangs on + the first write to the 79xx/13037 disc. + + VERSION: 3.6-1 + + OBSERVATION: The RTE offline restore program hangs when it tries to write + to the 79xx disc. The program is looping in a routine that obtains drive + status by sending the REQUEST STATUS command to the drive. + + CAUSE: The program expects that the REQUEST STATUS operation will clear + the status. If this operation returns DRIVE ATTENTION, the program loops + until it does not. However, the simulator does not the clear status value, + so after the seek completes, DRIVE ATTENTION is returned forever. + + Page 10-10 of the 13037 Disc Controller Technical Information Package (HP + 13037-90902, August 1980) contains this description of the REQUEST STATUS + command: + + "After receipt of this command, the controller returns two status words + to the interface. [...] The controller then clears Status-1 and waits + for a command from the same interface or a timeout to occur." + + The controller firmware routine STATS handles the status request. It calls + routine CLRST. The comment for the CLRST routine is, "Subroutine CLRST + clears status for all commands but status request," but examination of the + routine shows that it is unconditional. + + RESOLUTION: Modify the "DSC_RSTA" case in "ds_docmd" (hp2100_ds.c) to + clear status-1 after returning it. + + STATUS: Fixed in version 3.7-0. + + + +120. ENHANCEMENT: Separate TTY mode settings so that keyboard and display may + be set independently. + + VERSION: 3.6-1 + + OBSERVATION: HP terminals had a CAPS LOCK setting that allowed upper-case + input with mixed-case output. The current TTY simulator allows several I/O + options, but the keyboard and display settings are locked together. + + RESOLUTION: Modified "tty_set_opt" (hp2100_stddev.c) to allow keyboard + (TTY0) and display (TTY1) to be set independently. + + STATUS: Fixed in version 3.7-0. + + + +121. ENHANCEMENT: Add the HP 93585A double integer instruction set firmware + option. + + VERSION: 3.6-1 + + OBSERVATION: Later versions of RTE-6/VM were not supported on the 21MX + M-Series due to logical address space limitations. The RTE-6 OS and VMA + firmware options were not available for the M-Series, and some vital system + programs exceeded the available address space and failed to load when the + software equivalents were used. To run these programs, either the OS/VMA + or double integer firmware support must be added to reduce the address + space required. + + RESOLUTION: Add an implementation of the double integer instruction set to + "hp2100_cpu1.c" and add "DBI/NODBI" options to "cpu_mod[]" (hp2100_cpu.c) + to enable and disable the instructions. Note that the 93585A product + worked only on the E-Series, but it is available under simulation on the + M-Series as well. + + STATUS: Fixed in version 3.7-0. + + + +122. ENHANCEMENT: Add "1000-M" and "1000-E" CPU options as synonyms for + "21MX-M" and "21MX-E". + + VERSION: 3.6-1 + + OBSERVATION: The 21MX computer series was renamed the 1000 series with the + introduction of the F-Series in 1978. The 21MX/21MX-M became the 1000 + M-Series, and the 21XE/21MX-E became the 1000 E-Series. There is some + internal HP documentation that refers to the F-Series as the 21MX-F, but + the machine was introduced as the 1000 F-Series, and the other machines + were renamed at the same time. + + RESOLUTION: Modify "cpu_mod[]" (hp2100_cpu.c) to add "1000-M" and "1000-E" + options. + + STATUS: Fixed in version 3.7-0. + + + +123. ENHANCEMENT: The DMA device is automatically assigned the logical name + "DCPC" when SET CPU 21MX is done. + + VERSION: 3.6-1 + + OBSERVATION: The term "DMA" is used with the 2116 and 2100 machines. For + the 21MX, the equivalent card is termed the "Dual Channel Port Controller." + "DCPC" is used exclusively in the HP 21MX literature, and users are used to + working with the "DCPC" name. + + RESOLUTION: Modify "cpu_set_opt" (hp2100_cpu.c) to assign and deassign + logical names in response to SET CPU 2116/2100/21MX commands, and add + "assign_device" and "deassign_device" (scp.h) to the list of global + routines. + + Note that this enhancement does not proscribe users from using the DMA + device name with 21MX simulations. + + STATUS: Fixed in version 3.7-0. + + + +124. PROBLEM: Running FC under RTE aborts the simulation with an "Invalid + magtape record length" error. + + VERSION: 3.6-1 + + OBSERVATION: Attempting to run the RTE "FC" ("File Copy") tape archive + program to generate a tape image fails. The Read command is failing with + tape library error 4, "Invalid record length." + + Enabling the debug mode of the 7970 tape drive simulator reveals that FC is + attempting to leave space at the beginning of the tape for the archive + directory by issuing a series of GAP commands. After the files are stored, + the tape is rewound, and the directory is written, intending to overwrite + the erased area. + + CAUSE: FC writes items to the tape in this order: header, marker, comment, + directory, data file(s), and two EOFs. FC is issuing GAP commands to leave + space at the start of the tape for the tape header, which must be written + after the tape is complete, because the header indicates the number of data + files that fit on the tape. + + The SIMH mag tape library does not implement the "erase gap" feature, and + the 7970 simulator treats GAP as a NOP, so no space is reserved at the + start of the tape image. When FC rewinds and writes the directory, it + overwrites the existing records, resulting in a corrupt tape image. + + RESOLUTION: Implement an "erase gap" feature in the SIMH tape library by + defining GAP metadata markers, adding a "sim_tape_wrgap" command and + enhancing the "sim_tape_rdlntf" and "sim_tape_rdlntr" internal functions to + skip over GAP metadata markers (sim_tape.c). Alter the 7970 simulator + (hp2100_ms.c) to use it. Also, update the "mtdump" utility to report erase + gaps in tape images. + + Note: All HP 7970 mag tape drivers (SIO, BCS, DOS, RTE) employ the GFM + (erase gap and write file mark) command to write an EOF to tape. Also, the + tape diagnostic tests that an initial gap precedes the first data record or + EOF written at BOT (a function of the interface card). Consequently, + generated tape images contain substantial amounts of GAP metadata. In + almost all cases, they are unnecessary. Therefore, these gaps are written + only if the REALTIME option is selected. Note that this does not affect + the GAP command itself, which always writes gap metadata to tape images. + + STATUS: Fixed in version 3.7-0. + + + +125. ENHANCEMENT: Improve error reporting from the 7970 tape simulator. + + VERSION: 3.6-1 + + OBSERVATION: The new "erase gap" support is only implemented for + SIMH-format tape images. Attempting to write an erase gap with other + formats selected correctly returns MTSE_FMT from the library. However, the + 7970 simulator maps that error (and the MTSE_UNATT error) to SCPE_IERR. + The resulting "Internal error" message does not help the user identify the + source of the problem. + + RESOLUTION: Modify "ms_map_err" (hp2100_ms.c) to return SCPE_FMT and + SCPE_UNATT for the tape library errors MTSE_FMT and MTSE_UNATT, + respectively. + + STATUS: Fixed in version 3.7-0. + + + +126. PROBLEM: "calc_dma" and "calc_int" are being called needlessly for most + UIG 0 and UIG 1 instructions. + + VERSION: 3.6-1 + + OBSERVATION: The "calc_dma" and "calc_int" routines must be called after + any routine that might change the I/O priority chain or set SRQ. This + would be after any I/O Group instruction or card I/O action (i.e., card + service routine called). + + In "hp2100_cpu.c", the dispatch points for "cpu_uig_0" and "cpu_uig_1" call + these routines unconditionally, but they're only needed if an IOP "PRFIO" + or "PRFEI" instruction is executed (these execute standard I/O instructions + as part of their actions). + + CAUSE: The current code was a temporary expediency when the IOP + instructions were moved into a separate source module. + + RESOLUTION: Define a new "NOTE_IOG" status return (hp2100_defs.h) to + request recalculation of I/O interrupts after instruction execution + completes, and rename "STOP_INDINT" to "NOTE_INDINT" to reflect that it + notifies the main instruction execution loop of an interruptibility + condition, rather than stopping the simulation. Alter "iogrp" and + "resolve" (hp2100_cpu.c) respectively, to use these notification codes. + + STATUS: Fixed in version 3.7-0. + + + +127. ENHANCEMENT: Use the tape simulator library routine "sim_tape_bot" to + determine BOT status dynamically for the 7970 simulator. + + VERSION: 3.6-1. + + OBSERVATION: The 7970 simulator maintains its own BOT status by tracking + rewinds and motion commands. It would be simpler to use the routine + provided by the tape simulation library for this, rather than tracking each + tape movement. + + Note that prior to the addition of erase gap support, this would not work. + The diagnostic moved the tape off of BOT by using the GAP command, but this + was a NOP for the tape simulation library, and the tape remained at BOT, + leading to diagnostic failures. + + RESOLUTION: Modify "hp2100_ms.c" to use "sim_tape_bot" instead of tracking + BOT internally. + + STATUS: Fixed in version 3.7-0. + + + +128. PROBLEM: Sending a "controller clear" command to the 7970 magnetic tape + simulator may cause an unintended write. + + VERSION: 3.6-1 + + OBSERVATION: Clearing a write-in-progress properly writes any accumulated + partial record. Sending a second clear may write the record again. + + CAUSE: Receipt of a CLR command initiates a check for a write-in-progress + among active units. If the data buffer pointer is non-zero, then partial + data has been accumulated, and this is written to the tape image. The data + buffer pointer is normally zeroed when a write record command is received + and the command time delay has transpired. + + If a second write command is sent, and another CLR is done before the + command time has transpired (and therefore before any data has been + received from the CPU), then the previous partial record will be written + again. This happens because the buffer pointer was not cleared and so + implies the presence of another partial buffer of data. + + RESOLUTION: Modify "mscio" (hp2100_ms.c) to clear the buffer pointer + after a partial record is written. + + STATUS: Fixed in version 3.7-0. + + + +129. ENHANCEMENT: Improve debugging information from the 7970 simulator. + + VERSION: 3.6-1 + + OBSERVATION: Debugging problems such as the "controller clear" bug would + be easier if the debug logging decoded the tape commands and included all + controller actions. Currently, tape commands are reported in octal, and + only some actions are reported. + + RESOLUTION: Modify "hp2100_ms.c" to add additional debug logging and debug + flags to select subsets of the available information. + + STATUS: Fixed in version 3.7-0. + + + +130. ENHANCEMENT: Partition the various microcode options in "hp2100_cpu1.c" + into separate modules for easier maintenance. + + VERSION: 3.6-1 + + OBSERVATION: With the addition of the double integer instructions and + potential addition of the RTE-6/VM OS and VMA instructions, the microcode + option source module, "hp2100_cpu1.c", is becoming unwieldy. It is + currently the largest HP source module -- about 50% larger than the rest of + the CPU implementation. + + RESOLUTION: Move the microcode options into separate source files, grouped + by function, and restrict "hp2100_cpu1.c" to contain dispatching and common + routines. + + STATUS: Fixed in version 3.7-0. + + + +131. PROBLEM: Errors in nested command files give no indication where the error + occurred. + + VERSION: 3.6-1 + + OBSERVATION: Unless the -V switch is specified, errors in command files + report the error message but not the offending command. With the advent of + nested command files, the problem becomes more acute, as there is no + indication in which of perhaps several nested command files the offending + command is located, nor even which command is causing the error. And + because -V is not transitive, each DO command appearing in each command + file must be edited to add the -V switch if the error is to be located. + + CAUSE: The implication of errors in nested command files was overlooked + when nesting was enabled. + + RESOLUTION: Modify "do_cmd" (scp.c) to echo commands causing errors, + regardless of the -V switch, unless -Q (quiet) is supplied when starting + SIMH. Also, report the name of the file containing an offending command. + + Note: because commands returning error status are now displayed, error + message processing for the ASSERT command is simplified. In particular, + the extra code that merged the assertion into the error message is no + longer required. + + STATUS: Fixed in version 3.7-0. + + + +132. PROBLEM: The simulator stops with an "Indirect address loop" error when + running the HP 1000-F FFP diagnostic .GOTO test. + + VERSION: 3.6-1 + + OBSERVATION: According to the HP 2100 documentation, the simulator will + stop if "more than INDMAX indirect references are detected during memory + reference address decoding." INDMAX defaults to 16. However, attempting + a reference with exactly 16 indirects stops the simulator with an "Indirect + address loop" error. + + CAUSE: The indirect address resolution loop in the "resolve" function + executes a maximum of INDMAX times. However, the decision to report an + error considers only whether the loop counter reached INDMAX and not + whether the indirect chain was resolved. Therefore, resolution on the last + available pass through the loop is still reported as an error. + + RESOLUTION: Modify "resolve" (hp2100_cpu.c) to report an error if the + indirect chain is not resolved after exiting the loop. + + STATUS: Fixed in version 3.7-0. + + + +133. ENHANCEMENT: Add support for the HP 1000 F-Series CPU model. + + VERSION: 3.6-1 + + OBSERVATION: The Fast FORTRAN Processor option adds simulation support for + three-word floating-point operations. Generalizing these to support two, + three, and four-word operations would allow simulation of the F-Series + floating-point processor. + + RESOLUTION: Rework the FFP arithmetic simulations (hp2100_cpu3.c) into + general operations on multiple-precision operands. Add support for the + F-Series FPP instructions. Add support for the F-Series Scientific + Instruction Set (SIS) firmware. Add "1000-F" as a CPU option + (hp2100_cpu.c). + + Note: rather than have two floating-point simulations (hp2100_fp.c and + hp2100_fp1.c) that provide the two-word single-precision floating-point + instructions, they are alternately conditionally compiled, depending on + whether 64-bit integers are supported. As the FPP depends on this support, + compiling with it enables the FPP and therefore the F-Series option, and + "hp2100_fp1.c" handles the single-precision instructions for the other CPU + models. If 64-bit support is not available, then "hp2100_fp.c" handles the + single-precision instructions, and the F-Series is not available. + + STATUS: Fixed in version 3.7-0. + + + +134. ENHANCEMENT: Add support for the 2114 and 2115 CPU models. + + VERSION: 3.6-1 + + OBSERVATION: The 2114 and 2115 are reduced-feature versions of the 2116 + computer. One could restrict the 2116 environment to give an approximation + of the 2114 and 2115. However, these units used a unique DMA card that + behaved somewhat differently than that used in the 2100 and 1000 (the 12607 + card for the 2114 supported only one DMA channel, for example). So it + would be desirable to support the 2114 and 2115 directly and therefore more + faithfully. + + RESOLUTION: Add "2114" and "2115" CPU model options (hp2100_cpu.c). + + STATUS: Fixed in version 3.7-0. + + + +135. ENHANCEMENT: Add support for 12K and 24K memory sizes. + + VERSION: 3.6-1 + + OBSERVATION: The 2114 and 2115 CPUs supported up to 16K of memory in 4K + increments. For accurate simulation, finer granularity than the current + 4K/8K/16K/32K choices is needed. + + RESOLUTION: Alter the table of memory size (hp2100_cpu.c) to add 12K and + 24K options. + + STATUS: Fixed in version 3.7-0. + + + +136. PROBLEM: The DMS self-test instruction (10x701) should be a NOP on 1000-M + machines. + + VERSION: 3.6-1 + + OBSERVATION: The DMS self-test instruction should complement the A or B + register only on the 1000-E and F. On the M, it should be a NOP. In fact, + it complements on the M as well. + + CAUSE: Oversight. + + RESOLUTION: Modify "cpu_dms" (hp2100_cpu2.c) to execute 10x701 as NOP on + M-Series machines. + + STATUS: Fixed in version 3.7-0. + + + +137. ENHANCEMENT: Add support for 21xx loader enable and disable. + + VERSION: 3.6-1 + + OBSERVATION: The 21xx CPUs are core-based machines. Binary loaders are + kept in the top 64 memory locations and are protected from reading and + writing by front panel LOADER ENABLE switches. When the switch is off, + main memory effectively ends 64 locations earlier, i.e., the loader area is + treated as non-existent. Some 21xx diagnostics test for this feature and + will not proceed if the loader area is unprotected. + + RESOLUTION: Modify hp2100_cpu.c to add loader protection for 21xx models. + + STATUS: Fixed in version 3.7-0. + + + +138. PROBLEM: The General Purpose Register Diagnostic fails when run on a 2100. + + VERSION: 3.6-1 + + OBSERVATION: The GP register diagnostic and other diagnostics that test + the I/O system fail when run on 21xx CPUs. The failure is in the Basic I/O + test, Test 00. The failure is, "E015 INT RTN ADDR ERROR." + + CAUSE: The 21xx and 1000 CPUs behave differently when holding off + interrupt requests after executing certain instructions. At instruction + fetch time, a pending interrupt request may be deferred if the previous + instruction was a JMP indirect, JSB indirect, STC, CLC, STF, CLF, SFS (1000 + only), or SFC (1000 only), or was executing from an interrupt trap cell. + If the CPU is a 1000, then the request is always deferred until after the + current instruction completes. If the CPU is a 21xx, then the request is + deferred unless the current instruction is an MRG instruction other than + JMP or JMP,I or JSB,I. Note that for the 21xx, SFS and SFC are not + included in the deferral criteria. + + RESOLUTION: Modify "sim_instr" (hp2100_cpu.c) to clear "ion_defer" if + executing on a 21xx-series CPU and the current instruction is an MRG + instruction other than JMP or JMP,I or JSB,I. + + STATUS: Fixed in version 3.7-0. + + + +139. PROBLEM: The 2100-specific Memory Protect Diagnostic fails when testing + indirect holdoffs. + + VERSION: 3.6-1 + + OBSERVATION: Running the 2100-specific MP diagnostic fails, even though + the combined 2100/21MX MP diagnostic passes. The failure is: + + E26. RETURN ADDRESS INCORRECT FOR CHAINED JMP,I INTERRUPTS + + CAUSE: The memory protect feature adds an indirect counter that allows a + pending interrupt to be serviced if more than three levels of indirection + are encountered. Currently, the "resolve" routine handles this by + returning a status code that aborts the current instruction if an interrupt + is pending and the third indirect level is encountered. However, the + actual action of the hardware is to clear any interrupt deferral at the + third level and to abort the instruction at the fourth. The diagnostic + tests that a two-level JMP,I jumps and defers interrupts, a three-level + JMP,I jumps and then allows interrupts, and a four-level JMP,I aborts and + then allows interrupts. + + RESOLUTION: Modify "resolve" (hp2100_cpu.c) to obey the foregoing rules, + and modify "sim_instr" to set "ion_defer" before calling "resolve" for + JMP,I and JSB,I instructions. + + STATUS: Fixed in version 3.7-0. + + + +140. PROBLEM: The 2114/2115/2116/2100 DMA diagnostic fails with an unexpected + trap cell halt. + + VERSION: 3.6-1 + + OBSERVATION: Running the 21xx-specific DMA diagnostic fails, even though + the combined 2100/21MX DMA diagnostic passes. The failure manifests itself + as an unexpected trap cell halt, 106002. + + CAUSE: The diagnostic issues STF 6 and STC 6 instructions to cause a DMA + interrupt without a transfer to test the priority chain. This sets the + transfer (command) flip-flop on SC 6. In the next test, it does a CLC 0 + and then sets up a one-word DMA transfer from the test device. Then it + asserts device SRQ by doing CLC SC and STF SC, and finally it starts the + device and DMA with STC SC and STC 6,C. + + However, with command set, asserting SRQ starts the transfer immediately, + even though the control flip-flop is clear. So the word count has rolled + over to zero and the transfer terminated by the time the STC 6,C is done to + "start" the transfer. At that point, a second transfer is started, and the + word count of zero implies a transfer of 64K words, which begins scribbling + over memory. As the value 140000 had been written to the card before the + transfer, and as the card is in a loopback mode, 140000 is read from the + card on each transfer, and so this value overwrites memory. Eventually, + the diagnostic attempts a jump indirect through an overwritten location. + The target value 140000 is interpreted as a DEF 40000,I, and because + location 40000 contains zero, control transfers to location 0, leading to + execution of the trap cell halt 106002 in location 2. + + The problem is that the simulator incorrectly implements CRS ("Control + Reset," the backplane signal that is generated by the CLC 0 instruction) by + sending a CLC SC to each I/O card. For many cards, CLC 0 (CRS) and CLC SC + (CLC) invoke the same action. They do not on the DMA card, which clears + the control flip-flop for CLC, but clears the control and command + flip-flops for CRS. Clearing the command flip-flop prevents the DMA + transfer from starting until the STC 6,C instruction in the diagnostic is + executed. + + RESOLUTION: Modify "cpuio" (hp2100_cpu.c) to send a new signal, "ioCRS", + in response to CLC 0 and modify the I/O handlers of all devices to handle + "ioCRS" as "ioCTL" temporarily until each card response can be verified + from the schematics. + + STATUS: Fixed in version 3.7-0. + + + +141. PROBLEM: The 12566B diagnostic interface card (LPS) does not clear the + command flip-flop when CLC is done. + + VERSION: 3.6-1 + + OBSERVATION: In SET LPS DIAG mode, a 12566B microcircuit interface card + with a loopback connector is simulated. This is provided for the use of + certain diagnostics that test the I/O system. Attempting to use this + simulation with the 2114/2115/2116/2100 DMA diagnostic fails with: + + E136. D1-I/O FLG SET + + even though the combined 2100/21MX DMA diagnostic passes. + + CAUSE: The diagnostic requires that jumper W9 be set to the "A" position. + This enables clearing of the device command flip-flop when the CLC + instruction is executed. Clearing CMD is intended to stop any I/O in + progress. + + The diagnostic sets up a one-word output with STC and CLC specified in the + control word. At the end of the transfer, "dma_cycle" (hp2100_cpu.c) + correctly sends LPS a STC,C followed by a CLC,C. The STC,C starts a + transfer and therefore schedules an I/O event for completion in one + instruction. The CLC,C clears the control flip-flop and the device flag, + but because "sim_cancel" is not called, the I/O event remains. When it + fires, the device flag is set. The diagnostic is expecting the flag to be + clear. + + The 2100/21MX diagnostic tests for flag clear by using a control word that + has neither STC nor CLC present. This generates a CLF to the interface, + which correctly clears the device flag (without starting another + operation). + + RESOLUTION: Modify "lpsio" (hp2100_lps.c) diagnostic mode to latch the + input data on STC and schedule the command clear and flag set in two + instructions. Also, clear the command flip-flop and cancel any pending I/O + event if CLC is executed in diagnostic mode. This more correctly + implements the response of the hardware under DMA control. + + STATUS: Fixed in version 3.7-0. + + + +142. ENHANCEMENT: Add diagnostic loopback capability to the 12920A multiplexer. + + VERSION: 3.7-0 + + OBSERVATION: To run the HP multiplexer diagnostic, a loopback cable is + needed that interconnects two ports. To test all sixteen ports, eight + cables are needed, or the diagnostic must be run eight times while moving + the single cable from port pair to port pair. The diagnostic cannot be run + under simulation, because the 12920A simulator does not provide loopback + capability. + + RESOLUTION: Add DIAG/TERM commands to switch between diagnostic cable + (loopback) mode and terminal cable (Telnet connection) mode. + + STATUS: Fixed in version 3.7-1. + + + +143. PROBLEM: The 12920A multiplexer control card diagnostic fails in test 0. + + VERSION: 3.7-0 + + OBSERVATION: Running the control diagnostic reports this failure: + + TEST 00 + E027 PRESET DID NOT CLEAR STATUS ON PORT 01 + + The diagnostic is testing each channel after PRESET to verify that the + status is reset, but the value returned is not as expected. + + CAUSE: Page 3-6, paragraph 3-38 of the multiplexer service manual states, + "The channel number is four bits (10 through 13) of every output or input + word. When the scan bit is cleared (logic 0) during an OTA/B command, the + channel number does not change and the status of the same channel is loaded + by the next LIA/B command." The diagnostic sets the channel number by an + OTA to the control card select code. However, the "ioOTX" handler in + "muxcio" is not setting the channel to the supplied value for subsequent + LIA/B use. + + RESOLUTION: Set "muxc_chan" (hp2100_mux.c) to the channel number supplied + in the "ioOTX" handler in "muxcio." + + STATUS: Fixed in version 3.7-1. + + + +144. PROBLEM: The 12920A multiplexer control card diagnostic fails in test 4. + + VERSION: 3.7-0 + + OBSERVATION: Running the control diagnostic reports this failure: + + TEST 04 + E034 STORED STATUS NO. 1 FAILED TO INTERRUPT + + The diagnostic sets the multiplexer channel to interrupt on a change in S1 + status, but the interrupt did not occur as expected. + + CAUSE: The "mux_cntl_int" returns immediately if "muxc_scan" (the scan + bit) is zero. This behavior is incorrect; with the scan bit set to zero, + only the current channel should be tested for interrupt. + + Note that Figure 3-3, the "Simplified Schematic Diagram" on page 3-9 of the + service manual shows that the status interrupt is conditional on the scan + bit, but the actual schematic in figure 5-4 on page 5-15 shows that this is + not the case. + + RESOLUTION: Modify "mux_cntl_int" (hp2100_mux.c) to test the current + channel for a status interrupt condition if "muxc_scan" is zero, rather + than returning directly. + + STATUS: Fixed in version 3.7-1. + + + +145. PROBLEM: The 12920A multiplexer data card diagnostic fails in test 1. + + VERSION: 3.7-0 + + OBSERVATION: Running the data diagnostic reports this failure: + + TEST 01 + E032 SEND PORT NUMBER IS 00 SHOULD BE 01 + + The diagnostic is reading the transmitted data from the lower select code + to determine the transmit channel, but the channel number is wrong. + + CAUSE: The "mux_data_int" function is setting only the upper select code + status value in response to a transmit interrupt. The lower select code + card schematic, figure 5-3 on page 5-11 of the service manual, shows that + the interrupting channel number is presented on bits 14-10 of the status + words supplied by both the upper and lower cards. + + RESOLUTION: Modify "mux_data_int" (hp2100_mux.c) to set "muxl_ibuf" as + well as "muxu_ibuf" in response to a transmit interrupt. + + STATUS: Fixed in version 3.7-1. + + + +146. PROBLEM: The 12920A multiplexer data card diagnostic fails in test 1. + + VERSION: 3.7-0 + + OBSERVATION: Running the data diagnostic reports this failure: + + TEST 01 + E034 DATA RECEIVED ON PORT 00 IS 2125 SHOULD BE 3525 + + Data is sent out on one channel is compared for equality when received on + the other channel. The values are not equal. + + CAUSE: Characters delivered to the multiplexer are contained in bits 10-0 + of data words output from the CPU. In the "ioCTL" handler in "muxlio," the + output word is masked with OTL_CHAR (01777) to retain just the data before + storing the result in "mux_xbuf". However, "mux_xbuf" and the + corresponding "mux_rbuf" are declared as "uint8", so the upper three bits + are lost. + + RESOLUTION: Change the declarations of "mux_xbuf" and "mux_rbuf" + (hp2100_mux.c) from "uint8" to "uint16" to retain all of the character data + bits. + + STATUS: Fixed in version 3.7-1. + + + +147. PROBLEM: The 12920A multiplexer data card diagnostic fails in test 2. + + VERSION: 3.7-0 + + OBSERVATION: Running the data diagnostic reports this failure: + + TEST 02 + E041 BREAK BIT SHOULD BE SET + + The diagnostic is transmitting an all-space character and testing whether + the receiver detects this as a break. The break bit is not being set. + + CAUSE: The error is misleading. The actual cause is that an interrupt is + not occurring on the receive channel, because "mux_rchp" is not being set + for the target line in "muxi_svc" if SCPE_BREAK is detected, even though + the break flag is being set in the status word. + + RESOLUTION: Modify "muxi_svc" (hp2100_mux.c) to indicate a pending + character if a break is detected. + + STATUS: Fixed in version 3.7-1. + + + +148. PROBLEM: The 12920A multiplexer data card diagnostic fails in test 3. + + VERSION: 3.7-0 + + OBSERVATION: Running the data diagnostic reports this failure: + + TEST 03 + E042 PARITY BIT SHOULD BE SET + + The diagnostic is checking that the "parity check" bit (bit 15) of the + received status word is 1 when odd parity is sent. The bit is 0. + + CAUSE: The "odd_par" table has numerous errors in it. For example, the + values in columns 006 and 007 should be the opposite of the values in + columns 016 and 017, but in many cases they are not. + + Also, the "RCV_PAR" macro is setting LIL_PAR if the data has even parity, + not odd parity. For example, it returns LIL_PAR on a data value of zero. + Paragraph 3-23 on page 3-6 of the service manual says, "The parity bit is + set (logic 1) for odd parity and turned off (logic 0) for even parity." + + RESOLUTION: Correct the "odd_par" table (hp2100_mux.c) to reflect the + correct odd parity for all values. Reverse the sense of the test in + "RCV_PAR" so that "LIL_PAR" is returned if the received value has odd + parity. + + STATUS: Fixed in version 3.7-1. + + + +149. PROBLEM: The 12920A multiplexer data card diagnostic fails in test 3. + + VERSION: 3.7-0 + + OBSERVATION: Running the data diagnostic reports this failure: + + TEST 03 + E043 RAW PARITY BIT 7 + + The diagnostic is checking that bit 7 of the data word contains the desired + parity (odd or even). Bit 7 has the wrong value. + + CAUSE: Parity is not being generated for transmitted characters. + + RESOLUTION: Modify the "ioCTL" handler in "muxlio" (hp2100_mux.c) to + generate odd parity and add it to the data if bit 12 of the transmission + configuration word is set. + + STATUS: Fixed in version 3.7-1. + + + +150. PROBLEM: The 12920A multiplexer data card diagnostic fails in test 4. + + VERSION: 3.7-0 + + OBSERVATION: Running the data diagnostic reports this failure: + + TEST 04 + E033 RECEIVE PORT NUMBER IS 00 SHOULD BE 16 + + The diagnostic is configuring the diagnose channels and presuming that an + initial CLC 0 will clear the configuration parameters for all channels. + + CAUSE: The CLC handler is not performing the master clear function, so + the previously configured channel 0 is interrupting before the expected + channel 16. + + Also, the interrupting channel number is truncated to four bits by the + "PUT_CCH" macro in "mux_data_int", so an interrupt on channel 16 is + reported as being on channel 0. Control card channel numbers are four bits + in size, but data channel numbers are five bits; the wrong macro is being + used to form the status word. + + RESOLUTION: Modify the "ioCRS" handler in "muxlio" (hp2100_mux.c) to clear + all 37 channel transmit and receive parameters in response to a CLC 0. + Modify "mux_data_int" to use the "PUT_DCH" macro to put the data channel + number into the return status. + + STATUS: Fixed in version 3.7-1. + + + +151. ENHANCEMENT: Add debug printouts to the 12920A multiplexer. + + VERSION: 3.7-0 + + OBSERVATION: Debugging multiplexer behavior would be easier if the + internal state of the simulator was observable and recordable. + + RESOLUTION: Modify "hp2100_mux.c" to add debug-mode printouts. + + STATUS: Fixed in version 3.7-1. + + + +152. ENHANCEMENT: Add debug printouts to the 12875A Interprocessor Link. + + VERSION: 3.7-0 + + OBSERVATION: Debugging HP 2000 Time Shared BASIC systems would be + easier if the internal state of the link simulator was observable and + recordable. + + RESOLUTION: Modify "hp2100_ipl.c" to add debug-mode printouts. Modify + "sim_defs.h" to add a "DEBUG_PRJ" macro. + + STATUS: Fixed in version 3.7-1. + + + +153. PROBLEM: The 2000 Access terminal multiplexer does not initialize properly + approximately three starts in ten on multiprocessor host systems. + + VERSION: 3.7-0 + + OBSERVATION: Booting the 2000 Access Time Shared BASIC system appears to + start the system correctly, but the terminal multiplexer does not work. + Typing a CR does not produce the expected "PLEASE LOG IN" message, even + though the system console is responsive. Restarting the system often + corrects the problem. + + CAUSE: There is a race condition between the system processor (SP) and the + I/O processor (IOP) during initialization. A 321-word DMA transfer is done + from the IOP to the SP. Immediately after DMA completion, the SP pulses + the interprocessor link to "set correct flag direction" (according to the + Access source). The SP depends on the IOP still being in the DMA + completion interrupt handler when that pulse occurs, so that it does not + cause an interrupt and subsequent command processing. + + On a multiprocessor host system, the SP and IOP SIMH processes may run in + parallel. If the SP is blocked after DMA completion and before the IPL + pulse, the IOP may complete its own DMA completion interrupt handling and + therefore see the pulse as a second DMA command request. If that occurs, + the IOP hangs in the DMA transfer, so it never completes initialization of + the terminal multiplexer. + + RESOLUTION: Modify the "ioEDT" handler in "iplio" (hp2100_ipl.c) to sleep + for one millisecond before signalling a DMA completion interrupt for an + output transfer. This allows the SP time to pulse the IPL before the IOP + processes the DMA completion interrupt. Modify "dma_cycle" (hp2100_cpu.c) + to pass the DMA channel number and I/O direction flag in the "dat" + parameter to EDT handlers. + + Note that this is a workaround, and not a solution, as the SP can still + block between DMA completion and IPL pulsing, which would allow the IOP to + complete its DMA handling first. + + STATUS: Fixed in version 3.7-1. + + + +154. PROBLEM: The 12920A multiplexer simulator encounters a buffer overrun + error when the five "diagnose" lines are employed. + + VERSION: 3.7-0 + + OBSERVATION: Multiplexer line status is kept in "mux_sta", which is + defined with 16 elements. However, there are 21 receive lines for which + status is kept. When "mux_diag" is called to service the "diagnose" lines + (lines 16-20), "mux_sta" is indexed beyond the end of its definition. + + CAUSE: The size should be "MUX_LINES + MUX_ILINES" instead of "MUX_LINES". + + RESOLUTION: Modify the size of "mux_sta" (hp2100_mux.c) from 16 to 21 + elements. + + STATUS: Fixed in version 3.7-1. + + + +155. PROBLEM: Resetting the 12920A multiplexer does not clear status for the + receive-only "diagnose" lines. + + VERSION: 3.7-0 + + OBSERVATION: Line status is kept in "mux_sta[0..20]". Doing a multiplexer + reset (e.g. RESET, RUN, etc.) clears line status only in lines 0-15. + + CAUSE: Multiplexer line reset is handled by "mux_reset_ln" in response to + a device reset. "mux_reset_ln" is called only for lines 0-15. + + RESOLUTION: Modify "muxc_reset" (hp2100_mux.c) to clear the variables + associated with lines 16-20. + + STATUS: Fixed in version 3.7-1. + + + +156. PROBLEM: Breakpoint actions aren't executed properly if the breakpoint + occurs in a DO file. + + VERSION: 3.7-0 + + OBSERVATION: Breakpoint actions are not reliably executed if they appear + in a DO file. Given this "t.sim" command file: + + break 100; e 0-1 + go + break 200; e 2-3 + go + e 4-5 + + ...then entering "do t.sim" at the command prompt produces this output: + + Breakpoint, P: 00100 (NOP) + + Breakpoint, P: 00200 (NOP) + 4: 000000 + 5: 000000 + sim> e 2-3 + 2: 000000 + 3: 000000 + + Note that the "e 0-1" is not executed at all, and the "e 2-3" is executed + after the "e 4-5". + + CAUSE: Breakpoint actions are executed by a call to "sim_brk_getact" in + the main execution loop. The call is missing from the execution loop in + "do_cmd". + + In the test case, the "e 2-3" is being executed by the "sim_brk_getact" in + the main execution loop after command file execution terminates. This + out-of-sequence execution could have serious consequences, e.g. if the + command were intended to clear a log file prior to a debug run ("! del + big.log") but instead deleted it at the end of the run when the DO file + terminated. + + RESOLUTION: Modify "do_cmd" (scp.c) to incorporate a call to + "sim_brk_getact" to process breakpoint commands as they occur. + + STATUS: Fixed in version 3.7-1. + + + +157. PROBLEM: The .DMP instruction returns erroneous results. + + VERSION: 3.7-3 + + OBSERVATION: After creating a FMGR file that occupies the rest of the + cartridge, the "next track" field in the directory list is wildly + incorrect. + + CAUSE: An unsigned multiply is done instead of a signed multiply. + Multiplying by a small negative number returns an overflow condition. + + RESOLUTION: Convert the operands to signed integers before multiplying in + "hp2100_cpu3.c". + + STATUS: Fixed in version 3.8-0. + + + +158. PROBLEM: The .DDI instruction returns erroneous results. + + VERSION: 3.7-3 + + OBSERVATION: Attempting to scan an indexed library file that is split into + multiple extents returns FMGR -012 (SOF or EOF error). Accessing the + library file sequentially avoids the error. + + CAUSE: Extent calculations are in error. An unsigned divide is done + instead of a signed divide. + + RESOLUTION: Convert the operands to signed integers before dividing in + "hp2100_cpu3.c" + + STATUS: Fixed in version 3.8-0. + + + +159. ENHANCEMENT: Portable unsigned-to-signed conversions were added. + + VERSION: 3.7-3 + + OBSERVATION: Conversions from unsigned to signed values, e.g., from + "uint16" to "int16", using casts or union store/load are not portable. + They will fail if the size in bits is > 16. Portable versions are needed. + + RESOLUTION: Add portable "INT16" and "INT32" macros (hp2100_defs.h) to + provide uint16-to-int16 and uint32-to-int32 conversions. + + STATUS: Fixed in version 3.8-0. + + + +160. PROBLEM: The action of jumpers W5 (JSB), W6 (INT), and W7 (SEL1) for the + 12892B Memory Protect card are reversed. + + VERSION: 3.7-3 + + OBSERVATION: The SET/SHOW MP command sets/reports the jumpers in the wrong + state. A jumper flag of 1 is reported as "in" but it is treated as "out" + by the simulation. + + CAUSE: The "mp_mod" table treats a jumper flag bit on as indicating an + installed jumper, but the flag bit actually indicates a removed jumper. + + RESOLUTION: Reverse the jumper sense in the "mp_mod" table (hp2100_cpu.c). + + STATUS: Fixed in version 3.8-0. + + + +161. PROBLEM: The action of jumper W5 (JSB) is incorrect. + + VERSION: 3.7-3 + + OBSERVATION: Executing a JSB below the MP fence and to a write-protected + page should cause a DM violation. This occurs if W5 is in, but an MP + violation is reported if W5 is out. + + CAUSE: The W5 check is wrong. + + RESOLUTION: Correct the JSB handler in "sim_instr" (hp2100_cpu.c) to + report a DM error with W5 out (unless the instruction is JSB 0 or JSB 1, in + which case an MP error is correct). + + STATUS: Fixed in version 3.8-0. + + + +162. PROBLEM: The memory protect MEVFF is not reset when an I/O instruction is + executed from a trap cell during an interrupt. + + VERSION: 3.7-3 + + OBSERVATION: The Memory Expansion Violation Flip-Flop (MEVFF) is set + on any DMS violation: read protect, write protect, base-page protect, or + privilege. The MEVFF is cleared when MP is re-enabled after the violation + is handled. + + Any interrupt request automatically disables MP. MP is re-enabled + explicitly via an STC 5 instruction or implicitly after a non-HLT I/O + instruction is executed in the interrupt trap cell. This latter case does + not clear the MEVFF under simulation. + + CAUSE: Improper coding in the interrupt handler. + + RESOLUTION: Modify "sim_instr" (hp2100_cpu.c) to set "mp_mevff" to zero if + a non-HLT I/O instruction is executed from a trap cell. + + STATUS: Fixed in version 3.8-0. + + + +163. PROBLEM: Running certain RTE-6/VM configurations will cause an + "unimplemented instruction" stop for the DIAG (100000) instruction. + + VERSION: 3.7-3 + + OBSERVATION: If an RTE-6/VM system is generated with a firmware + replacement for the $LIBR routine, and a program using the software + equivalent is run under that system, an "unimplemented instruction" stop + occurs. This is actually due to a bug in $RQST (EXEC6). The instruction + sequence executed is: + + XOR INSTR NOW HAVE THE ADDRESS + RAL,CLE,SLA,ERA IF INDIRECT + INDR XLA A,I GET NEXT LEVEL + RAL,CLE,SLA,ERA CHECK FOR MULTI LEVEL + JMP INDR FOUND ONE SO LOOP (MUST END) + + If the sign bit of the A register is zero, the first "RAL,CLE,SLA,ERA" + improperly skips the first word of the two-word instruction "XLA A,I" and + executes the second word (100000). This decodes as a DIAG instruction. + DIAG should execute as a NOP with the CPU running, as it is only effective + when executed from single-step mode. This would mask the bug, as the + second "RAL,CLE,SLA,ERA" would also skip, taking execution out of the + sequence; the bug fix would be to replace the first "RAL,CLE,SLA,ERA" with + a "JMP *+3". However, the simulator stops instead. + + CAUSE: The DIAG processor executes as NOP on the E-Series, but no + equivalent test is made for the F-Series. + + RESOLUTION: Modify "cpu_eau" (hp2100_cpu1.c) to allow DIAG as NOP on the + F-Series as well as the E-Series. + + STATUS: Fixed in version 3.8-0. + + + +164. ENHANCEMENT: Add the RTE-6/VM operating system accelerator and virtual + memory firmware instructions. + + VERSION: 3.7-3 + + OBSERVATION: RTE-6/VM "primary" (i.e., factory distribution) systems after + revision 2401 were generated with the OS/VMA firmware replacements. Such + systems will not run under SIMH due to the lack of firmware support. To + get later revision systems running without firmware replacements requires a + bootstrapping process that begins with revision 2340 and generates + successive systems until the desired revision is reached. Moreover, later + revisions of some programs (e.g., TF) will not load due to exceeding the + logical address space available when software replacements are used. + + RESOLUTION: Add the OS/VMA instructions (hp2100_cpu5.c, hp2100_cpu6.c) to + support later primaries and to provide address space reductions in later + programs. Add CPU debug support and flags for OS and VMA instructions. + + STATUS: Fixed in version 3.8-0. + + + +165. ENHANCEMENT: Change the default breakpoint type from the current static + setting of "-e" (break unconditionally) to a dynamic setting that matches + the current DMS mapping ("-n", "-s", or "-u"). + + VERSION: 3.2-1 + + OBSERVATION: After reaching a map-specific breakpoint (e.g., a system-map + breakpoint to debug a device driver), the most common action is to examine + memory locations and set another breakpoint farther ahead in the code. That + breakpoint will, of course, be set in the same mapping mode as the one just + reached, i.e., in the current DMS mapping mode. Therefore, defaulting to + "the same map as is currently enabled" leads to the most-used cases not + requiring additional switches (and therefore the chance of operator error). + + RESOLUTION: Before exiting "sim_instr" (hp2100_cpu.c), set "sim_brk_dflt" + to a switch corresponding to the current DMS mapping mode. + + STATUS: Fixed in version 3.8-0. + + + +166. ENHANCEMENT: Change the default examine/deposit addressing mode from the + current static setting of "address is physical" to a dynamic setting that + matches the current DMS mapping ("-s" or "-u"), and provide a new modifier + option ("-n") to specify that an address is a physical address. + + VERSION: 3.2-1 + + OBSERVATION: After reaching a breakpoint, it is common to examine memory + contents. The most common requirement is to examine memory under the + currently enabled map, i.e., if a break occurred under the system map, then + examination of system memory is most likely to be requested (and + correspondingly for user-map breakpoints). However, the current default is + to examine the first 32K of physical memory. This is a reasonable default + for non-DMS systems, or when DMS is not enabled, but is awkward when + debugging mapped environments. + + A switch ("-v") is currently provided to request access under the current + DMS map, but debugging with DMS active essentially requires specifying that + switch on every EXAMINE and DEPOSIT command. It would be more useful if + this action were the default. + + RESOLUTION: Modify "cpu_ex", "cpu_dep", and "dms_cons" (hp2100_cpu.c) to + respond to redefined switch modifiers as follows: + + Old New Description + === === =========================================================== + -v if DMS enabled, use current map, else use unmapped + -n use unmapped + -s -s if DMS enabled, use system map, else illegal + -u -u if DMS enabled, use user map, else illegal + -p -p if DMS enabled, use DCPC port A map, else illegal + -q -q if DMS enabled, use DCPC port B map, else illegal + + If a map specifier is used when DMS is not enabled, "Command not allowed" + results. Note that the SAVE and RESTORE commands always access memory + unmapped. Also, note that operation in non-DMS environments is unchanged, + i.e., EXAMINE and DEPOSIT with no modifiers still access physical memory as + before. + + STATUS: Fixed in version 3.8-0. + + + +167. ENHANCEMENT: NOBR with no argument clears breakpoint at the current PC. + + VERSION: 3.7-0 + + OBSERVATION: Breakpoints are often required only once, e.g., when + establishing which of several paths through a routine is taken. In this + case, when a breakpoint is reached, it is immediately removed. + + The existing breakpoint clear syntax requires specification of the address. + It would be helpful if the address defaulted to the current PC, i.e., the + location of the breakpoint just hit. + + RESOLUTION: Modify "ssh_break" (scp.c) to allow omission of the address + argument and, if omitted, to clear the breakpoint corresponding to the + current PC. + + STATUS: Fixed in version 3.8-0. + + + +168. ENHANCEMENT: The SHOW VERSION command now reports the patch level. + + VERSION: 3.3-2 + + OBSERVATION: Having multiple patched versions of SIMH that report the + same version number leads to confusion. But official releases often + increment the minor version only. + + RESOLUTION: Modify "show_version" (scp.c) and "sim_rev.h" to add a + reported "patch delta" version number. + + STATUS: Fixed in version 3.8-0. + + + +169. PROBLEM: The DPTR register in the DS device cannot be set to any value + other than 0 or 1. + + VERSION: 3.7-3 + + OBSERVATION: The DPTR register is documented as an 8-bit "sector buffer + pointer." However, it is implemented as a single-bit flag in the REG + structure. This prohibits setting any value other than 0/1. + + CAUSE: DPTR is improperly defined with the FLDATA macro. It should use + DRDATA instead. + + RESOLUTION: Modify "ds_reg" (hp2100_ds.c) to define the DPTR register as + DRDATA instead of FLDATA. + + STATUS: Fixed in version 3.8-0. + + + +170. ENHANCEMENT: Add an implementation of the 12966A Buffered Asynchronous + Communications Interface (BACI) card. + + VERSION: 3.7-3 + + OBSERVATION: Newer RTE primary systems will not run without a system + console connected to a BACI card using DVR05, as support for the Teletype + interface using DVR00 had been dropped. Reconfiguring to a DVR00 driver is + problematic if another "type 00 driver" (e.g., DVM00) is present in the + equipment table ahead of DVR00. Also, some RTE features, such as + command-stack editing, don't work with the Teletype interface. Having a + BACI simulation would allow these systems to run "out of the box." + + RESOLUTION: Add a BACI simulation (hp2100_baci.c) to the HP simulator. + + STATUS: Fixed in version 3.8-0. + + + +171. ENHANCEMENT: Expose the current time base generator (CLK) poll time via a + device register. + + VERSION: 3.7-3 + + OBSERVATION: It is often helpful to know the number of simulated CPU + instructions per second on a host machine. As the CLK device is calibrated + to real time, knowing the tick rate and the service poll time would allow + the calculation of the simulated MIPS. The tick rate is given by the "SEL" + register, but the poll time is set using a local variable and is not + visible to the user. + + RESOLUTION: Added global variable "clk_tick" and register "IPTICK" + (instructions per tick) to the CLK device (hp2100_stddev.c). + + STATUS: Fixed in version 3.8-0. + + + +172. PROBLEM: The "ioCRS" actions are incorrect in several devices. + + VERSION: 3.7-3 + + OBSERVATION: The "ioCRS" signal was added in 3.7-0 to all devices. As an + expedient, the action was defaulted to CLC SC, which was how CRS was + handled before. Most devices handle CRS as CLC, but not all do. In + particular, the TTY and DS devices do not. + + CAUSE: Expediency. + + RESOLUTION: Modified the "ioCRS" handlers in "tty_svc" (hp2100_stddev.c) + and "ds_svc" (hp2100_ds.c) to implement the control reset signal correctly. + + STATUS: Fixed in version 3.8-0. + + + +173. PROBLEM: The paper tape reader hangs at EOT after "rewinding" a tape. + + VERSION: 3.7-3 + + OBSERVATION: The POS register records the current position of the file + attached to the PTR device. The manual says, "...by changing POS, the user + can backspace or advance the reader." Attempting to re-read a tape by + setting POS to 0 causes the reader to hang when the end-of-tape is + encountered the second time. + + CAUSE: The trailing-null counter, "ptr_trlcnt", is not reset when the + position is. Therefore, the automatic trailer function does not work the + second time, and the reader hangs. + + RESOLUTION: Reset "ptr_trlcnt" when a non-null character is read. + + STATUS: Fixed in version 3.8-0. + + + +174. PROBLEM: The .PWR2 instruction returns the wrong value in the A register. + + VERSION: 3.7-3 + + OBSERVATION: The .PWR2 instruction returns the result of the expression + (ab * 2 ^ n) in the A and B registers. The B-register value is correct, + but the A-register value is always 0. + + CAUSE: The conversion of the high-word value in "fp_unpack" from "fop" to + "mantissa" is incorrect. Specifically, the cast to 16 bits should be done + on the shifted value, but it is improperly done on the unshifted value, so + that shifting right by 16 always yields a zero value. + + Note that the only other instruction to use "fp_unpack" is .FLUN, but that + discards the A-register (high mantissa) value and instead returns the + exponent in A, so the error does not manifest itself there. + + Also note that there are two "fp_unpack" implementations. The one in error + is the firmware floating-point version. The hardware floating-point + version in "hp2100_fp1.c" is correct and is used when HAVE_INT64 is defined + during compilation. + + RESOLUTION: Modify "fp_unpack" (hp2100_fp.c) to correct the conversion. + + STATUS: Fixed in version 3.8-0. + + + +175. PROBLEM: The DBI self-test instruction does not skip. + + VERSION: 3.7-3 + + OBSERVATION: The double-integer firmware self-test is supposed to set the + S register to 102077 octal and return to P+1. Neither of these actions + occur. + + CAUSE: At the time that the DBI firmware was implemented, the source + microcode and the installation manual were unavailable. Subsequently, the + source microcode was located, and the self-test action is now known. + + RESOLUTION: Modify "cpu_dbi" (hp2100_cpu3.c) to add the proper + implementation of the DBI self-test instruction. + + STATUS: Fixed in version 3.8-0. + + + +176. PROBLEM: The DEPOSIT command will change in some + other device if the name is unique to that other device. + + VERSION: 3.7-3 + + OBSERVATION: Entering "deposit ptr ppos 0" actually changes the "ppos" + register in the "tty" device. It should give an error that "ppos" does not + exist in the "ptr" device. + + CAUSE: The "exdep_cmd" routine is calling "find_reg_glob" if the + "find_reg" routine returns a not-found error for the selected device. + "find_reg_glob" searches for a unique name among all devices and returns + it if found. + + RESOLUTION: None. + + STATUS: Fixed in version 3.8-0. + + + +177. PROBLEM: The four-word double-precision sine and cosine functions return + erroneous results. + + VERSION: 3.7-3 + + OBSERVATION: The .SIN and .COS functions return improper values when SIS + firmware is present. When the firmware is absent, the results are correct. + + CAUSE: .SIN and .COS call /CMRT, the common range reduction routine. This + routine is implemented in the SIS firmware. The /CMRT firmware simulation + is not setting the B register properly to the lower 16 bits of the + reduction multiple. + + RESOLUTION: Correct "cpu_sis" (hp2100_cpu4.c) to return the proper value + in the B register for the /CMRT instruction. + + STATUS: Fixed in version 3.8-0. + + + +178. PROBLEM: The free HP 700/92 terminal emulator, QCTERM from AICS, does not + work with SIMH. + + VERSION: 3.7-0 + + OBSERVATION: Attempting to run QCTERM as a Telnet client with SIMH loses + characters. Specifically, the first character typed after a CR is lost. + + CAUSE: QCTERM is sending "bare" carriage-return characters to SIMH. SIMH + presumes that CR will always be followed by LF or NUL in text mode, so it + simply drops the next character. For QCTERM, this is the first character + of the subsequent transmission. + + Examination of the Telnet connection initiation code shows that SIMH is + sending several command sequences but is not checking the client replies + (except for binary mode). A correct negotiation mechanism must be + implemented to handle the variety of Telnet clients properly. + + WORKAROUND: Modify the TNS_SKIP case in "tmxr_poll_rx" (sim_txmxr.c) to + skip only LF or NUL following CR. Any other character is processed as is. + + STATUS: Fixed in version 3.8-0. + + + +179. ENHANCEMENT: Add infrastructure changes to support CPU idling in a future + release. + + VERSION: 3.7-3 + + OBSERVATION: Idle support would be a welcome addition to the HP simulator. + + RESOLUTION: Modify hp2100_stddev.c to change the TTY (console) input poll + to use a 10 millisecond calibrated timer, to provide a synchronization + routine for use by other devices with input polls, and to synchronize the + CLK to the console poll if it is set for a 10-millisecond period. Add + UNIT_IDLE flags to the CLK and TTY input units. Modify hp2100_mux.c and + hp2100_baci.c to synchronize Telnet polling with the console poll. + + STATUS: Fixed in version 3.8-0. + + + +180. PROBLEM: There is some dead code in hp2100_stddev.c, now that control + character handling is in sim_console.c. + + VERSION: 3.7-0 + + OBSERVATION: In version 3.2-2, "tto_out" (hp2100_stddev.c) was altered to + suppress output for all control characters (characters < 40 octal), except + for BEL, BS, LF, and CR. This was in support of the RTE line editor. + + In version 3.5-2, generalized support for control character output + suppression was added to sim_console.c. This obviated the HP-specific + handling. However, some of that code remained in hp2100_stddev.c. + + CAUSE: Oversight. + + RESOLUTION: Removed the redundant code. + + STATUS: Fixed in version 3.8-0. + + + +181. ENHANCEMENT: Add the RTE-IVB extended memory area firmware instructions. + + VERSION: 3.7-3 + + OBSERVATION: The Pascal/1000 compiler (HP 92832A) relies on EMA + instructions to manage its internal memory. EMA software is available, but + the compiler can exceed the available logical address space if they are + employed, due to the size of the software routines. + + RESOLUTION: Add the EMA instructions (hp2100_cpu5.c) to provide address + space reductions in the Pascal compiler. Add CPU debug support and flags + for the EMA instructions. + + STATUS: Fixed in version 3.8-0. + + + +182. ENHANCEMENT: Add the Vector Instruction Set firmware instructions. + + VERSION: 3.7-3 + + OBSERVATION: VIS was used in some HP programs, notably SPICE. + + RESOLUTION: Add the VIS instructions (hp2100_cpu7.c) to provide support + for HP-SPICE. Add CPU debug support and flags for the VIS instructions. + + STATUS: Fixed in version 3.8-0. + + + +183. PROBLEM: Single-stepping through interrupts does not report instruction + execution properly. + + VERSION: 3.7-3 + + OBSERVATION: When single-stepping, the simulator prints the next + instruction to be executed before pausing for a command. When an interrupt + is pending, the instruction printed is not correct. Moreover, a + single-step command at this point will execute two instructions. + + CAUSE: There are two problems with the simulator. + + The first is with the simulator routine that prints the next instruction to + be executed at the end of a step. It is not checking whether an interrupt + is pending. The instruction printed is the next instruction that would + have been executed, if there had not been an interrupt pending. But + because there was an interrupt pending, the next instruction actually + executed is the trap-cell instruction. + + The second problem is that the simulator is not counting down events during + the trap cell instruction execution. During each normal instruction, the + simulator decreases the event counter, including the step counter. But it + omits the decrement for the trap cell instruction. So single-stepping with + an interrupt pending actually causes two instruction executions: the + trap-cell instruction, and the subsequent instruction (usually the target + of the JMP or JSB in the trap cell). + + RESOLUTION: Modify "fprint_sym" (hp2100_sys.c) to check for a pending + interrupt, and if so, to print the trap cell instruction instead of the + instruction at PC. Modify "sim_instr" (hp2100_cpu.c) to decrement the + event counter for trap cell instructions. + + STATUS: Fixed in version 3.8-0. + + + +184. PROBLEM: The TTY output interrupt time is too short for MSU BASIC. + + VERSION: 3.7-3 + + OBSERVATION: When running MSU BASIC, this code eventually produces an + "Indirect address loop, P: 37001 (STA 1,I)" error: + + 10 PRINT "HELLO WORLD!" + 20 GOTO 10 + 30 END + + CAUSE: The TTY output rate is abnormally fast compared to the original + hardware. The ASR-33 operated at 10 characters per second. The HP 2116 + processor ran at about 600 instructions per millisecond. Therefore, the + TTY would interrupt approximately every 60000 CPU instructions. But the + default SIMH configuration (SERIAL_OUT_WAIT) is to interrupt every 100 + instructions -- about 600x the rate of the actual Teletype. + + MSU BASIC (a contributed library program) maintains per-user I/O state + buffers, one for each of four users, plus one for the I/O system. When a + TTY interrupt occurs, the program copies the per-user state into the I/O + state buffer, enters the TTY driver to output a character, copies the + updated I/O state back to the per-user buffer, and returns to a monitor + loop to wait for the completion interrupt, which would occur 100 + milliseconds later on a real machine. + + It takes 85 instructions from the STC that starts the TTY output until the + updated state copy is completed. With the TTIME default of 100 + instructions, that is normally just enough time to complete the buffer + transfer before another interrupt occurs. + + However, MSU BASIC also runs the time base generator (CLK) with a + one-second period. The TBG interrupt handler takes from 25 to 71 + instructions. If the TBG interrupts while the TTY event is active, it will + absorb enough instructions to cause the TTY interrupt to occur before the + updated state copy is finished. That leaves the per-user state buffer + inconsistent. As a result of the TTY interrupt, that inconsistent buffer + is copied to the I/O state buffer, and mayhem ensues. + + RESOLUTION: Lengthened the TTY output time in "tty_unit" (hp2100_stddev.c) + from 100 to 200 instructions. + + STATUS: Fixed in version 3.8-0. + + + +185. ENHANCEMENT: Add the SIGNAL/1000 firmware instructions. + + VERSION: 3.7-3 + + OBSERVATION: SIGNAL provides firmware acceleration for Fast Fourier + Transforms and was used in some signal processing applications. + + RESOLUTION: Add the SIGNAL instructions (hp2100_cpu7.c). Add CPU debug + support and flags for the SIGNAL instructions. + + STATUS: Fixed in version 3.8-0. + + + +186. ENHANCEMENT: Add idle support to the HP 2100 simulator. + + VERSION: 3.8-0 + + OBSERVATION: The DOS and RTE operating systems keep the current time of + day by counting TBG ticks. To maintain accurate time, a simulation must + run continuously. Given this requirement for continuous operation, it + would be helpful if the simulator idled the host processor when these + operating systems were idle themselves. + + RESOLUTION: Alter "cpu_mod" to add SET CPU IDLE/NOIDLE commands, and alter + "sim_instr" to add idle detection for DOS and RTE (hp2100_cpu.c). + + STATUS: Fixed in version 3.8-1. + + + +187. ENHANCEMENT: Report the device and line number for Telnet connections. + + VERSION: 3.8-0 + + OBSERVATION: When connecting a Telnet client to a simulator device via the + multiplexer library, the client receives a "welcome" message of the format: + + Connected to the HP2100 simulator + + It would be helpful if the user knew to which device and line the client + had connected. For example: + + Connected to the HP2100 simulator MUX device, line 3 + + The report for single-line devices, e.g., additional terminal devices, + would suppress the line number: + + Connected to the HP2100 simulator BACI device + + RESOLUTION: Modify sim_tmxr.h to add a "DEVICE *dptr" field at the end of + the TMXR structure. Change tmxr_attach() to look up the device from the + unit via find_dev_from_unit() and set "dptr" to point at the device. + Change tmxr_poll_conn() to print the device name and line number (if more + than one line defined) in the greeting message. + + STATUS: Fixed in version 3.8-1. + + + +188. ENHANCEMENT: Add a simulation of the 12792C eight-channel multiplexer. + + VERSION: 3.8-0 + + OBSERVATION: The main terminal multiplexer for later RTEs was the 12792, + and direct support was generated into primary systems from HP. The A/B/C + revisions of the multiplexer firmware used the same protocol and drivers on + RTE-IVB and RTE-6/VM. The D revision used an incompatible protocol and + required different drivers that were supported only on RTE-6/VM. + + RESOLUTION: Add the MPX device (hp2100_mpx.c) to simulate the 12792A/B/C, + and alter "hp2100_sys.c" and "hp2100_defs.h" to add the device structure + and default select code assignment. + + STATUS: Fixed in version 3.8-1. + + + +189. ENHANCEMENT: Add a mechanism to provide a device-specified connection + order for terminal multiplexers. + + VERSION: 3.8-0 + + OBSERVATION: Some operating systems allow per-line device drivers for + multiplexers (e.g., the HP 12792 and 12920 under RTE). These change the + line behavior, so that the existing model of multiplexers as pools of + identical lines is no longer valid. A method of specifying line connection + order is needed, so that connection to specific device drivers is possible. + + RESOLUTION: Modify the TMXR structure (sim_tmxr.h) to add an "int32 + *lnorder" field that points at an array specifying the line connection + order. Modify "tmxr_poll_conn" (sim_tmxr.c) to connect in the order given + by *lnorder, if defined, else to connect in ascending port number order. + Add "tmxr_set_lnorder" and "tmxr_show_lnorder" routines to provide support + for SET LINEORDER= and SHOW LINEORDER commands. + + STATUS: Fixed in version 3.8-1. + + + +190. ENHANCEMENT: Add a simulation of the 12620A/12936A Privileged Interrupt + Fences. + + VERSION: 3.8-0 + + OBSERVATION: Privileged DOS and RTE systems require the use of a + privileged interrupt fence card. This is needed to run the 12920A + 16-channel multiplexer under RTE. When configured for DIAG operation, the + LPS device may be used as an RTE fence, although the corresponding line + printer function is then lost. The DOS fence (12936A) had a unique + operation that is not duplicated by any existing simulation. + + RESOLUTION: Add the PIF device (hp2100_pif.c) to simulate the 12620A and + 12936A, and alter "hp2100_sys.c" and "hp2100_defs.h" to add the device + structure and default select code assignment. + + STATUS: Fixed in version 3.8-1. + + + +191. PROBLEM: The action of certain I/O cards (e.g., the 12936A Privileged + Interrupt Fence) cannot be modelled by SIMH. + + VERSION: 3.8-0 + + OBSERVATION: Certain I/O actions cannot be implemented within the current + design of the I/O simulation. For example, the 12936A card breaks the + interrupt priority chain when flag OR control is set. Simulation assumes + that priority is broken when flag AND control are set. + + CAUSE: The hardware has I/O signals for interrupt request (IRQ) and + interrupt priority to lower-priority devices (PRL). These signals are not + modelled directly in SIMH. Rather, they are implied by control, flag, and + flag buffer set (for IRQ) and control and flag set (for PRL). If an I/O + card does not follow these conventions, then the proper action cannot be + simulated. + + RESOLUTION: Modify the I/O simulation structure to model hardware signals, + rather than I/O instructions. Verify each simulated device's action in + response to each I/O backplane signal. Verify each device's reset routine + to ensure the proper response to RESET (POPIO signal) and RESET -P (PON + signal). + + STATUS: Fixed in version 3.8-1. + + + +192. PROBLEM: Escaping backslashes in DO commands does not work. + + VERSION: 3.8-0 + + OBSERVATION: The SIMH User's Guide says in Section 3.13, "Executing + Command Files:" + + The string %n is recognized as meaning argument n from the DO command + line. The character \ has the usual UNIX meaning of an escape character; + the next character is interpreted literally, even if it is % or \. + + The sequence "\%" is recognized as a literal "%" character. The sequence + "\\" is not recognized as a literal "\" character; instead, it is left + unaltered. In fact, "\%" is the only recognized escape; "\" followed by + any other character will not be processed, i.e., the "\" and that character + will remain. This makes using parameters in Windows file paths + impossible, as this: + + attach dev c:\path\to\\%1 + + substitutes for "%1" but leaves the double-backslashes, and this: + + attach dev c:\path\to\%1 + + ...does not substitute for "%1" and parses as "c:\path\to%1". + + Actually, the documented behavior (escaping every character) is + undesirable, as it will invalidate every current command file that uses + Windows path names. Were it implemented as documented, then a path such as + "c:\path\to\file" would be parsed as "c:pathtofile". Even restricting the + change to escaping just "\" and "%" will still invalidate current command + files that use network paths (e.g., "\\server\\share\\path\to\file" will + become "\server\share\path\to\file", which is a local path. This at least + is fixable, whereas there is no workaround for the current situation. + + CAUSE: The argument substituter is checking only for the "\%" case. + + RESOLUTION: Modify "sub_args" (scp.c) to accept "\\" as a literal + backslash, in addition to "\%" as a literal percent sign. + + STATUS: Fixed in version 3.8-1. + + + +193. PROBLEM: The DR and IPL boot loaders do not work. + + VERSION: 3.8-0 + + OBSERVATION: Attempting to boot the DR or IPL devices results in a hang in + the bootstrap. Examination shows that the I/O instructions are not being + configured. + + CAUSE: The loader protection feature added at revision 3.7-0 must be + turned off in order to write programmatically to the boot loader area. + Protection is automatically disabled for the devices using the "ibl_copy" + function in the CPU, but the DR and IPL devices install their bootstraps + within their boot routines and do not call "ibl_copy". + + RESOLUTION: Modify "ipl_boot" (hp2100_ipl.c) and "drc_boot" (hp2100_dr.c) + to use the "ibl_copy" routine. + + STATUS: Fixed in version 3.8-1. + + + +194. PROBLEM: Omitted parameters to DO command files do not substitute null + strings for the corresponding arguments. + + VERSION: 3.8-0 + + OBSERVATION: Given a command file "cmdfile" containing "echo %1 and %2", + the command "do cmdfile a b" results in: + + a and b + + ...which is as expected. However, "do cmdfile a" results in: + + a and %2 + + ...which is unexpected; the expected response is: + + a and + + ...i.e., the null string is substituted for "%2". This would be consistent + with argument substitution in operating system command shells. + + CAUSE: Arguments for omitted parameters are not being considered for + substitution. + + RESOLUTION: Modify "do_cmd" (scp.c) to initialize omitted arguments to + NULL and modify "sub_args" to skip null arguments during substitution. + + STATUS: Fixed in version 3.8-1. + + + +195. PROBLEM: JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort. + + VERSION: 3.8-0 + + OBSERVATION: The upper bound of protected memory is set by the memory + protect fence, and the lower bound is normally location 2. However, the + lower bound is 0 if the instruction is a JMP, or if the instruction is a + JSB and jumper W5 is out. That is, a JMP or a JSB (with W5 out) to any + location under the memory protect fence will cause a violation. If the + fence is set to or below the lower bound, though, then MP violations will + not occur. + + However, a JSB 0 or JSB 1 with the fence set to 0 or 1 and jumper W5 out + still causes an MP abort. + + CAUSE: Improper coding of the W5 test in the JSB simulation. + + RESOLUTION: Modify the instruction dispatcher "sim_instr" (hp2100_cpu.c) + to set the protected lower bound for JSB as indicated by W5 and to test the + target address against the lower bound as well as the MP fence. + + STATUS: Fixed in version 3.8-1. + + + +196. PROBLEM: The MEM (DMS) violation register is not being set properly. + + VERSION: 3.8-0 + + OBSERVATION: The STC handler within the MP I/O instruction routine "proio" + contains an explicit clear of the MEM violation register. There is no such + action shown on either the MP or MEM card schematics. When the statement + is removed, the Memory Expansion Module Diagnostic (DSN 102103) fails in + TST21, the "Violation Register Map Bits Test," with an "E302 VR MAP 00" + error. + + TST21 generates three MEM violations and one MP violation. The value of + the MEM violation register is checked after all four violations to confirm + that the map register address corresponds to the violation location. The + value after the MP violation is in error; the violation register still + contains the value from the prior MEM violation. + + CAUSE: The simulator updates the violation register whenever a MEM + violation occurs. The hardware actually updates the violation register for + every memory read, every memory write above the lower bound of protected + memory, and every execution of a privileged DMS instruction. The register + is "frozen" when MP is disabled by an MP or DM error to capture the state + of the MEM (MEVFF sets or CTL5FF clears). + + Examining the violation register value after each MEM violation produces + the expected result. Examining it after the MP violation does not, because + the register is not being set. As it happens, the MP violation in the + diagnostic occurs on page 0, so the problem is masked if the violation + register is set to 0 when MP is enabled. Other bits in the register are + wrong in this case, but the diagnostic does not check them. + + It would be proper to fix this problem by updating the violation register + after each memory access, as is done in hardware. Fortunately, this isn't + necessary, as the visible state of the violation register is only available + via a programmed RVA/B instruction or via the SCP interface. Therefore, it + is sufficient if the register is updated: + + - at a DM violation (when freezing) + - at an MP violation (when freezing) + - during RVA/B execution (if not frozen) + - before returning to SCP after a simulator stop (if not frozen) + + The first of these conditions is currently implemented. The other three + must be added to address the issue. + + RESOLUTION: Add a new "dms_upd_vr" routine (hp2100_cpu.c) to update the + MEM violation register value. Modify the ABORT macro to take the address + of the last memory access as the parameter. Modify the MP abort handler to + use the memory address to update the MEM violation register. Add new + update calls to the RVA/B simulator and to the cleanup code at the end of + "sim_instr" before returning to SCP. + + STATUS: Fixed in version 3.8-1. + + + +197. PROBLEM: The ME Bus Enabled bit in the MEM violation register is not being + set properly. + + VERSION: 3.8-0 + + OBSERVATION: The ME Bus Enabled bit in the violation register reflects the + state of the MEBEN (ME Bus Enable) signal on the MEM card. MEBEN is + asserted if the MEM is enabled (MAPON signal) and the last memory access + was not to the unmapped portion of the base page (OFA signal). + + Under simulation, this bit is set if a MEM violation is either a read + violation or a write violation, and it is clear otherwise (base page or + privileged instruction violation). This is correct only for the base page + violation case; for the other three cases, MEBEN may be either high or low. + + CAUSE: Incorrect logic in the "dms_viol" routine. + + A base page violation, by definition, occurs if a write is attempted to the + unmapped portion of the base page. MEBEN must be off in this case (BPV is + qualified by -MEBEN). Each of the other three violations could occur with + MEBEN either asserted or denied. + + Consider a read from the base page with map 0 indicating read protection. + If the read is from the mapped portion, MEBEN will be asserted. If the + read is from the unmapped portion, MEBEN will be denied. In either case, a + read violation will be indicated. The same conditions pertain to a write + to the base page with map 0 indicating write protection, and to an + attempted privileged instruction execution from the base page. + + RESOLUTION: Modify "dms_upd_vr" (hp2100_cpu.c) to call a new "is_mapped" + routine to determine if an access is to unmapped memory. + + STATUS: Fixed in version 3.8-1. + + + +198. PROBLEM: JMP to a write-protected page fails to signal a DMS violation. + + VERSION: 3.8-0 + + OBSERVATION: The "21MX M-Series Computer Operating and Reference Manual" + states on page 4-2: + + Any attempt to write to a write-protected page will result in a write + violation and the memory will not be altered. In addition, if a page is + write-protected, a jump or jump indirect instruction to that page will + cause a write violation and the jump will not occur. + + The write violation for a JMP to a write-protected page does not occur. + + CAUSE: Coding error in "mp_dms_jmp". + + MEM write and base-page violations are checked when an MPCK micro-order is + executed. MPCK asserts the MPCND signal if the address is above the lower + bound of protected memory (0 for a JMP). MPCND is qualified with the + accessed page's write-protect bit for write violations, and with an + "unmapped access to the base page" signal for base-page violations. Any + instruction that executes MPCK will enable these two violation checks, and + all jump-type instructions do. + + Under simulation, the MEM check for base-page violations is done by the + "mp_dms_jmp" routine. However, this routine does not check for write + violations. + + RESOLUTION: Modify "mp_dms_jmp" (hp2100_cpu.c) to check for write + violations as well as base-page violations. + + STATUS: Fixed in version 3.8-1. + + + +199. PROBLEM: .GOTO to A/B causes incorrect MP violation. + + VERSION: 3.8-0 + + OBSERVATION: The lower bound of protected memory is normally location 2, + allowing unrestricted access to the A and B registers (locations 0 and 1, + respectively). The MP card checks the instruction register and uses a + lower bound of 0 for JMP, as well as for JSB if jumper W5 is out. The JLY + and JPY microcode also requests a lower bound of 0 by setting the IR to the + JMP opcode before the MP check. + + Under simulation, the MP check against a lower bound of 0 is done by the + "mp_dms_jmp" routine (hp2100_cpu.c). However, this routine is also called + for the DJP, SJP, UJP, JRS, and .GOTO instructions. These latter + instructions should allow access to the A/B registers, but they don't. + + CAUSE: Logic error. + + RESOLUTION: Modify "mp_dms_jmp" (hp2100_cpu.c) to accept the protected + lower bound as a parameter, and modify the JMP, JSB, JLY, JPY, DJP, SJP, + UJP, JRS, and .GOTO instruction handlers (hp2100_cpu.c, hp2100_cpu2.c, and + hp2100_cpu3.c) to pass the desired lower bound value. + + STATUS: Fixed in version 3.8-1. + + + +200. PROBLEM: UJP fails erroneously with a write-protect violation. + + VERSION: 3.8-0 + + OBSERVATION: Attempting to enable the user map with a UJP instruction + fails if the target page in the system map is write-protected. + + CAUSE: The instruction is checking the jump target in the wrong map. + + The DJP, SJP, and UJP instructions validate that the target address is not + below the MP fence and on a write-protected page. In firmware, these + instructions alter the Memory Expansion Unit before validating the jump + address. For example, UJP enables the user map and then checks the target + address using the user map. Under simulation, the "mp_dms_jmp" check is + issued before the map is changed, leading to failures. + + RESOLUTION: Modify "cpu_dms" (hp2100_cpu2.c) to move the "mp_dms_jmp" + checks to after the MEU update for the DJP, SJP, and UJP instructions. + + STATUS: Fixed in version 3.8-1. + + + +201. PROBLEM: Several HP 2100 devices use registers variables < 32 bits without + REG_FIT. + + VERSION: 3.8-0 + + OBSERVATION: Scalar register variables must be either 32 bits in size or + declared with the REG_FIT flag. In the absence of REG_FIT, a 32-bit access + is assumed by the examine and deposit routines. Several HP 2100 devices + use 8- or 16-bit scalar variables as registers without REG_FIT. This will + cause failures on big-endian machines. + + Note that arrayed registers are automatically accessed at the minimum size + implied by the "width" and "offset" values and therefore do not need + REG_FIT. + + CAUSE: Coding errors. + + RESOLUTION: Modify hp2100_baci.c, hp2100_dp.c, hp2100_dq.c, and + hp2100_mpx.c to add REG_FIT where needed. + + STATUS: Fixed in version 3.8-1. + + + +202. PROBLEM: The HP 2100 CPU simulation shadows the A and B registers + unnecessarily. + + VERSION: 3.8-0 + + OBSERVATION: The A and B register values are stored in two places: as + "uint16 ABREG[2]" duing execution, and as "uint32 saved_AR" and "uint32 + saved_BR" between executions. The latter was to accommodate the + requirement that register variables must be 32 bits in size. That + requirement was removed in version 3.5-2 for registers declared with the + REG_FIT flag. + + With REG_FIT, "ABREG[0]" and "ABREG[1]" can be used directly as register + values, and the code associated with saving and restoring the A and B + registers can be eliminated. + + CAUSE: The code wasn't updated to take advantage of the new feature. + + RESOLUTION: Modify hp2100_cpu.c to use "ABREG[]" variables as register + values with REG_FIT, and remove the "saved_AR" and "saved_BR" values and + associated code. Modify "msc_boot" (hp2100_ms.c) to use "AR" instead of + "saved_AR". + + STATUS: Fixed in version 3.8-1. + + + +203. PROBLEM: RTE break mode does not work with the 12920A multiplexer on fast + host machines. + + VERSION: 3.8-0 + + OBSERVATION: Hitting the BREAK key when the terminal is idle or output is + in progress should produce an RTE prompt. BREAK works properly when the + terminal is idle, but hitting BREAK when output is in progress does not + produce a prompt. This means that long outputs can be neither paused nor + aborted. + + CAUSE: The RTE multiplexer driver is a privileged driver. Privileged + drivers bypass RTE to provide rapid interrupt handling. To inform RTE that + an operation is complete, e.g., that a line has been written, the interrupt + section of the driver sets a device timeout of one clock tick (10 + milliseconds). When that timeout occurs, RTE is entered normally to + complete the I/O transaction. While the completion timeout is pending, the + driver ignores any further interrupts from the multiplexer line. + + The maximum communication rate for the multiplexer is 2400 baud, or + approximately 4.2 milliseconds per character transferred. A typical line + of 20 characters would therefore take ~85 milliseconds, plus the 10 + millisecond completion timeout, or about 95 milliseconds total. BREAK + recognition would be ignored for roughly 10% of that time. At lower baud + rates, recognition would be ignored for a correspondingly smaller + percentage of the time. + + However, SIMH uses an optimized timing of 500 instructions per character + transfer, rather than the ~6600 instructions that a character transfer + should take, and so a typical 20-character line will take about 11,000 + instructions. On the other hand, the clock tick is calibrated to real + time, and 10 milliseconds of real time takes about 420,000 instructions on + a 2.0 GHz PC. To be recognized, then, the BREAK key must be pressed in a + window that is open for about 2.5% of the time. Therefore, the BREAK key + will be ignored about 97.5% of the time, and RTE break-mode effectively + will not work. + + RESOLUTION: Defer BREAK recognition until either a character is output or + a second successive input poll occurs, providing that we are not in + diagnostic mode. This ensures that the BREAK interrupt will be accepted. + Added a "mux_defer[]" flag (hp2100_mux.c) to record break deferrals. + + STATUS: Fixed in version 3.8-1. + + + +204. ENHANCEMENT: Add line connection order support to the 12920A multiplexer. + + VERSION: 3.8-0 + + OBSERVATION: RTE and DOS provide per-line device drivers for the 12920A + multiplexer. A method of specifying line connection order is needed, so + that connection to specific device drivers is possible. + + RESOLUTION: Add "SET MUX LINEORDER=" and "SHOW MUX LINEORDER" + commands to the 12920A simulator. + + STATUS: Fixed in version 3.8-1. + + + +205. PROBLEM: The LOCKED, WRITEENABLED, and FORMAT commands do not work as + documented. + + VERSION: 3.8-0 + + OBSERVATION: The HP2100 documentation says that the "SET MTC LOCKED" + command write-locks the tape drive. Attempting this, however, results in a + "Non-existent parameter" error. + + CAUSE: The commands are part of the wrong command table (MTD instead of + MTC). + + RESOLUTION: Modify "mtd_mod" and "mtc_mod" (hp2100_mt.c) to move the + LOCKED, WRITEENABLED, and FORMAT commands to the command channel to be + compatible with the MS tape device. + + STATUS: Fixed in version 3.8-1. + + + +206. PROBLEM: Wrong mnemonic reported in IAK display for RTE-6/VM OS dual-use + microcode instructions. + + VERSION: 3.8-0 + + OBSERVATION: RTE-6/VM OS instructions have four "dual-use" opcodes. These + have different meanings, and thus different mnemonics, depending on whether + they are used in interrupt trap cells or not. For example, the 105357 + opcode is $TBG (time-base generator interrupt handler) if in a trap cell + and .DSPI (set display indicator) if not. The mnemonic is correct for the + EXAMINE command. A single-step through an interrupt acknowledgement + displays the wrong mnemonic: + + [CTRL+E] + + Simulation stopped, P: 02040 (JMP 2037) + sim> s + + Step expired, P: 02037 (IAK 15: .DSPI) + sim> e -m 15 + 15: $TBG + + The IAK report should also display $TBG. + + CAUSE: The "fprint_sym" routine detects the IAK and obtains the trap cell + value, but it fails to change the instruction address, so the address + remains that of the interrupted instruction. As dual-use mnemonics depend + on the instruction address, the mnemonic reported is incorrect. + + RESOLUTION: Modify "fprint_sym" (hp2100_sys.c) to set the instruction + address for an interrupt acknowledgement to the interrupt trap cell + address. + + STATUS: Fixed in version 3.8-1. + + + +207. PROBLEM: The 3030 mag tape does not interrupt after a CLR command. + + VERSION: 3.8-0 + + OBSERVATION: Page 2-6 of the 12559A 9-Track Magnetic Tape Unit Interface + Kit Operating and Service Manual says that the CLR command channel flag + flip-flop when the command completes. The MT simulator does not, so the + command channel does not interrupt. + + CAUSE: Coding error. + + RESOLUTION: Modify "mtcio" (hp2100_mt.c) to set the command channel flag + when the command completes. + + STATUS: Fixed in version 3.8-1. + + + +208. PROBLEM: Exiting the simulator does not report "Disconnected from the HP + 2100 simulator" on MUX sessions. + + VERSION: 3.8-0 + + OBSERVATION: Exiting the simulator detaches all devices. Detaching + multiplexer-type devices, such as BACI and MPX, reports "Disconnected from + the simulator" on each connected Telnet session. However, no such + report appears on MUX sessions. Doing a DETACH ALL does report the + disconnection on MUX sessions. + + CAUSE: As part of simulator shutdown, "detach_all" is called with the + "shutdown" parameter set to TRUE. This causes the detach routines for + non-attachable units to be called. "ds_detach" calls "detach_unit", which + returns SCPE_NOATT for unit 8 (the controller unit). "detach_all" exits on + a non-zero status return from a device detach routine, so the devices after + DS in the device array are never detached. + + Doing a DETACH ALL calls "detach_all" with the "shutdown" parameter set to + FALSE. This calls device detach routines only for attached units. All of + these return SCPE_OK, so MUX is eventually detached, and the disconnection + reports are sent to the MUX sessions. + + Note that the same problem would arise if an attached unit fails to detach + cleanly, e.g., due to a file write error. The remaining devices would not + be detached before simulator exit. + + RESOLUTION: Modify "detach_all" (scp.c) to ignore errors from device + detach routines during shutdown, so that all devices will be detached. + + STATUS: Fixed in version 3.8-1. + + + +209. ENHANCEMENT: Add a microcode simulation module for site-specific + microprograms. + + VERSION: 3.8-0 + + OBSERVATION: The 2100 and 1000 CPUs supported user microprogramming. A + user of the HP2100 simulator may have user-written microcode that he would + like to add to SIMH. It would be helpful to have the infrastructure in + place to aid in the implementation of site-specific microprogram + simulations. + + RESOLUTION: Add a new "cpu_user" microcode dispatcher and an example + skeleton microcode simulator (hp2100_cpu0.c). Alter "cpu_uig_0" and + "cpu_uig_1" (hp2100_cpu1.c) to route any instruction not allocated to an + installed firmware option to the user-microcode dispatcher. In the absence + of a user-microcode simulation for a given instruction, execution will + cause an undefined instruction stop. + + STATUS: Fixed in version 3.8-1. + + + +210. PROBLEM: The VIS and IOP options conflict on the 1000-F. + + VERSION: 3.8-0 + + OBSERVATION: The Vector Instruction Set and 2000/Access I/O Processor + instructions share the same opcode range. Only one or the other should be + present at a time. The SET CPU option processor does not enforce this. + + CAUSE: The case was overlooked when VIS was added. + + RESOLUTION: Modify "cpu_set_opt" (hp2100_cpu.c) to make the VIS and IOP + options mutually exclusive on the 1000-F. + + STATUS: Fixed in version 3.8-1. + + + +211. PROBLEM: Pressing BREAK on a BACI terminal under RTE locks the card. + + VERSION: 3.8-0 + + OBSERVATION: Under RTE, pressing the BREAK key on a BACI terminal session + will cause that session to lock up. If the session was writing, it will + resume in four seconds. If it was reading or idle, it will re-enable after + the timeout period specified for the device in RTE. If no timeout was + specified, then the session will remain locked forever. + + CAUSE: The RTE driver operates the BACI in character mode. Normally, + pressing a key while the session is writing or idle will bring up the RTE + system prompt. + + Pressing BREAK enters a NUL into the FIFO and interrupts with the BREAK + CONDITION bit set in the status word. The driver ignores this by sending a + "reset break status" command and then re-enabling interrupts with an STC + sc,C instruction. But the original interrupt was caused not by the BREAK + status (there is no explicit interrupt-on-BREAK function) but rather by the + presence of a received character in the FIFO. So the BACI attempts to + interrupt again, this time with the BREAK CONDITION bit clear. + + This second interrupt would normally be allowed, as the STC sc,C + instruction clears the "interrupt lockout" flag that was set when the first + interupt was generated. However, the STC signal handler checks for + interrupt status between the STC and the succeeding CLF, rather than after + the CLF. The result is that the STC clears lockout, then the FIFO status + sets the flag and lockout, and then the CLF clears the flag, leaving + interrupt lockout set. At that point, no interrupt is pending, and no + future interrupts can occur, because the lockout flag prevents them. + + When device timeout occurs, the card is reinitialized and then re-enabled, + so it becomes responsive again. + + RESOLUTION: Modify "baci_io" (hp2100_baci.c) to update the interrupt + status after the CLF of a STC sc,C instruction. + + STATUS: Fixed in version 3.8-1. + + + +212. PROBLEM: Setting a breakpoint on an interrupt trap cell does not work. + + VERSION: 3.8-0 + + OBSERVATION: If a breakpoint is set on an interrupt trap cell, the + breakpoint does not trip when the corresponding interrupt occurs and the + trap cell contents are executed. + + CAUSE: The breakpoint detection code is only in the "normal instruction" + execution path. + + RESOLUTION: Modify "sim_instr" (hp2100_cpu.c) to add breakpoint detection + to the "interrupt trap cell" execution path. + + STATUS: Fixed in version 3.8-1. diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c index 9c139043..8a20b98e 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -1,4 +1,4 @@ -/* hp2100_cpu.c: HP 21xx CPU simulator +/* hp2100_cpu.c: HP 21xx/1000 CPU simulator Copyright (c) 1993-2008, Robert M. Supnik @@ -24,11 +24,26 @@ in this Software without prior written authorization from Robert M Supnik. CPU 2114C/2115A/2116C/2100A/1000-M/E/F central processing unit + 12731A memory expansion module MP 12581A/12892B memory protect DMA0,DMA1 12607B/12578A/12895A direct memory access controller DCPC0,DCPC1 12897B dual channel port controller + 30-Sep-08 JDB Breakpoints on interrupt trap cells now work + 05-Sep-08 JDB VIS and IOP are now mutually exclusive on 1000-F + 11-Aug-08 JDB Removed A/B shadow register variables + 07-Aug-08 JDB Moved hp_setdev, hp_showdev to hp2100_sys.c + Moved non-existent memory checks to WritePW + 05-Aug-08 JDB Fixed mp_dms_jmp to accept lower bound, check write protection + 30-Jul-08 JDB Corrected DMS violation register set conditions + Refefined ABORT to pass address, moved def to hp2100_cpu.h + Combined dms and dms_io routines + 29-Jul-08 JDB JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort + 11-Jul-08 JDB Unified I/O slot dispatch by adding DIBs for CPU, MP, and DMA + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + EDT no longer passes DMA channel 30-Apr-08 JDB Enabled SIGNAL instructions, SIG debug flag + 28-Apr-08 JDB Added SET CPU IDLE/NOIDLE, idle detection for DOS/RTE 24-Apr-08 JDB Fixed single stepping through interrupts 20-Apr-08 JDB Enabled EMA and VIS, added EMA, VIS, and SIGNAL debug flags 03-Dec-07 JDB Memory ex/dep and bkpt type default to current map mode @@ -80,7 +95,7 @@ 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 + 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 @@ -134,18 +149,21 @@ (5955-0282, Mar-1980) - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation (92851-90001, Mar-1981) + - HP 1000 M/E/F-Series Computers I/O Interfacing Guide + (02109-90006, Sep-1980) - 12607A Direct Memory Access Operating and Service Manual (12607-90002, Jan-1970) - 12578A/12578A-01 Direct Memory Access Operating and Service Manual (12578-9001, Mar-1972) - 12892B Memory Protect Installation Manual (12892-90007, Jun-1978) + 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 + PC<14:0> P register - program counter + SR<15:0> S register - switch register MR<14:0> M register - memory address TR<15:0> T register - memory data E extend flag (carry out) @@ -306,11 +324,6 @@ |in| operand address | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - This routine is the instruction decode routine for the HP 2100. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - General notes: 1. Reasons to stop. The simulator can be stopped by: @@ -322,28 +335,46 @@ 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: + 2. Interrupts. I/O devices are modelled by substituting software states for + I/O backplane signals. Signals generated by I/O instructions and DMA + cycles are dispatched to the target device for action. Backplane signals + are processed sequentially, except for the "clear flag" signal, which may + be generated in parallel with another signal. For example, the "STC sc,C" + instruction generates the "set control" and the "clear flag" signals + concurrently. - 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] + CPU interrupt signals are modelled as three parallel arrays: - The HP 2100 interrupt structure is based on flag, flag buffer, - and control. If a device flag is set, the flag buffer is set, - the control bit is set, and the device is the highest priority - on the interrupt chain, it requests an interrupt. When the - interrupt is acknowledged, the flag buffer is cleared, preventing - further interrupt requests from that device. The combination of - flag and control set blocks interrupts from lower priority devices. + - device request priority as bit vector dev_prl [2] [31..0] + - device interrupt requests as bit vector dev_irq [2] [31..0] + - device service requests as bit vector dev_srq [2] [31..0] - Command plays no direct role in interrupts. The command flop - tells whether a device is active. It is set by STC and cleared - by CLC; it is also cleared when the device flag is set. Simple - devices don't need to track command separately from control. + Each array forms a 64-bit vector, with bits 0-31 of the first element + corresponding to select codes 00-37 octal, and bits 0-31 of the second + element corresponding to select codes 40-77 octal. - Service requests are used to trigger the DMA service logic. + The HP 2100 interrupt structure is based on the PRH, PRL, IRQ, and IAK + signals. PRH indicates that no higher-priority device is interrupting. + PRL indicates to lower-priority devices that a given device is not + interrupting. IRQ indicates that a given device is requesting an + interrupt. IAK indicates that the given device's interrupt request is + being acknowledged. + + PRH and PRL form a hardware priority chain that extends from interface to + interface on the backplane. We model just PRL, as PRH is calculated from + the PRLs of higher-priority devices. + + Typical I/O devices have a flag, flag buffer, and control flip-flop. If a + device's flag, flag buffer, and control bits are set, and the device is + the highest priority on the interrupt chain, it requests an interrupt by + asserting IRQ. When the interrupt is acknowledged with IAK, the flag + buffer is cleared, preventing further interrupt requests from that device. + The combination of flag and control set blocks interrupts from lower + priority devices. + + Service requests are used to trigger the DMA service logic. Setting the + device flag typically also sets SRQ, although SRQ may be calculated + independently. 3. Non-existent memory. On the HP 2100, reads to non-existent memory return zero, and writes are ignored. In the simulator, the @@ -379,12 +410,27 @@ current instruction is an MRG instruction other than JMP or JMP,I or JSB,I. Note that for the 21xx, SFS and SFC are not included in the deferral criteria. + + 7. Terminology. The 1000 series of computers was originally called the 21MX + at introduction. The 21MX (occasionally, 21MXM) corresponds to the 1000 + M-Series, and the 21MXE (occasionally, 21XE) corresponds to the 1000 + E-Series. The model numbers were changed before the introduction of the + 1000 F-Series, although some internal HP documentation refers to a 21MXF. + + The terms MEM (Memory Expansion Module), MEU (Memory Expansion Unit), DMI + (Dynamic Mapping Instructions), and DMS (Dynamic Mapping System) are used + somewhat interchangeably to refer to the logical-to-physical memory + address translation option provided on the 1000-Series. DMS consists of + the MEM card (12731A) and the DMI firmware (13307A). However, MEM and MEU + have been used interchangeably to refer to the mapping card, as have DMI + and DMS to refer to the firmware instructions. */ + #include "hp2100_defs.h" -#include #include "hp2100_cpu.h" + /* Memory protect constants */ #define UNIT_V_MP_JSB (UNIT_V_UF + 0) /* MP jumper W5 */ @@ -394,55 +440,164 @@ #define UNIT_MP_INT (1 << UNIT_V_MP_INT) /* 1 = W6 is out */ #define UNIT_MP_SEL1 (1 << UNIT_V_MP_SEL1) /* 1 = W7 is out */ -#define ABORT(val) longjmp (save_env, (val)) +/* DMA channels */ + +#define DMA_OE 020000000000 /* byte packing odd/even flag */ +#define DMA1_STC 0100000 /* DMA - issue STC */ +#define DMA1_PB 0040000 /* DMA - pack bytes */ +#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 */ + uint32 latency; /* 1st cycle delay */ + uint32 packer; /* byte-packer holding reg */ + }; #define DMAR0 1 #define DMAR1 2 + +/* Command line switches */ + #define ALL_BKPTS (SWMASK('E')|SWMASK('N')|SWMASK('S')|SWMASK('U')) #define ALL_MAPMODES (SWMASK('S')|SWMASK('U')|SWMASK('P')|SWMASK('Q')) + +/* RTE base-page addresses. */ + +static const uint32 xeqt = 0001717; /* XEQT address */ +static const uint32 tbg = 0001674; /* TBG address */ + +/* DOS base-page addresses. */ + +static const uint32 m64 = 0000040; /* constant -64 address */ +static const uint32 p64 = 0000067; /* constant +64 address */ + +/* CPU local data */ + +static uint32 jsb_plb = 2; /* protected lower bound for JSB */ +static uint32 saved_MR = 0; /* between executions */ +static uint32 fwanxm = 0; /* first word addr of nx mem */ + +/* CPU global data */ + uint16 *M = NULL; /* memory */ -uint32 saved_AR = 0; /* A register */ -uint32 saved_BR = 0; /* B register */ -uint16 ABREG[2]; /* during execution */ +uint16 ABREG[2]; /* A/B registers */ uint32 PC = 0; /* P register */ uint32 SR = 0; /* S register */ uint32 MR = 0; /* M register */ -uint32 saved_MR = 0; /* between executions */ 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 */ +FLIP_FLOP ion = CLEAR; /* interrupt enable */ +t_bool ion_defer = FALSE; /* 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 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 */ + +uint32 dev_prl [2] = { ~(uint32) 0, ~(uint32) 0 }; /* device priority low bit vector */ +uint32 dev_irq [2] = { 0, 0 }; /* device interrupt request bit vector */ +uint32 dev_srq [2] = { 0, 0 }; /* device service request bit vector */ + +/* Memory protect global data */ + +FLIP_FLOP mp_control = CLEAR; /* MP control flip-flop */ +FLIP_FLOP mp_flag = CLEAR; /* MP flag flip-flop */ +FLIP_FLOP mp_flagbuf = CLEAR; /* MP flag buffer flip-flop */ +FLIP_FLOP mp_mevff = CLEAR; /* memory expansion violation flip-flop */ +FLIP_FLOP mp_evrff = SET; /* enable violation register flip-flop */ + +uint32 mp_fence = 0; /* MP fence register */ +uint32 mp_viol = 0; /* MP violation register */ + +uint32 iop_sp = 0; /* iop stack reg */ +uint32 ind_max = 16; /* iadr nest limit */ uint32 err_PC = 0; /* error PC */ +jmp_buf save_env; /* MP abort handler */ + +/* DMA global data */ + +struct DMA dmac[2] = { { 0 }, { 0 } }; /* DMA channels */ +FLIP_FLOP dma_xferen [2] = { CLEAR, CLEAR }; /* transfer enable flip-flops */ +FLIP_FLOP dma_control [2] = { CLEAR, CLEAR }; /* control flip-flops */ +FLIP_FLOP dma_flag [2] = { CLEAR, CLEAR }; /* flag flip-flops */ +FLIP_FLOP dma_flagbuf [2] = { CLEAR, CLEAR }; /* flag buffer flip-flops */ +FLIP_FLOP dma_select [2] = { CLEAR, CLEAR }; /* register select flip-flops */ + +/* Dynamic mapping system global data */ + 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 */ -uint32 fwanxm = 0; /* first word addr of nx mem */ -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 */ + +/* External data */ + +extern int32 sim_interval; +extern int32 sim_int_char; +extern int32 sim_brk_char; +extern int32 sim_del_char; +extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern DEVICE *sim_devices[]; +extern char halt_msg[]; +extern t_bool sim_idle_enab; +extern DIB clk_dib; /* CLK DIB for idle check */ + +/* CPU local routines */ + +static t_stat Ea (uint32 IR, uint32 *addr, uint32 irq); +static uint16 ReadTAB (uint32 va); +static uint32 dms (uint32 va, uint32 map, uint32 prot); +static uint32 shift (uint32 inval, uint32 flag, uint32 oper); +static void dma_cycle (uint32 chan, uint32 map); +static uint32 calc_dma (void); +static t_bool dev_conflict (void); +static uint32 devdisp (uint32 select_code, IOSIG signal, uint32 data); + +/* CPU global routines */ + +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_reset (DEVICE *dptr); +t_stat cpu_boot (int32 unitno, DEVICE *dptr); +t_stat mp_reset (DEVICE *dptr); +t_stat dma0_reset (DEVICE *dptr); +t_stat dma1_reset (DEVICE *dptr); +t_stat cpu_set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc); +t_stat cpu_set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc); +t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat cpu_set_opt (UNIT *uptr, int32 option, char *cptr, void *desc); +t_stat cpu_clr_opt (UNIT *uptr, int32 option, char *cptr, void *desc); +t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc); +t_stat cpu_set_idle (UNIT *uptr, int32 option, char *cptr, void *desc); +t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc); +void hp_post_cmd (t_bool from_scp); + +uint32 cpuio (uint32 select_code, IOSIG signal, uint32 data); +uint32 ovflio (uint32 select_code, IOSIG signal, uint32 data); +uint32 pwrfio (uint32 select_code, IOSIG signal, uint32 data); +uint32 protio (uint32 select_code, IOSIG signal, uint32 data); +uint32 dmasio (uint32 select_code, IOSIG signal, uint32 data); +uint32 dmapio (uint32 select_code, IOSIG signal, uint32 data); +uint32 nullio (uint32 select_code, IOSIG signal, uint32 data); + +/* External routines */ + +extern t_stat cpu_eau (uint32 IR, uint32 intrq); +extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); +extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); + +extern void (*sim_vm_post) (t_bool from_scp); + /* Table of CPU features by model. @@ -496,49 +651,6 @@ static struct FEATURE_TABLE cpu_features[] = { /* features in UNIT_xxxx 1048576 } }; -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_char; -extern int32 sim_del_char; -extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; -extern DEVICE *sim_devices[]; -extern int32 sim_switches; -extern char halt_msg[]; - -t_stat Ea (uint32 IR, uint32 *addr, uint32 irq); -uint16 ReadIO (uint32 addr, uint32 map); -uint16 ReadPW (uint32 addr); -uint16 ReadTAB (uint32 addr); -void WriteIO (uint32 addr, uint32 dat, uint32 map); -void WritePW (uint32 addr, uint32 dat); -uint32 dms (uint32 va, uint32 map, uint32 prot); -uint32 dms_io (uint32 va, uint32 map); -uint32 shift (uint32 inval, uint32 flag, uint32 oper); -void dma_cycle (uint32 chan, uint32 map); -uint32 calc_dma (void); -uint32 calc_int (void); -uint32 calc_defer (void); -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_boot (int32 unitno, DEVICE *dptr); -t_stat mp_reset (DEVICE *dptr); -t_stat dma0_reset (DEVICE *dptr); -t_stat dma1_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc); -t_stat cpu_set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc); -t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat cpu_set_opt (UNIT *uptr, int32 option, char *cptr, void *desc); -t_stat cpu_clr_opt (UNIT *uptr, int32 option, char *cptr, void *desc); -t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc); -t_bool dev_conflict (void); -void hp_post_cmd (t_bool from_scp); - -extern t_stat cpu_eau (uint32 IR, uint32 intrq); -extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); -extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); -extern void (*sim_vm_post) (t_bool from_scp); /* CPU data structures @@ -553,8 +665,8 @@ UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, 0) }; REG cpu_reg[] = { { ORDATA (P, PC, 15) }, - { ORDATA (A, saved_AR, 16) }, - { ORDATA (B, saved_BR, 16) }, + { ORDATA (A, AR, 16), REG_FIT }, + { ORDATA (B, BR, 16), REG_FIT }, { ORDATA (M, MR, 15) }, { ORDATA (T, TR, 16), REG_RO }, { ORDATA (X, XR, 16) }, @@ -574,22 +686,17 @@ REG cpu_reg[] = { { FLDATA (STOP_INST, stop_inst, 0) }, { FLDATA (STOP_DEV, stop_dev, 1) }, { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { ORDATA (FWANXM, fwanxm, 32), REG_HRO }, { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC }, { ORDATA (PCQP, pcq_p, 6), REG_HRO }, + { ORDATA (JSBPLB, jsb_plb, 32), REG_HRO }, + { ORDATA (SAVEDMR, saved_MR, 32), REG_HRO }, + { ORDATA (FWANXM, fwanxm, 32), 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 }, + { BRDATA (PRL, dev_prl, 8, 32, 2), REG_HRO }, + { BRDATA (IRQ, dev_irq, 8, 32, 2), REG_HRO }, + { BRDATA (SRQ, dev_srq, 8, 32, 2), REG_HRO }, { NULL } }; @@ -613,6 +720,9 @@ MTAB cpu_mod[] = { { UNIT_MODEL_MASK, UNIT_1000_F, "", "1000-F", &cpu_set_model, &cpu_show_model, "1000-F" }, #endif + { MTAB_XTD | MTAB_VDV, 1, "IDLE", "IDLE", &cpu_set_idle, &cpu_show_idle, NULL }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "NOIDLE", &cpu_set_idle, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "LOADERENABLE", &cpu_set_ldr, NULL, NULL }, { MTAB_XTD | MTAB_VDV, 0, NULL, "LOADERDISABLE", &cpu_set_ldr, NULL, NULL }, @@ -689,32 +799,50 @@ DEBTAB cpu_deb[] = { }; 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, - NULL, DEV_DEBUG, - 0, cpu_deb, NULL, NULL - }; + "CPU", /* device name */ + &cpu_unit, /* unit array */ + cpu_reg, /* register array */ + cpu_mod, /* modifier array */ + 1, /* number of units */ + 8, /* address radix */ + PA_N_SIZE, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 16, /* data width */ + &cpu_ex, /* examine routine */ + &cpu_dep, /* deposit routine */ + &cpu_reset, /* reset routine */ + &cpu_boot, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + NULL, /* device information block */ + DEV_DEBUG, /* device flags */ + 0, /* debug control flags */ + cpu_deb, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ /* Memory protect data structures + mp_dib MP device information block mp_dev MP device descriptor mp_unit MP unit descriptor mp_reg MP register list mp_mod MP modifiers list */ +DIB mp_dib = { PRO, &protio }; + UNIT mp_unit = { UDATA (NULL, UNIT_MP_SEL1, 0) }; /* default is JSB in, INT in, SEL1 out */ 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)) }, + { FLDATA (CTL, mp_control, 0) }, + { FLDATA (FLG, mp_flag, 0) }, + { FLDATA (FBF, mp_flagbuf, 0) }, { ORDATA (FR, mp_fence, 15) }, { ORDATA (VR, mp_viol, 16) }, - { FLDATA (MEV, mp_mevff, 0) }, { FLDATA (EVR, mp_evrff, 0) }, + { FLDATA (MEV, mp_mevff, 0) }, { NULL } }; @@ -729,27 +857,46 @@ MTAB mp_mod[] = { }; 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", /* device name */ + &mp_unit, /* unit array */ + mp_reg, /* register array */ + mp_mod, /* modifier array */ + 1, /* number of units */ + 8, /* address radix */ + 1, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 16, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &mp_reset, /* reset routine */ + NULL, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + &mp_dib, /* device information block */ + DEV_DISABLE | DEV_DIS, /* device flags */ + 0, /* debug control flags */ + NULL, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ /* DMA controller data structures + dmax_dib DMAx device information block dmax_dev DMAx device descriptor dmax_reg DMAx register list */ +DIB dma0_dib = { DMA0, &dmapio }; + 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)) }, + { FLDATA (XFR, dma_xferen [0], 0) }, + { FLDATA (CTL, dma_control [0], 0) }, + { FLDATA (FLG, dma_flag [0], 0) }, + { FLDATA (FBF, dma_flagbuf [0], 0) }, + { FLDATA (CTL2, dma_select [0], 0) }, { ORDATA (CW1, dmac[0].cw1, 16) }, { ORDATA (CW2, dmac[0].cw2, 16) }, { ORDATA (CW3, dmac[0].cw3, 16) }, @@ -760,21 +907,39 @@ REG dma0_reg[] = { }; 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", /* device name */ + &dma0_unit, /* unit array */ + dma0_reg, /* register array */ + NULL, /* modifier array */ + 1, /* number of units */ + 8, /* address radix */ + 1, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 16, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &dma0_reset, /* reset routine */ + NULL, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + &dma0_dib, /* device information block */ + DEV_DISABLE, /* device flags */ + 0, /* debug control flags */ + NULL, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ + +DIB dma1_dib = { DMA1, &dmapio }; 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)) }, + { FLDATA (XFR, dma_xferen [1], 0) }, + { FLDATA (CTL, dma_control [1], 0) }, + { FLDATA (FLG, dma_flag [1], 0) }, + { FLDATA (FBF, dma_flagbuf [1], 0) }, + { FLDATA (CTL3, dma_select [1], 0) }, { ORDATA (CW1, dmac[1].cw1, 16) }, { ORDATA (CW2, dmac[1].cw2, 16) }, { ORDATA (CW3, dmac[1].cw3, 16) }, @@ -785,45 +950,53 @@ REG dma1_reg[] = { }; 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", /* device name */ + &dma1_unit, /* unit array */ + dma1_reg, /* register array */ + NULL, /* modifier array */ + 1, /* number of units */ + 8, /* address radix */ + 1, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 16, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &dma1_reset, /* reset routine */ + NULL, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + &dma1_dib, /* device information block */ + DEV_DISABLE, /* device flags */ + 0, /* debug control flags */ + NULL, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ -/* Interrupt defer table (1000 version) */ -static int32 defer_tab[] = { 0, 1, 1, 1, 0, 0, 0, 1 }; +/* Interrupt deferral table (1000 version) */ +/* Deferral for I/O subops: soHLT, soFLG, soSFC, soSFS, soMIX, soLIX, soOTX, soCTL */ +static t_bool defer_tab [] = { FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE }; /* Device dispatch table */ -uint32 devdisp (uint32 devno, uint32 inst, uint32 IR, uint32 outdat); -int32 cpuio (int32 op, int32 IR, int32 outdat); -int32 ovfio (int32 op, int32 IR, int32 outdat); -int32 pwrio (int32 op, int32 IR, int32 outdat); -int32 proio (int32 op, int32 IR, int32 outdat); -int32 dmsio (int32 op, int32 IR, int32 outdat); -int32 dmpio (int32 op, int32 IR, int32 outdat); -int32 nulio (int32 op, int32 IR, int32 outdat); +IODISP *dtab[64] = { &cpuio, &ovflio }; /* init with immutable devices */ -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 - }; + +/* Execute CPU instructions. + + 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. +*/ 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 */ +int32 i; /* temp */ DEVICE *dptr; /* temp */ DIB *dibp; /* temp */ int abortval; @@ -831,128 +1004,192 @@ int abortval; /* Restore register state */ if (dev_conflict ()) return SCPE_STOP; /* check consistency */ -AR = saved_AR & DMASK; /* restore reg */ -BR = saved_BR & DMASK; err_PC = PC = PC & VAMASK; /* load local PC */ reason = 0; /* Restore I/O state */ -if (mp_dev.flags & DEV_DIS) dtab[PRO] = NULL; -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; - } -if (dma1_dev.flags & DEV_DIS) dtab[DMA1] = dtab[DMALT1] = NULL; -else { - dtab[DMA1] = &dmpio; /* set up DMA1 dispatch */ - dtab[DMALT1] = &dmsio; - } +dev_prl [0] = dev_prl [1] = ~(uint32) 0; /* set all priority lows */ +dev_irq [0] = dev_irq [1] = 0; /* clear all interrupt requests */ +dev_srq [0] = dev_srq [1] = 0; /* clear all service requests */ -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_cmd[1] = dev_ctl[1] = dev_flg[1] = dev_fbf[1] = 0; -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ +for (i = OPTDEV; i <= I_DEVMASK; i++) /* default optional devices dispatch */ + dtab [i] = &nullio; + +dtab [PWR] = &pwrfio; /* for now, powerfail is always present */ + +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 */ + dtab [dibp->devno] = dibp->iot; /* set I/O signal dispatch */ + dtab [dibp->devno] (dibp->devno, ioSIR, 0); /* set interrupt request state */ } } +if (dtab [DMA0] == &dmapio) /* first DMA channel enabled? */ + dtab [DMALT0] = &dmasio; /* set up secondary handler */ + +if (dtab [DMA1] == &dmapio) /* second DMA channel enabled? */ + dtab [DMALT1] = &dmasio; /* set up secondary handler */ + /* Configure interrupt deferral table */ if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) /* 21xx series? */ - defer_tab[ioSFC] = defer_tab[ioSFS] = 0; /* SFC/S doesn't defer */ + defer_tab [soSFC] = defer_tab [soSFS] = FALSE; /* SFC/S doesn't defer */ else /* 1000 series */ - defer_tab[ioSFC] = defer_tab[ioSFS] = 1; /* SFC/S does defer */ + defer_tab [soSFC] = defer_tab [soSFS] = TRUE; /* SFC/S does defer */ -/* Abort handling - If an abort occurs in memory protection, the relocation routine - executes a longjmp to this area OUTSIDE the main simulation loop. - Memory protection errors are the only sources of aborts in the - HP 2100. All referenced variables must be globals, and all sim_instr - scoped automatics must be set after the setjmp. +/* Set MP abort handling. + + If an abort occurs in memory protection, the relocation routine executes a + longjmp to this area OUTSIDE the main simulation loop. Memory protection + errors are the only sources of aborts in the HP 2100. All referenced + variables must be globals, and all sim_instr scoped automatics must be set + after the setjmp. + + To initiate an MP abort, use the MP_ABORT macro and pass the violation + address. MP_ABORT should only be called if "mp_control" is SET, as aborts do + not occur if MP is turned off. + + An MP interrupt (SC 05) is qualified by "ion" but not by "ion_defer". If the + interrupt system is off when an MP violation is detected, the violating + instruction will be aborted, even though no interrupt occurs. In this case, + neither the flag nor flag buffer are set, and EVR is not cleared. + + Implementation notes: + + 1. The protected lower bound address for the JSB instruction depends on the + W5 jumper setting. If W5 is in, then the lower bound is 2, allowing JSBs + to the A and B registers. If W5 is out, then the lower bound is 0, just + as with JMP. + + 2. The violation address is passed to enable the MEM violation register to + be updated. The "longjmp" routine will not pass a value of 0; it is + converted internally to 1. This is OK, because only the page number + of the address value is used, and locations 0 and 1 are both on page 0. + + 3. This routine is used both for MP and MEM violations. The MEV flip-flop + will be clear for the former and set for the latter. The MEV violation + register will be updated by "dms_upd_vr" only if the call is NOT for an + MEM violation; if it is, then the VR has already been set and should not + be disturbed. */ +jsb_plb = (mp_unit.flags & UNIT_MP_JSB) ? 0 : 2; /* set protected lower bound for JSB */ + abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval != 0) { /* mem mgt abort? */ - setFLG (PRO); /* req interrupt */ - mp_evrff = 0; /* block mp_viol upd */ + +if (abortval) { /* memory protect abort? */ + dms_upd_vr (abortval); /* update violation register (if not MEV) */ + + if (ion) /* interrupt system on? */ + protio (PRO, ioENF, 0); /* set flag */ } -dmarq = calc_dma (); /* recalc DMA masks */ -intrq = calc_int (); /* recalc interrupts */ + +dmarq = calc_dma (); /* initial recalc of DMA masks */ +intrq = calc_int (); /* initial recalc of interrupts */ + /* Main instruction fetch/decode loop */ 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; + if (sim_interval <= 0) { /* event timeout? */ + if (reason = sim_process_event ()) /* process event service */ + break; /* service status not OK */ + 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 */ + if (dmarq & DMAR0) /* DMA channel 1 request? */ + dma_cycle (0, PAMAP); /* do one DMA cycle using port A map */ + + if (dmarq & DMAR1) /* DMA channel 2 request? */ + dma_cycle (1, PBMAP); /* do one DMA cycle using port B map */ + + dmarq = calc_dma (); /* recalc DMA requests */ intrq = calc_int (); /* recalc interrupts */ } if (intrq && ion_defer) /* interrupt pending but deferred? */ ion_defer = calc_defer (); /* confirm deferral */ - -/* (From Dave Bryan) - Unlike most other I/O devices, the MP flag flip-flop is cleared - automatically when the interrupt is acknowledged and not by a programmed - instruction (CLF and STF affect the parity error enable FF instead). - Section 4.4.3 "Memory Protect and I/O Interrupt Generation" of the "HP 1000 - M/E/F-Series Computers Engineering and Reference Documentation" (HP - 92851-90001) says: - "When IAK occurs and IRQ5 is asserted, the FLAGBFF is cleared, FLAGFF - clocked off at next T2, and IRQ5 will no longer occur." +/* Check for pending interrupt request. + + Interrupt recognition is controlled by three state variables: "ion", + "ion_defer", and "intrq". "ion" corresponds to the INTSYS flip-flop in the + 1000 CPU, "ion_defer" corresponds to the INTEN flip-flop, and "intrq" + corresponds to the NRMINT flip-flop. STF 00 and CLF 00 set and clear INTSYS, + turning the interrupt system on and off. Micro-orders ION and IOFF set and + clear INTEN, deferring or allowing certain interrupts. An IRQ signal from a + device, qualified by the corresponding PRL signal, will set NRMINT to request + a normal interrupt; an IOFF or IAK will clear it. + + Under simulation, "ion" is controlled by STF/CLF 00. "ion_defer" is set or + cleared as appropriate by the individual instruction simulators. "intrq" is + set to the successfully interrupting device's select code, or to zero if + there is no qualifying interrupt request. + + Presuming PRL is set to allow priority to an interrupting device: + + 1. Power fail (SC 04) may interrupt if "ion_defer" is clear; this is not + conditional on "ion" being set. + + 2. Memory protect (SC 05) may interrupt if "ion" is set; this is not + conditional on "ion_defer" being clear. + + 3. Parity error (SC 05) may interrupt always; this is not conditional on + "ion" being set or "ion_defer" being clear. + + 4. All other devices (SC 06 and up) may interrupt if "ion" is set and + "ion_defer" is clear. + + Qualification with "ion" is performed by "calc_int", except for case 2, which + is qualified by the MP abort handler above (because qualification occurs on + the MP card, rather than in the CPU). Therefore, we need only qualify by + "ion_defer" here. */ - 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 */ + if (intrq && ((intrq == PRO) || !ion_defer)) { /* interrupt request? */ + if (sim_brk_summ && /* any breakpoints? */ + sim_brk_test (intrq, SWMASK ('E') | /* unconditional or right type for DMS? */ + (dms_enb ? SWMASK ('S') : SWMASK ('N')))) { + reason = STOP_IBKPT; /* stop simulation */ + break; } - else dms_sr = dms_sr & ~MST_UMPI; - IR = ReadW (intrq); /* get dispatch instr */ - ion_defer = 1; /* defer interrupts */ + + intaddr = intrq; /* save int addr in CIR */ 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 /* I/O instr leaves MP on */ - mp_mevff = 0; /* but clears MEV flip-flop */ + ion_defer = TRUE; /* defer interrupts */ + iotrap = 1; /* mark as I/O trap cell instr */ + + if (dms_enb) /* dms enabled? */ + dms_sr = dms_sr | MST_ENBI; /* set in status */ + else /* not enabled */ + dms_sr = dms_sr & ~MST_ENBI; /* clear in status */ + + if (dms_ump) { /* user map enabled at interrupt? */ + dms_sr = dms_sr | MST_UMPI; /* set in status */ + dms_ump = SMAP; /* switch to system map */ + } + else /* system map enabled at interrupt */ + dms_sr = dms_sr & ~MST_UMPI; /* clear in status */ + + IR = ReadW (intaddr); /* get trap cell instruction */ + + devdisp (intaddr, ioIAK, IR); /* acknowledge interrupt */ + + if (intaddr != PRO) /* not MP interrupt? */ + protio (intaddr, ioIAK, IR); /* send IAK for device to MP too */ } else { /* normal instruction */ - iotrap = 0; + iotrap = 0; /* not a trap cell instruction */ err_PC = PC; /* save PC for error */ if (sim_brk_summ && /* any breakpoints? */ sim_brk_test (PC, SWMASK ('E') | /* unconditional or */ @@ -964,7 +1201,7 @@ while (reason == 0) { /* loop until halted */ if (mp_evrff) mp_viol = PC; /* if ok, upd mp_viol */ IR = ReadW (PC); /* fetch instr */ PC = (PC + 1) & VAMASK; - ion_defer = 0; + ion_defer = FALSE; } sim_interval = sim_interval - 1; /* count instruction */ @@ -998,37 +1235,24 @@ while (reason == 0) { /* loop until halted */ break; /* JSB is a little tricky. It is possible to generate both an MP and a DM - violation simultaneously. Consider a JSB to a location under the MP fence - and on a write-protected page. This situation must be reported as a DM - violation, because it has priority (SFS 5 and SFC 5 check only the MEVFF, - which sets independently of the MP fence violation). - - Under simulation, this means that DM violations must be checked, and the - MEVFF must be set, before an MP abort is taken. This is done for JSB by the - WriteW call to store the return PC. However, WriteW only checks for fence - violations above location 2, as normally JSBs to locations 0 and 1 (i.e., the - A and B register) are allowed. However, if the W5 (JSB) jumper is out, then - JSB 0 and JSB 1 are MP violations as well and must be caught. We do this - with an explicit check before calling WriteW. - - This would seem to violate the above requirement for DM checks before MP - checks. However, a DM abort cannot occur on a write to 0/1, even if logical - page 0 is write-protected, because writes to 0/1 do not attempt to access - memory; they are intercepted and affect the A/B registers instead (micro- - order TAB is used in the Store field), so no MEV signal is generated. + violation simultaneously, as the MP and MEM cards validate in parallel. + Consider a JSB to a location under the MP fence and on a write-protected + page. This situation must be reported as a DM violation, because it has + priority (SFS 5 and SFC 5 check only the MEVFF, which sets independently of + the MP fence violation). Under simulation, this means that DM violations + must be checked, and the MEVFF must be set, before an MP abort is taken. + This is done by the "mp_dms_jmp" routine. */ case 0230:case 0231:case 0232:case 0233: case 0234:case 0235:case 0236:case 0237: - ion_defer = 1; /* defer if JSB,I */ + ion_defer = TRUE; /* defer if JSB,I */ case 0030:case 0031:case 0032:case 0033: case 0034:case 0035:case 0036:case 0037: if (reason = Ea (IR, &MA, intrq)) break; /* JSB */ - if ((mp_unit.flags & UNIT_MP_JSB) && /* if W5 (JSB) out */ - CTL (PRO) && (MA <= 1)) /* and MP on and JSB 0 or JSB 1 */ - ABORT (ABORT_PRO); /* MP violation */ + mp_dms_jmp (MA, jsb_plb); /* validate jump address */ WriteW (MA, PC); /* store PC */ PCQ_ENTRY; @@ -1043,16 +1267,97 @@ while (reason == 0) { /* loop until halted */ AR = AR ^ ReadW (MA); break; +/* CPU idle processing. + + The 21xx/1000 CPUs have no "wait for interrupt" instruction. Idling in HP + operating systems consists of sitting in "idle loops" that end with JMP + instructions. We test for certain known patterns when a JMP instruction is + executed to decide if the simulator should idle. + + Idling must not occur if an interrupt is pending. As mentioned in the + "General Notes" above, HP CPUs will defer interrupts if certain instructions + are executed. OS interrupt handlers exit via such deferring instructions. + If there is a pending interrupt when the OS is otherwise idle, the idle loop + will execute one instruction before reentering the interrupt handler. If we + call sim_idle() in this case, we will lose interrupts. + + Consider the situation in RTE. Under simulation, the TTY and CLK events are + co-scheduled, with the CLK expiring one instruction after the TTY. When the + TTY interrupts, $CIC in RTE is entered. One instruction later, the CLK + expires and posts its interrupt, but it is not immediately handled, because + the JSB $CIC,I / JMP $CIC0,I / SFS 0,C instruction entry sequence continually + defers interrupts until the interrupt system is turned off. When $CIC + returns via $IRT, one instruction of the idle loop is executed, even though + the CLK interrupt is still pending, because the UJP instruction used to + return also defers interrupts. + + If sim_idle() is called at this point, the simulator will sleep when it + should be handling the pending CLK interrupt. When it awakes, TTY expiration + will be moved forward to the next instruction. The still-pending CLK + interrupt will then be recognized, and $CIC will be entered. But the TTY and + then the CLK will then expire and attempt to interrupt again, although they + are deferred by the $CIC entry sequence. This causes the second CLK + interrupt to be missed, as processing of the first one is just now being + started. + + Similarly, at the end of the CLK handling, the TTY interrupt is still + pending. When $IRT returns to the idle loop, sim_idle() would be called + again, so the TTY and then CLK interrupt a third time. Because the second + TTY interrupt is still pending, $CIC is entered, but the third TTY interrupt + is lost. + + We solve this problem by testing for a pending interrupt before calling + sim_idle(). The system isn't really quiescent if it is just about to handle + an interrupt. +*/ + case 0250:case 0251:case 0252:case 0253: case 0254:case 0255:case 0256:case 0257: - ion_defer = 1; /* defer if JMP,I */ + ion_defer = TRUE; /* defer if JMP,I */ case 0050:case 0051:case 0052:case 0053: case 0054:case 0055:case 0056:case 0057: if (reason = Ea (IR, &MA, intrq)) break; /* JMP */ - mp_dms_jmp (MA); /* validate jump addr */ + mp_dms_jmp (MA, 0); /* validate jump addr */ PCQ_ENTRY; PC = MA; /* jump */ + +/* Idle conditions by operating system: + + RTE-6/VM: + - ISZ / JMP *-1 + - mp_fence = 0 + - XEQT (address 1717B) = 0 + - DMS on with system map enabled + - RTE verification: TBG (address 1674B) = CLK select code + + RTE though RTE-IVB: + - JMP * + - mp_fence = 0 + - XEQT (address 1717B) = 0 + - DMS on with user map enabled (RTE-III through RTE-IVB only) + - RTE verification: TBG (address 1674B) = CLK select code + + DOS through DOS-III: + - STF 0 / CCA / CCB / JMP *-3 + - DOS verification: A = B = -1, address 40B = -64, address 67B = +64 + - Note that in DOS, the TBG is set to 100 milliseconds +*/ + + if ((sim_idle_enab) && (intrq == 0)) /* idle enabled w/o pending irq? */ + if (((PC == err_PC) || /* RTE through RTE-IVB */ + ((PC == (err_PC - 1)) && /* RTE-6/VM */ + ((ReadW (PC) & I_MRG) == I_ISZ))) && /* RTE jump target */ + (mp_fence == CLEAR) && (M [xeqt] == 0) && /* RTE idle indications */ + (M [tbg] == clk_dib.devno) || /* RTE verification */ + + (PC == (err_PC - 3)) && /* DOS through DOS-III */ + (ReadW (PC) == I_STF) && /* DOS jump target */ + (AR == 0177777) && (BR == 0177777) && /* DOS idle indication */ + (M [m64] == 0177700) && /* DOS verification */ + (M [p64] == 0000100)) /* DOS verification */ + + sim_idle (TMR_POLL, FALSE); /* idle the simulator */ break; case 0060:case 0061:case 0062:case 0063: @@ -1244,8 +1549,6 @@ while (reason == 0) { /* loop until halted */ /* 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 */ @@ -1253,19 +1556,9 @@ saved_MR = MR; /* save for T cmd update if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */ (reason == STOP_IND)) PC = err_PC; /* back up PC */ dms_upd_sr (); /* update dms_sr */ +dms_upd_vr (MR); /* update dms_vr */ if (reason == STOP_HALT) /* programmed halt? */ cpu_set_ldr (NULL, FALSE, NULL, NULL); /* disable loader (ignore errors) */ -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 (dms_enb) /* default breakpoint type */ if (dms_ump) sim_brk_dflt = SWMASK ('U'); /* to current map mode */ @@ -1274,6 +1567,7 @@ else sim_brk_dflt = SWMASK ('N'); return reason; } + /* Resolve indirect addresses. An indirect chain is followed until a direct address is obtained. Under @@ -1292,12 +1586,12 @@ t_stat resolve (uint32 MA, uint32 *addr, uint32 irq) { uint32 i; t_bool pending = (irq && !(mp_unit.flags & DEV_DIS)); -t_bool int_enable = ((mp_unit.flags & UNIT_MP_INT) && CTL(PRO)); +t_bool int_enable = ((mp_unit.flags & UNIT_MP_INT) && mp_control); for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ if (pending) { /* interrupt pending and MP enabled? */ if ((i == 2) || int_enable) /* 3rd level indirect or INT out? */ - ion_defer = 0; /* reenable interrrupts */ + ion_defer = FALSE; /* reenable interrrupts */ if ((i > 2) || int_enable) /* 4th or higher or INT out? */ return NOTE_INDINT; /* break out now */ } @@ -1308,9 +1602,10 @@ if (MA & I_IA) return STOP_IND; /* indirect loop? */ return SCPE_OK; } + /* Get effective address from IR */ -t_stat Ea (uint32 IR, uint32 *addr, uint32 irq) +static t_stat Ea (uint32 IR, uint32 *addr, uint32 irq) { uint32 MA; @@ -1319,9 +1614,10 @@ if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */ return resolve (MA, addr, irq); /* resolve indirects */ } + /* Shift micro operation */ -uint32 shift (uint32 t, uint32 flag, uint32 op) +static uint32 shift (uint32 t, uint32 flag, uint32 op) { uint32 oldE; @@ -1363,84 +1659,152 @@ if (op == 06) E = (t >> 15) & 1; /* disabled ext lft rot return t; /* input unchanged */ } + /* I/O instruction decode. If memory protect is enabled, and the instruction is not in a trap cell, then HLT instructions are illegal and will cause a memory protect violation. If jumper W7 (SEL1) is in, then all other I/O instructions are legal; if W7 is - out, then only I/O instructions to select code 1 are legal. + out, then only I/O instructions to select code 1 are legal, and I/O to other + select codes will cause a violation. - We return NOTE_IOG for normal status instead of SCPE_OK to request that - interrupts be recalculated at the end of the instruction (execution of the - I/O group instructions can change the interrupt priority chain). + If the instruction is allowed, then the I/O signal corresponding to the + instruction is determined, the state of the interrupt deferral flag is set. + Then the signal is dispatched to the device simulator indicated by the target + select code. The return value is split into status and data values, with the + latter containing the SKF signal state or data to be returned in the A or B + registers. + + Implementation notes: + + 1. If the H/C (hold/clear flag) bit is set, then the ioCLF signal is added + (not ORed) to the base signal derived from the I/O instruction. + + 2. ioNONE is dispatched for HLT instructions because although HLT does not + assert any backplane signals, the H/C bit may be set. If it is, then the + result will be to dispatch ioCLF. + + 3. Device simulators return either ioSKF or ioNONE in response to an SFC or + SFS signal. ioSKF means that the instruction should skip. Because + device simulators return the "data" parameter value by default, we + initialize that parameter to ioNONE to ensure that a simulator that does + not implement SFC or SFS does not skip, which is the correct action for + an interface that does not drive the SKF signal. + + 4. STF/CLF and STC/CLC share sub-opcode values and must be further decoded + by the state of instruction register bits 9 and 11, respectively. + + 5. We return NOTE_IOG for normal status instead of SCPE_OK to request that + interrupts be recalculated at the end of the instruction (execution of + the I/O group instructions can change the interrupt priority chain). */ t_stat iogrp (uint32 ir, uint32 iotrap) { -uint32 dev, sop, iodata, iostat, 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? */ - ((dev != OVF) && (mp_unit.flags & UNIT_MP_SEL1)))) { /* sel code OK? */ - if (sop == ioLIX) ABREG[ab] = 0; /* A/B writes anyway */ - ABORT (ABORT_PRO); +/* Translation for I/O subopcodes: soHLT, soFLG, soSFC, soSFS, soMIX, soLIX, soOTX, soCTL */ +static const IOSIG generate_signal [] = { ioNONE, ioSTF, ioSFC, ioSFS, ioIOI, ioIOI, ioIOO, ioSTC }; + +const uint32 dev = ir & I_DEVMASK; /* device select code */ +const uint32 sop = I_GETIOOP (ir); /* I/O subopcode */ +const uint32 ab = (ir & I_AB) != 0; /* A/B register select */ +const t_bool clf = (ir & I_HC) != 0; /* H/C flag select */ +uint32 iodata = (SCPE_OK << IOT_V_REASON) | (uint32) ioNONE; /* initialize for SKF test */ +uint32 ioreturn; +t_stat iostat; +IOSIG iosig; + +if (!iotrap && mp_control && /* instr not in trap cell and MP on? */ + ((sop == soHLT) || /* and is HLT? */ + ((dev != OVF) && (mp_unit.flags & UNIT_MP_SEL1)))) { /* or is not SC 01 and SEL1 out? */ + if (sop == soLIX) /* MP violation; is LIA/B instruction? */ + ABREG [ab] = 0; /* A/B writes anyway */ + MP_ABORT (err_PC); /* MP abort */ } -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 */ + +iosig = generate_signal [sop]; /* generate I/O signal */ +ion_defer = defer_tab [sop]; /* defer depending on instruction */ + +if (sop == soOTX) /* OTA/B instruction? */ + iodata = (SCPE_OK << IOT_V_REASON) | ABREG [ab]; /* pass A/B register value */ + +else if ((sop == soCTL) && (ir & I_CTL)) /* CLC instruction? */ + iosig = ioCLC; /* change STC to CLC signal */ + +if ((sop == soFLG) && clf) /* CLF instruction? */ + iosig = ioCLF; /* change STF to CLF signal */ + +else if (clf) /* CLF with another instruction? */ + iosig = iosig + ioCLF; /* add CLF signal */ + +ioreturn = devdisp (dev, iosig, iodata); /* dispatch I/O signal */ + +iostat = (t_stat) (ioreturn >> IOT_V_REASON); /* extract status */ +iodata = ioreturn & DMASK; /* extract return data value */ + +if (((sop == soSFC) || (sop == soSFS)) && /* testing flag state? */ + ((IOSIG) iodata == ioSKF)) /* and SKF asserted? */ + PC = (PC + 1) & VAMASK; /* bump P to skip next instruction */ + +else if (sop == soLIX) /* LIA/B instruction? */ + ABREG [ab] = iodata; /* load returned data */ + +else if (sop == soMIX) /* MIA/B instruction? */ + ABREG [ab] = ABREG [ab] | iodata; /* merge returned data */ + +else if (sop == soHLT) { /* HLT instruction? */ + const int32 len = strlen (halt_msg); /* find end msg */ sprintf (&halt_msg[len - 6], "%06o", ir); /* add the halt */ return STOP_HALT; } -iostat = iodata >> IOT_V_REASON; -if (iostat == SCPE_OK) return NOTE_IOG; /* normal status */ -else return iostat; /* abnormal status */ + +if (iostat == SCPE_OK) /* normal status? */ + return NOTE_IOG; /* request interrupt recalc */ +else /* abnormal status */ + return iostat; /* return it */ } -/* Device dispatch */ -uint32 devdisp (uint32 devno, uint32 inst, uint32 IR, uint32 dat) +/* Device dispatcher */ + +static uint32 devdisp (uint32 select_code, IOSIG signal, uint32 data) { -if (dtab[devno]) return dtab[devno] (inst, IR, dat); -else return nulio (inst, IR, dat); +return dtab [select_code] (select_code, signal, data); } + /* Calculate DMA requests */ -uint32 calc_dma (void) +static uint32 calc_dma (void) { uint32 r = 0; -if (CMD (DMA0) && SRQ (dmac[0].cw1 & I_DEVMASK)) /* check DMA0 cycle */ +if (dma_xferen [0] && SRQ (dmac[0].cw1 & I_DEVMASK)) /* check DMA0 cycle */ r = r | DMAR0; -if (CMD (DMA1) && SRQ (dmac[1].cw1 & I_DEVMASK)) /* check DMA1 cycle */ +if (dma_xferen [1] && SRQ (dmac[1].cw1 & I_DEVMASK)) /* check DMA1 cycle */ r = r | DMAR1; return r; } + /* Determine whether a pending interrupt deferral should be inhibited. - Execution of certain instructions generally causes a pending interrupt to be + Execution of certain instructions generally cause a pending interrupt to be deferred until the succeeding instruction completes. However, the interrupt deferral rules differ on the 21xx vs. the 1000. - + The 1000 always defers until the completion of the instruction following a deferring instruction. The 21xx defers unless the following instruction is an MRG instruction other than JMP or JMP,I or JSB,I. If it is, then the deferral is inhibited, i.e., the pending interrupt will be serviced. - + See the "Set Phase Logic Flowchart," transition from phase 1A to phase 1B, and the "Theory of Operation," "Control Section Detailed Theory," "Phase Control Logic," "Phase 1B" paragraph in the Model 2100A Computer Installation and Maintenance Manual for details. */ -uint32 calc_defer (void) +t_bool calc_defer (void) { uint16 IR; @@ -1450,266 +1814,451 @@ if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) { /* 21xx series? */ if (((IR & I_MRG & ~I_AB) != 0000000) && /* is MRG instruction? */ ((IR & I_MRG_I) != I_JSB_I) && /* but not JSB,I? */ ((IR & I_MRG) != I_JMP)) /* and not JMP or JMP,I? */ - return 0; /* yes, so inhibit deferral */ + return FALSE; /* yes, so inhibit deferral */ else - return 1; /* no, so allow deferral */ + return TRUE; /* no, so allow deferral */ } else - return 1; /* 1000 always allows deferral */ + return TRUE; /* 1000 always allows deferral */ } -/* Calculate interrupt requests - This routine takes into account all the relevant state of the - interrupt system: ion, dev_flg, dev_fbf, and dev_ctl. +/* Calculate interrupt requests. - 1. dev_flg & dev_ctl determines the end of the priority grant. - The break in the chain will occur at the first device for - which dev_flg & dev_ctl is true. This is determined by - AND'ing the set bits with their 2's complement; only the low - order (highest priority) bit will differ. 1 less than - that, or'd with the single set bit itself, is the mask of - possible interrupting devices. If ION is clear, only devices - 4 and 5 are eligible to interrupt. - 2. dev_flg & dev_ctl & dev_fbf determines the outstanding - interrupt requests. All three bits must be on for a device - to request an interrupt. This is the masked under the - result from #1 to determine the highest priority interrupt, - if any. + The interrupt request (IRQ) of the highest-priority device for which all + higher-priority PRL bits are set is granted. That is, there must be an + unbroken chain of priority to a device requesting an interrupt for that + request to be granted. + + A device sets its IRQ bit to request an interrupt, and it clears its PRL bit + to prevent lower-priority devices from interrupting. IRQ is cleared by an + interrupt acknowledge (IAK) signal. PRL generally remains low while a + device's interrupt service routine is executing to prevent preemption. + + IRQ and PRL indicate one of four possible states for a device: + + IRQ PRL Device state + --- --- ---------------------- + 0 1 Not interrupting + 1 0 Interrupt requested + 0 0 Interrupt acknowledged + 1 1 (not allowed) + + Note that PRL must be dropped when requesting an interrupt (IRQ set). This + is a hardware requirement of the 1000 series. The IRQ lines from the + backplane are not priority encoded. Instead, the PRL chain expresses the + priority by allowing only one IRQ line to be active at a time. This allows a + simple pull-down encoding of the CIR inputs. + + The end of priority chain is marked by the highest-priority (lowest-order) + bit that is clear. The device corresponding to that bit is the only device + that may interrupt (a higher priority device that had IRQ set would also have + had PRL set, which is a state violation). We calculate a priority mask by + ANDing the complement of the PRL bits with an increment of the PRL bits. Only + the lowest-order bit will differ. For example: + + dev_prl : ...1 1 0 1 1 0 1 1 1 1 1 1 (PRL denied for SC 06 and 11) + + dev_prl + 1 : ...1 1 0 1 1 1 0 0 0 0 0 0 + ~dev_prl : ...0 0 1 0 0 1 0 0 0 0 0 0 + ANDed value : ...0 0 0 0 0 1 0 0 0 0 0 0 (break is at SC 06) + + The interrupt requests are then ANDed with the priority mask to determine if + a request is pending: + + pri mask : ...0 0 0 0 0 1 0 0 0 0 0 0 (allowed interrupt source) + dev_irq : ...0 0 1 0 0 1 0 0 0 0 0 0 (devices requesting interrupts) + ANDed value : ...0 0 0 0 0 1 0 0 0 0 0 0 (request to grant) + + The select code corresponding to the granted request is then returned to the + caller. + + If ION is clear, only power fail (SC 04) and parity error (SC 05) are + eligible to interrupt (memory protect shares SC 05, but qualification occurs + in the MP abort handler, so if SC 05 is interrupting when ION is clear, it + must be a parity error interrupt). */ uint32 calc_int (void) { -int32 j, lomask, mask[2], req[2]; +uint32 sc, pri_mask [2], req_grant [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]; +pri_mask [0] = ~dev_prl [0] & (dev_prl [0] + 1); /* calculate lower priority mask */ +req_grant [0] = pri_mask [0] & dev_irq [0]; /* calculate lower request to grant */ + +if (ion) /* interrupt system on? */ + if ((req_grant [0] == 0) && (pri_mask [0] == 0)) { /* no requests in lower set and PRL unbroken? */ + pri_mask [1] = ~dev_prl [1] & (dev_prl [1] + 1); /* calculate upper priority mask */ + req_grant [1] = pri_mask [1] & dev_irq [1]; /* calculate upper request to grant */ } - else req[1] = 0; + else /* lower set has request */ + req_grant [1] = 0; /* no grants to upper set */ + +else { /* interrupt system off */ + req_grant [0] = req_grant [0] & /* only PF and PE can interrupt */ + (INT_M (PWR) | INT_M (PRO)); + req_grant [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; + +if (req_grant [0]) /* device in lower half? */ + for (sc = 0; sc <= 31; sc++) /* determine interrupting select code */ + if (req_grant [0] & 1) /* grant this request? */ + return sc; /* return this select code */ + else /* not this one */ + req_grant [0] = req_grant [0] >> 1; /* position next request */ + +else if (req_grant [1]) /* device in upper half */ + for (sc = 32; sc <= 63; sc++) /* determine interrupting select code */ + if (req_grant [1] & 1) /* grant this request? */ + return sc; /* return this select code */ + else /* not this one */ + req_grant [1] = req_grant [1] >> 1; /* position next request */ + +return 0; /* no interrupt granted */ } -/* Memory access routines */ + +/* Memory access routines. + + These routines access memory for reads and writes. They validate the + accesses for MP and MEM violations, if enabled. The following routines are + provided: + + - ReadPW : Read a word using a physical address + - ReadB : Read a byte using the current map + - ReadBA : Read a byte using the alternate map + - ReadW : Read a word using the current map + - ReadWA : Read a word using the alternate map + - ReadIO : Read a word using the specified map without protection + - ReadTAB : Read a word using the current map without protection + + - WritePW : Write a word using a physical address + - WriteB : Write a byte using the current map + - WriteBA : Write a byte using the alternate map + - WriteW : Write a word using the current map + - WriteWA : Write a word using the alternate map + - WriteIO : Write a word using the specified map without protection + + The memory protect (MP) and memory expansion module (MEM) accessories provide + a protected mode that guards against improper accesses by user programs. + They may be enabled or disabled independently, although protection requires + that both be enabled. MP checks that memory writes do not fall below the + Memory Protect Fence Register (MPFR) value, and MEM checks that read/write + protection rules on the target page are compatible with the access desired. + If either check fails, and MP is enabled, then the request is aborted. + + Each mapped routine calls "dms" if DMS is enabled to translate the logical + address supplied to a physical address. "dms" performs a protection check + and aborts without returning if the check fails. The write routines perform + an additional memory-protect check and abort if a violation occurs (so, to + pass, a page must be writable AND the target must be above the MP fence). + + Note that MP uses a lower bound of 2 for memory writes, allowing unrestricted + access to the A and B registers (addressed as locations 0 and 1). +*/ + +#define MP_TEST(va) (mp_control && ((va) >= 2) && ((va) < mp_fence)) + + +/* Read a word using a physical address */ + +uint16 ReadPW (uint32 pa) +{ +if (pa <= 1) /* read locations 0 or 1? */ + return ABREG[pa]; /* return A/B register */ +else /* location >= 2 */ + return M[pa]; /* return physical memory value */ +} + + +/* Read a byte using the current map */ uint8 ReadB (uint32 va) { int32 pa; -if (dms_enb) pa = dms (va >> 1, dms_ump, RD); -else pa = va >> 1; -if (va & 1) return (ReadPW (pa) & 0377); -else return ((ReadPW (pa) >> 8) & 0377); +if (dms_enb) /* MEM enabled? */ + pa = dms (va >> 1, dms_ump, RDPROT); /* translate address */ +else /* MEM disabled */ + pa = va >> 1; /* use logical as physical address */ + +if (va & 1) /* low byte addressed? */ + return (ReadPW (pa) & 0377); /* mask to lower byte */ +else /* high byte addressed */ + return ((ReadPW (pa) >> 8) & 0377); /* position higher byte and mask */ } + +/* Read a byte using the alternate map */ + uint8 ReadBA (uint32 va) { uint32 pa; -if (dms_enb) pa = dms (va >> 1, dms_ump ^ MAP_LNT, RD); -else pa = va >> 1; -if (va & 1) return (ReadPW (pa) & 0377); -else return ((ReadPW (pa) >> 8) & 0377); +if (dms_enb) /* MEM enabled? */ + pa = dms (va >> 1, dms_ump ^ MAP_LNT, RDPROT); /* translate address using alternate map */ +else /* MEM disabled */ + pa = va >> 1; /* use logical as physical address */ + +if (va & 1) /* low byte addressed? */ + return (ReadPW (pa) & 0377); /* mask to lower byte */ +else /* high byte addressed */ + return ((ReadPW (pa) >> 8) & 0377); /* position higher byte and mask */ } + +/* Read a word using the current map */ + uint16 ReadW (uint32 va) { uint32 pa; -if (dms_enb) pa = dms (va, dms_ump, RD); -else pa = va; -return ReadPW (pa); +if (dms_enb) /* MEM enabled? */ + pa = dms (va, dms_ump, RDPROT); /* translate address */ +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +return ReadPW (pa); /* return word */ } + +/* Read a word using the alternate map */ + uint16 ReadWA (uint32 va) { uint32 pa; -if (dms_enb) pa = dms (va, dms_ump ^ MAP_LNT, RD); -else pa = va; -return ReadPW (pa); +if (dms_enb) /* MEM enabled? */ + pa = dms (va, dms_ump ^ MAP_LNT, RDPROT); /* translate address using alternate map */ +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +return ReadPW (pa); /* return word */ } + +/* Read a word using the specified map without protection */ + uint16 ReadIO (uint32 va, uint32 map) { uint32 pa; -if (dms_enb) pa = dms_io (va, map); -else pa = va; -return M[pa]; +if (dms_enb) /* MEM enabled? */ + pa = dms (va, map, NOPROT); /* translate address with no protection */ +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +return M[pa]; /* return word without A/B interception */ } -uint16 ReadPW (uint32 pa) + +/* Read a word using the current map without protection */ + +static uint16 ReadTAB (uint32 va) { -if (pa <= 1) return ABREG[pa]; -return M[pa]; +uint32 pa; + +if (dms_enb) /* MEM enabled? */ + pa = dms (va, dms_ump, NOPROT); /* translate address with no protection */ +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +return ReadPW (pa); /* return word */ } -uint16 ReadTAB (uint32 addr) + +/* Write a word using a physical address */ + +void WritePW (uint32 pa, uint32 dat) { -if (addr == 0) return saved_AR; -else if (addr == 1) return saved_BR; -else return ReadIO (addr, dms_ump); +if (pa <= 1) /* write locations 0 or 1? */ + ABREG[pa] = dat & DMASK; /* store A/B register */ +else if (pa < fwanxm) /* 2 <= location <= LWA memory? */ + M[pa] = dat & DMASK; /* store physical memory value */ + +return; } -/* Memory protection test for writes - From Dave Bryan: The problem is that memory writes aren't being checked for - an MP violation if DMS is enabled, i.e., if DMS is enabled, and the page is - writable, then whether the target is below the MP fence is not checked. [The - simulator must] do MP check on all writes after DMS translation and violation - 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)) +/* Write a byte using the current map */ void WriteB (uint32 va, uint32 dat) { uint32 pa, t; -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); - } +if (dms_enb) /* MEM enabled? */ + pa = dms (va >> 1, dms_ump, WRPROT); /* translate address */ +else /* MEM disabled */ + pa = va >> 1; /* use logical as physical address */ + +if (MP_TEST (va >> 1)) /* MPCK? */ + MP_ABORT (va >> 1); /* MP violation */ + +t = ReadPW (pa); /* get word */ + +if (va & 1) /* low byte addressed? */ + t = (t & 0177400) | (dat & 0377); /* merge in lower byte */ +else /* high byte addressed */ + t = (t & 0377) | ((dat & 0377) << 8); /* position higher byte and merge */ + +WritePW (pa, t); /* store word */ return; } + +/* Write a byte using the alternate map */ + 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); - } -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); +if (dms_enb) { /* MEM enabled? */ + dms_viol (va >> 1, MVI_WPR); /* always a violation if protected */ + pa = dms (va >> 1, dms_ump ^ MAP_LNT, WRPROT); /* translate address using alternate map */ } +else /* MEM disabled */ + pa = va >> 1; /* use logical as physical address */ + +if (MP_TEST (va >> 1)) /* MPCK? */ + MP_ABORT (va >> 1); /* MP violation */ + +t = ReadPW (pa); /* get word */ + +if (va & 1) /* low byte addressed? */ + t = (t & 0177400) | (dat & 0377); /* merge in lower byte */ +else /* high byte addressed */ + t = (t & 0377) | ((dat & 0377) << 8); /* position higher byte and merge */ + +WritePW (pa, t); /* store word */ return; } + +/* Write a word using the current map */ + void WriteW (uint32 va, uint32 dat) { uint32 pa; -if (dms_enb) pa = dms (va, dms_ump, WR); -else pa = va; -if (MP_TEST (va)) ABORT (ABORT_PRO); -if (MEM_ADDR_OK (pa)) WritePW (pa, dat); +if (dms_enb) /* MEM enabled? */ + pa = dms (va, dms_ump, WRPROT); /* translate address */ +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +if (MP_TEST (va)) /* MPCK? */ + MP_ABORT (va); /* MP violation */ + +WritePW (pa, dat); /* store word */ return; } + +/* Write a word using the alternate map */ + 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); +if (dms_enb) { /* MEM enabled? */ + dms_viol (va, MVI_WPR); /* always a violation if protected */ + pa = dms (va, dms_ump ^ MAP_LNT, WRPROT); /* translate address using alternate map */ } -else pa = va; -if (MP_TEST (va)) ABORT (ABORT_PRO); -if (MEM_ADDR_OK (pa)) WritePW (pa, dat); +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +if (MP_TEST (va)) /* MPCK? */ + MP_ABORT (va); /* MP violation */ + +WritePW (pa, dat); /* store word */ return; } + +/* Write a word using the specified map without protection */ + void WriteIO (uint32 va, uint32 dat, uint32 map) { uint32 pa; -if (dms_enb) pa = dms_io (va, map); -else pa = va; -if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; +if (dms_enb) /* MEM enabled? */ + pa = dms (va, map, NOPROT); /* translate address with no protection */ +else /* MEM disabled */ + pa = va; /* use logical as physical address */ + +if (pa < fwanxm) + M[pa] = dat & DMASK; /* store word without A/B interception */ return; } -void WritePW (uint32 pa, uint32 dat) + +/* Mapped access check. + + Returns TRUE if the address will be mapped (presuming MEM is enabled). +*/ + +static t_bool is_mapped (uint32 va) { -if (pa <= 1) ABREG[pa] = dat & DMASK; -else M[pa] = dat & DMASK; -return; +uint32 dms_fence = dms_sr & MST_FENCE; /* get BP fence value */ + +if (va >= 02000) /* above the base bage? */ + return TRUE; /* always mapped */ +else + return (dms_sr & MST_FLT) ? (va < dms_fence) : /* below BP fence and lower portion mapped? */ + (va >= dms_fence); /* or above BP fence and upper portion mapped? */ } -/* DMS relocation for CPU access */ -uint32 dms (uint32 va, uint32 map, uint32 prot) +/* DMS relocation. + + This routine translates logical into physical addresses. It must be called + only when DMS is enabled, as that condition is not checked. The logical + address, desired map, and desired access type are supplied. If the access is + legal, the mapped physical address is returned; if it is not, then a MEM + violation is indicated. + + The current map may be specified by passing "dms_ump" as the "map" parameter, + or a specific map may be used. Normally, read and write accesses pass RDPROT + or WRPROT as the "prot" parameter to request access checking. For DMA + accesses, NOPROT must be passed to inhibit access checks. + + This routine checks for read, write, and base-page violations and will call + "dms_viol" as appropriate. The latter routine will abort if MP is enabled, + or will return if protection is off. +*/ + +static 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 */ - } +if (va <= 1) /* reference to A/B register? */ + return va; /* use address */ + +if (!is_mapped (va)) { /* unmapped? */ + if ((va >= 2) && (prot == WRPROT)) /* base page write access? */ + dms_viol (va, MVI_BPG); /* signal a base page violation */ + return va; /* use unmapped address */ } + +pgn = VA_GETPAG (va); /* get page num */ mpr = dms_map[map + pgn]; /* get map reg */ -if (mpr & prot) dms_viol (va, prot); /* prot violation? */ -return (MAP_GETPAG (mpr) | VA_GETOFF (va)); + +if (mpr & prot) /* desired access disallowed? */ + dms_viol (va, prot); /* signal protection violation */ + +return (MAP_GETPAG (mpr) | VA_GETOFF (va)); /* return mapped address */ } -/* DMS relocation for IO access */ -uint32 dms_io (uint32 va, uint32 map) -{ -uint32 pgn, mpr; +/* DMS relocation for console access. -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)); -} + Console access allows the desired map to be specified by switches on the + command line. All protection checks are off for console access. -/* DMS relocation for console access */ + This routine is called to restore a saved configuration, and mapping is not + used for restoration. +*/ -uint32 dms_cons (uint32 va, int32 sw) +static uint32 dms_cons (uint32 va, int32 sw) { uint32 map_sel; @@ -1722,390 +2271,692 @@ else if (sw & SWMASK ('P')) map_sel = PAMAP; else if (sw & SWMASK ('Q')) map_sel = PBMAP; else map_sel = dms_ump; /* dflt to log addr, cur map */ 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 if (dms_enb) return dms (va, map_sel, NOPROT); /* DMS on? go thru map */ else return va; /* else return virtual */ } -/* Mem protect and DMS validation for jumps */ -void mp_dms_jmp (uint32 va) +/* Memory protect and DMS validation for jumps. + + Jumps are a special case of write validation. The target address is treated + as a write, even when no physical write takes place, so jumping to a + write-protected page causes a MEM violation. In addition, a MEM violation is + indicated if the jump is to the unmapped portion of the base page. Finally, + jumping to a location under the memory-protect fence causes an MP violation. + + Because the MP and MEM hardware works in parallel, all three violations may + exist concurrently. For example, a JMP to the unmapped portion of the base + page that is write protected and under the MP fence will indicate a + base-page, write, and MP violation, whereas a JMP to the mapped portion will + indicate a write and MP violation (BPV is inhibited by the MEBEN signal). If + MEM and MP violations occur concurrently, the MEM violation takes precedence, + as the SFS and SFC instructions test the MEV flip-flop. + + The lower bound of protected memory is passed in the "plb" argument. This + must be either 0 or 2. All violations are qualified by the MPCND signal, + which responds to the lower bound. Therefore, if the lower bound is 2, and + if the part below the base-page fence is unmapped, or if the base page is + write-protected, then a MEM violation will occur only if the access is not to + locations 0 or 1. The instruction set firmware uses a lower bound of 0 for + JMP, JLY, and JPY (and for JSB with W5 out), and of 2 for DJP, SJP, UJP, JRS, + and .GOTO (and JSB with W5 in). + + Finally, all violations are inhibited if MP is off (mp_control is CLEAR), and + MEM violations are inhibited if the MEM is disabled. +*/ + +void mp_dms_jmp (uint32 va, uint32 plb) { -uint32 pgn = VA_GETPAG (va); /* get page num */ +uint32 violation = 0; +uint32 pgn = VA_GETPAG (va); /* get page number */ -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 (mp_control) { /* MP on? */ + if (dms_enb) { /* MEM on? */ + if (dms_map [dms_ump + pgn] & WRPROT) /* page write protected? */ + violation = MVI_WPR; /* write violation occured */ + + if (!is_mapped (va) && (va >= plb)) /* base page target? */ + violation = violation | MVI_BPG; /* base page violation occured */ + + if (violation) /* any violation? */ + dms_viol (va, violation); /* signal MEM violation */ } + + if ((va >= plb) && (va < mp_fence)) /* jump under fence? */ + MP_ABORT (va); /* signal MP violation */ } -if (CTL (PRO) && (va < mp_fence)) ABORT (ABORT_PRO); /* base page MPR */ + return; } -/* DMS read and write maps */ + +/* DMS read and write map registers */ uint16 dms_rmap (uint32 mapi) { mapi = mapi & MAP_MASK; -return (dms_map[mapi] & ~MAP_MBZ); +return (dms_map[mapi] & ~MAP_RSVD); } void dms_wmap (uint32 mapi, uint32 dat) { mapi = mapi & MAP_MASK; -dms_map[mapi] = (uint16) (dat & ~MAP_MBZ); +dms_map[mapi] = (uint16) (dat & ~MAP_RSVD); return; } -/* DMS violation */ + +/* Process a MEM violation. + + A MEM violation will report the cause in the violation register. This occurs + even if the MEM is not in the protected mode (i.e., MP is not enabled). If + MP is enabled, an MP abort is taken with the MEV flip-flop set. Otherwise, + we return to the caller. +*/ 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 */ +dms_vr = st | dms_upd_vr (va); /* set violation cause in register */ + +if (mp_control) { /* memory protect on? */ + mp_mevff = SET; /* record memory expansion violation */ + MP_ABORT (va); /* abort */ } return; } -/* DMS update status */ + +/* Update the MEM violation register. + + In hardware, the MEM violation register (VR) is clocked on every memory read, + every memory write above the lower bound of protected memory, and every + execution of a privileged DMS instruction. The register is not clocked when + MP is disabled by an MP or MEM error (i.e., when MEVFF sets or CTL5FF + clears), in order to capture the state of the MEM. In other words, the VR + continually tracks the memory map register accessed plus the MEM state + (MEBEN, MAPON, and USR) until a violation occurs, and then it's "frozen." + + Under simulation, we do not have to update the VR on every memory access, + because the visible state is only available via a programmed RVA/B + instruction or via the SCP interface. Therefore, it is sufficient if the + register is updated: + + - at a MEM violation (when freezing) + - at an MP violation (when freezing) + - during RVA/B execution (if not frozen) + - before returning to SCP after a simulator stop (if not frozen) +*/ + +uint32 dms_upd_vr (uint32 va) +{ +if (mp_control && (mp_mevff == CLEAR)) { /* violation register unfrozen? */ + dms_vr = VA_GETPAG (va) | /* set map address */ + (dms_enb ? MVI_MEM : 0) | /* and MEM enabled */ + (dms_ump ? MVI_UMP : 0); /* and user map enabled */ + + if (is_mapped (va)) /* is addressed mapped? */ + dms_vr = dms_vr | MVI_MEB; /* ME bus is enabled */ + } + +return dms_vr; +} + + +/* Update the MEM status register */ uint32 dms_upd_sr (void) { dms_sr = dms_sr & ~(MST_ENB | MST_UMP | MST_PRO); if (dms_enb) dms_sr = dms_sr | MST_ENB; if (dms_ump) dms_sr = dms_sr | MST_UMP; -if (CTL (PRO)) dms_sr = dms_sr | MST_PRO; +if (mp_control) 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). +/* CPU (SC 0) I/O signal handler. - NOTE: CLC 0 issues CRS to all devices, not CLC. While most cards react - identically to CRS and CLC, some do not, e.g., the 12566B when used as an - I/O diagnostic target. PRESET also issues CRS (with POPIO). + I/O instructions for select code 0 manipulate the interrupt system. STF and + CLF turn the interrupt system on and off, and SFS and SFC test the state of + the interrupt system. When the interrupt system is off, only power fail and + parity error interrupts are allowed. - From Dave Bryan: RTE uses the undocumented instruction "SFS 0,C" to both test - and turn off the interrupt system. This is confirmed in the "RTE-6/VM - Technical Specifications" manual (HP 92084-90015), section 2.3.1 "Process - the Interrupt", subsection "A.1 $CIC": + Implementation notes: - "Test to see if the interrupt system is on or off. This is done with the - SFS 0,C instruction. In either case, turn it off (the ,C does it)." + 1. An IOI signal reads the floating I/O bus (0 on all machines). - ...and in section 5.8, "Parity Error Detection": + 2. A CLC 0 issues CRS to all devices, not CLC. While most cards react + identically to CRS and CLC, some do not, e.g., the 12566B when used as an + I/O diagnostic target. - "Because parity error interrupts can occur even when the interrupt system - is off, the code at $CIC must be able to save the complete system status. - The major hole in being able to save the complete state is in saving the - interrupt system state. In order to do this in both the 21MX and the 21XE - the instruction 103300 was used to both test the interrupt system and - turn it off." + 3. RTE uses the undocumented SFS 0,C instruction to both test and turn off + the interrupt system. This is confirmed in the "RTE-6/VM Technical + Specifications" manual (HP 92084-90015), section 2.3.1 "Process the + Interrupt", subsection "A.1 $CIC": + + "Test to see if the interrupt system is on or off. This is done with + the SFS 0,C instruction. In either case, turn it off (the ,C does + it)." + + ...and in section 5.8, "Parity Error Detection": + + "Because parity error interrupts can occur even when the interrupt + system is off, the code at $CIC must be able to save the complete + system status. The major hole in being able to save the complete state + is in saving the interrupt system state. In order to do this in both + the 21MX and the 21XE the instruction 103300 was used to both test the + interrupt system and turn it off." + + 4. Select code 0 cannot interrupt, so there is no SIR handler. */ -int32 cpuio (int32 inst, int32 IR, int32 dat) +uint32 cpuio (uint32 select_code, IOSIG signal, uint32 data) { -int i; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +uint32 sc; -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - 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; + case ioCLF: /* clear flag flip-flop */ + ion = CLEAR; /* turn interrupt system off */ break; - case ioSFS: /* skip flag set */ - if (ion) PC = (PC + 1) & VAMASK; + case ioSTF: /* set flag flip-flop */ + ion = SET; /* turn interrupt system on */ break; - case ioLIX: /* load */ - dat = 0; /* returns 0 */ + case ioSFC: /* skip if flag is clear */ + setSKF (!ion); /* skip if interrupt system is off */ break; - case ioCTL: /* control */ - if (IR & I_CTL) /* CLC 0 sends CRS */ - for (i = 0; i <= I_DEVMASK; i++) /* to all devices */ - devdisp (i, ioCRS, I_CTL + i, 0); /* IR -> "CLC i" for convenience */ + case ioSFS: /* skip if flag is set */ + setSKF (ion); /* skip if interupt system is on */ break; - default: + case ioIOI: /* I/O input */ + data = 0; /* returns 0 */ break; - } -if (IR & I_HC) ion = 0; /* HC option */ -return dat; + case ioCLC: /* clear control flip-flop */ + for (sc = 6; sc <= I_DEVMASK; sc++) /* send CRS to devices */ + devdisp (sc, ioCRS, 0); /* from select code 6 and up */ + break; + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + cpuio (select_code, ioCLF, 0); /* issue CLF */ + +return data; } -/* Device 1 (overflow/S-register) I/O routine - NOTE: The S register is read-only on the 2115/2116. It is read/write on - the 2114, 2100, and 1000. +/* Overflow/S-register (SC 1) I/O signal handler. + + Flag instructions directed to select code 1 manipulate the overflow (O) + register. Input and output instructions access the switch (S) register. On + the 2115 and 2116, there is no S-register indicator, so it is effectively + read-only. On the other machines, a front-panel display of the S-register is + provided. On all machines, front-panel switches are provided to set the + contents of the S register. + + Implementation notes: + + 1. Select code 1 cannot interrupt, so there is no SIR handler. */ -int32 ovfio (int32 inst, int32 IR, int32 dat) +uint32 ovflio (uint32 select_code, IOSIG signal, uint32 data) { -switch (inst) { /* case on opcode */ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ - case ioFLG: /* flag */ - O = (IR & I_HC)? 0: 1; /* clear/set overflow */ - return dat; +switch (base_signal) { /* dispatch base I/O signal */ - 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; + case ioCLF: /* clear flag flip-flop */ + O = 0; /* clear overflow */ break; - case ioLIX: /* load */ - dat = SR; + case ioSTF: /* set flag flip-flop */ + O = 1; /* set overflow */ break; - case ioOTX: /* output */ - if ((UNIT_CPU_MODEL != UNIT_2116) && - (UNIT_CPU_MODEL != UNIT_2115)) - SR = dat; + case ioSFC: /* skip if flag is clear */ + setSKF (!O); /* skip if overflow is clear */ break; - default: + case ioSFS: /* skip if flag is set */ + setSKF (O); /* skip if overflow is set */ break; - } -if (IR & I_HC) O = 0; /* HC option */ -return dat; + case ioIOI: /* I/O input */ + data = SR; /* read switch register value */ + break; + + case ioIOO: /* I/O output */ + if ((UNIT_CPU_MODEL != UNIT_2116) && /* no S register display on */ + (UNIT_CPU_MODEL != UNIT_2115)) /* 2116 and 2115 machines */ + SR = data; /* write S register value */ + break; + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + ovflio (select_code, ioCLF, 0); /* issue CLF */ + +return data; } -/* Device 4 (power fail) I/O routine */ -int32 pwrio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ +/* Power fail (SC 4) I/O signal handler. - case ioMIX: /* merge */ - dat = dat | intaddr; - break; + Power fail detection is standard on 2100 and 1000 systems and is optional on + 21xx systems. Power fail recovery is standard on the 2100 and optional on + the others. Power failure or restoration will cause an interrupt on select + code 4. The direction of power change (down or up) can be tested by SFC. - case ioLIX: /* load */ - dat = intaddr; - break; - - default: - break; - } - -return dat; -} - -/* Device 5 (memory protect) I/O routine - - From Dave Bryan: Examination of the schematics for the MP card in the - engineering documentation shows that the SFS and SFC I/O backplane signals - gate the output of the MEVFF onto the SKF line unconditionally. - - The MEVFF records memory expansion (a.k.a. dynamic mapping) violations. It - is set when an DM violation is encountered. It is cleared on POPIO, STC 5, - and -HLT * IOGSP * INTPT. The latter occurs when an interrupt causes - execution of a non-halt I/O instruction in the interrupt trap cell. + We do not implement power fail under simulation. However, the central + interrupt register (CIR) is always read by an IOI directed to select code 4. */ -int32 proio (int32 inst, int32 IR, int32 dat) +uint32 pwrfio (uint32 select_code, IOSIG signal, uint32 data) { -switch (inst) { /* case on opcode */ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ - case ioSFC: /* skip flag clear */ - if (!mp_mevff) PC = (PC + 1) & VAMASK; /* skip if mem prot */ +switch (base_signal) { /* dispatch base I/O signal */ + + case ioSTC: /* set control flip-flop */ + break; /* reinitializes power fail */ + + case ioCLC: /* clear control flip-flop */ + break; /* reinitializes power fail */ + + case ioSFC: /* skip if flag is clear */ + break; /* skips if power fail occurred */ + + case ioIOI: /* I/O input */ + data = intaddr; /* input CIR value */ break; - case ioSFS: /* skip flag set */ - if (mp_mevff) PC = (PC + 1) & VAMASK; /* skip if DMS */ + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + pwrfio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + pwrfio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; +} + + +/* Memory protect/parity error (SC 5) I/O signal handler. + + The memory protect card has a number of non-standard features: + + - CLF and STF affect the parity error enable flip-flop, not the flag + - SFC and SFS test the memory expansion violation flip-flop, not the flag + - POPIO clears control, flag, and flag buffer instead of setting the flags + - CLC does not clear control (the only way to turn off MP is to cause a + violation) + - PRL and IRQ are a function of the flag only, not flag and control + - IAK is used unqualified by IRQ + + The IAK backplane signal is asserted when any interrupt is acknowledged by + the CPU. Normally, an interface qualifies IAK with its own IRQ to ensure + that it responds only to an acknowledgement of its own request. The MP card + does this to reset its flag buffer and flag flip-flops, and to reset the + parity error indication. However, it also responds to an unqualified IAK + (i.e., for any interface) as follows: + + - clears the MPV flip-flop + - clears the indirect counter + - clears the control flip-flop + - sets the INTPT flip-flop + + The INTPT flip-flop indicates an occurrence of an interrupt. If the trap + cell of the interrupting device contains an I/O instruction that is not a + HLT, action equivalent to STC 05 is taken, i.e.: + + - sets the control flip-flop + - set the EVR flip-flop + - clears the MEV flip-flop + - clears the PARERR flip-flop + + In other words, an interrupt for any device will disable MP unless the trap + cell contains an I/O instruction other than a HLT. + + Implementation notes: + + 1. Because the card uses IAK unqualified, this routine is called whenever + any interrupt occurs. If the MP card itself is not interrupting, the + select code passed will not be SC 05. In either case, the trap cell + instruction is passed in the "data" parameter. + + 2. The MEV flip-flop records memory expansion (a.k.a. dynamic mapping) + violations. It is set when an DM violation is encountered and can be + tested via SFC/SFS. + + 3. MP cannot be turned off in hardware, except by causing a violation. + Microcode typically does this by executing an IOG micro-order with select + code /= 1, followed by an IAK to clear the interrupt and a FTCH to clear + the INTPT flip-flop. Under simulation, mp_control may be set to CLEAR to + produce the same effect. + + 4. Parity error logic is not implemented. +*/ + +uint32 protio (uint32 select_code, IOSIG signal, uint32 data) +{ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ + +switch (base_signal) { /* dispatch base I/O signal */ + + case ioCLF: /* clear flag flip-flop */ + break; /* turns off PE interrupt */ + + case ioSTF: /* set flag flip-flop */ + break; /* turns on PE interrupt */ + + case ioENF: /* enable flag */ + mp_flag = mp_flagbuf = SET; /* set flag buffer and flag flip-flops */ + mp_evrff = CLEAR; /* inhibit violation register updates */ break; - case ioMIX: /* merge */ - dat = dat | mp_viol; + case ioSFC: /* skip if flag is clear */ + setSKF (!mp_mevff); /* skip if MP interrupt */ break; - case ioLIX: /* load */ - dat = mp_viol; + case ioSFS: /* skip if flag is set */ + setSKF (mp_mevff); /* skip if DMS interrupt */ break; - case ioOTX: /* output */ - mp_fence = dat & VAMASK; - if (cpu_unit.flags & UNIT_2100) iop_sp = mp_fence; + case ioIOI: /* I/O input */ + data = mp_viol; /* read MP violation register */ break; - case ioCRS: /* control reset */ - 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 */ + case ioIOO: /* I/O output */ + mp_fence = data & VAMASK; /* write to MP fence register */ + + if (cpu_unit.flags & UNIT_2100) /* 2100 IOP uses MP fence */ + iop_sp = mp_fence; /* as a stack pointer */ + break; + + case ioPOPIO: /* power-on preset to I/O */ + mp_control = CLEAR; /* clear control flip-flop */ + mp_flag = mp_flagbuf = CLEAR; /* clear flag and flag buffer flip-flops */ + mp_mevff = CLEAR; /* clear memory expansion violation flip-flop */ + mp_evrff = SET; /* set enable violation register flip-flop */ + break; + + case ioSTC: /* set control flip-flop */ + mp_control = SET; /* turn on MP */ + mp_mevff = CLEAR; /* clear memory expansion violation flip-flop */ + mp_evrff = SET; /* set enable violation register flip-flop */ + break; + + case ioSIR: /* set interrupt request */ + setPRL (PRO, !mp_flag); /* set PRL signal */ + setIRQ (PRO, mp_flag); /* set IRQ signal */ + break; + + case ioIAK: /* interrupt acknowledge */ + if (select_code == PRO) /* MP interrupt acknowledgement? */ + mp_flag = mp_flagbuf = CLEAR; /* clear flag and flag buffer */ + + if (((data & I_NMRMASK) != I_IO) || /* trap cell instruction not I/O */ + (I_GETIOOP (data) == soHLT)) /* or is halt? */ + mp_control = CLEAR; /* turn protection off */ + else { /* non-HLT I/O instruction leaves MP on */ + mp_mevff = CLEAR; /* but clears MEV flip-flop */ + mp_evrff = SET; /* and reenables violation register flip-flop */ } break; - default: - break; - } + default: /* all other signals */ + break; /* are ignored */ + } -if (IR & I_HC) { clrFLG (PRO); } /* HC option */ -return dat; +if (signal > ioCLF) /* multiple signals? */ + protio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + protio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } -/* Devices 2,3 (secondary DMA) I/O routine. - Implements control word 2 (memory address) and control word 3 (word count). +/* DMA/DCPC secondary (SC 2/3) I/O signal handler. - The 12607B (2114) supports 14-bit addresses and 13-bit word counts. - The 12578A (2115/6) supports 15-bit addresses and 14-bit word counts. - The 12895A (2100) and 12897B (1000) support 15-bit addresses and 16-bit word - counts. + DMA consists of one (12607B) or two (12578A/12895A/12897B) channels. Each + channel uses two select codes: 2 and 6 for channel 1, and 3 and 7 for channel + 2. The lower select codes are used to configure the memory address register + (control word 2) and the word count register (control word 3). The upper + select codes are used to configure the service select register (control word + 1) and to activate and terminate the transfer. - Note: because the I/O bus floats to zero on 211x computers, LIA/MIA (word - count) returns zeros in the unused bit locations, even though the word count - is a negative value. + There are differences in the implementations of the memory address and word + count registers among the various cards. The 12607B (2114) supports 14-bit + addresses and 13-bit word counts. The 12578A (2115/6) supports 15-bit + addresses and 14-bit word counts. The 12895A (2100) and 12897B (1000) + support 15-bit addresses and 16-bit word counts. + + Implementation notes: + + 1. Because the I/O bus floats to zero on 211x computers, an IOI (read word + count) returns zeros in the unused bit locations, even though the word + count is a negative value. + + 2. Select codes 2 and 3 cannot interrupt, so there is no SIR handler. */ -int32 dmsio (int32 inst, int32 IR, int32 dat) +uint32 dmasio (uint32 select_code, IOSIG signal, uint32 data) { -int32 ch; +const uint32 ch = select_code & 1; /* DMA channel number */ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -ch = IR & 1; /* get channel num */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioLIX: /* load remaining word count */ - dat = 0; - - case ioMIX: /* merge */ + case ioIOI: /* I/O data input */ if (UNIT_CPU_MODEL == UNIT_2114) /* 2114? */ - dat = dat | (dmac[ch].cw3 & 0017777); /* only 13-bit count */ + data = dmac [ch].cw3 & 0017777; /* only 13-bit count */ else if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* 2115/2116? */ - dat = dat | (dmac[ch].cw3 & 0037777); /* only 14-bit count */ - else - dat = dat | dmac[ch].cw3; /* rest use full value */ - break; + data = dmac [ch].cw3 & 0037777; /* only 14-bit count */ + else /* other models */ + data = dmac [ch].cw3; /* rest use full value */ + break; /* read remaining word count */ - case ioOTX: /* output */ - if (CTL (DMALT0 + ch)) /* word count selected? */ - dmac[ch].cw3 = dat; /* save count */ + case ioIOO: /* I/O data output */ + if (dma_select [ch]) /* word count selected? */ + dmac [ch].cw3 = data; /* save count */ else /* memory address selected */ if (UNIT_CPU_MODEL == UNIT_2114) /* 2114? */ - dmac[ch].cw2 = dat & 0137777; /* 14-bit address */ - else - dmac[ch].cw2 = dat; /* full address stored */ + dmac [ch].cw2 = data & 0137777; /* only 14-bit address */ + else /* other models */ + dmac [ch].cw2 = data; /* full address stored */ break; - case ioCRS: /* control reset */ - case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (DMALT0 + ch); } /* CLC */ - else { setCTL (DMALT0 + ch); } /* STC */ + case ioCLC: /* clear control flip-flop */ + dma_select [ch] = CLEAR; /* set for word count access */ break; - default: + case ioSTC: /* set control flip-flop */ + dma_select [ch] = SET; /* set for memory address access */ break; - } -return dat; + default: /* all other signals */ + break; /* are ignored */ + } + +return data; } -/* Devices 6,7 (primary DMA) I/O routine - Implements control word 1 (device address) and DMA control. +/* DMA/DCPC primary (SC 6/7) I/O signal handler. - The 12607B (2114) stores only bits 2-0 of the select code and interprets them - as select codes 10-16 (SRQ17 is not decoded). The 12578A (2115/6), 12895A - (2100), and 12897B (1000) support the full 10-77 range of select codes. + The primary DMA control interface and the service select register are + manipulated through select codes 6 and 7. Each channel has transfer enable, + control, flag, and flag buffer flip-flops. Transfer enable must be set via + STC to start DMA. Control is used only to enable the DMA completion + interrupt; it is set by STC and cleared by CLC. Flag and flag buffer are set + at transfer completion to signal an interrupt. STF may be issued to abort a + transfer in progress. - The 12578A supports byte-sized transfers by setting bit 14. Bit 14 is - ignored by all other DMA cards, which support word transfers only. + Again, there are hardware differences between the various DMA cards. The + 12607B (2114) stores only bits 2-0 of the select code and interprets them as + select codes 10-16 (SRQ17 is not decoded). The 12578A (2115/16), 12895A + (2100), and 12897B (1000) support the full range of select codes (10-77 + octal). - NOTE: LIx/MIx reads floating S-bus (1 on 21MX, 0 on 211x/2100). + Implementation notes: - NOTE: CRS clears control and command flip-flops, whereas CLC clears only - control. + 1. An IOI reads the floating S-bus (high on the 1000, low on the 21xx). + + 2. The CRS signal on the DMA card resets the secondary (SC 2/3) select + flip-flops. Under simulation, ioCRS is dispatched to select codes 6 and + up, so we reset the flip-flop in our handler. + + 3. The 12578A card does not start the transfer until one instruction after + the STC 6/7 has executed. The diagnostic tests for this, so we + implement a startup latency counter to provide the proper delay. + + 4. The 12578A supports byte-sized transfers by setting bit 14. Bit 14 is + ignored by all other DMA cards, which support word transfers only. + Under simulation, we use a byte-packing/unpacking register to hold one + byte while the other is read or written during the DMA cycle. */ -int32 dmpio (int32 inst, int32 IR, int32 dat) +uint32 dmapio (uint32 select_code, IOSIG signal, uint32 data) { -int32 ch; +const uint32 ch = select_code & 1; /* DMA channel number */ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -ch = IR & 1; /* get channel number */ +switch (base_signal) { /* dispatch base I/O signal */ -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 */ - } + case ioCLF: /* clear flag flip-flop */ + dma_flag [ch] = dma_flagbuf [ch] = CLEAR; /* clear flag and flag buffer */ break; - case ioSFC: /* skip flag clear */ - if (FLG (DMA0 + ch) == 0) PC = (PC + 1) & VAMASK; + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + dma_flag [ch] = dma_flagbuf [ch] = SET; /* set flag and flag buffer */ + dma_xferen [ch] = CLEAR; /* clear transfer enable to abort transfer */ break; - case ioSFS: /* skip flag set */ - if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK; + case ioSFC: /* skip if flag is clear */ + setSKF (!dma_flag [ch]); /* skip if transfer in progress */ break; - case ioLIX: /* load */ - dat = 0; - - case ioMIX: /* merge */ - if (UNIT_CPU_TYPE == UNIT_TYPE_1000) - dat = DMASK; + case ioSFS: /* skip if flag is set */ + setSKF (dma_flag [ch]); /* skip if transfer is complete */ break; - case ioOTX: /* output */ + case ioIOI: /* I/O data input */ + if (UNIT_CPU_TYPE == UNIT_TYPE_1000) /* 1000? */ + data = DMASK; /* return all ones */ + else /* other models */ + data = 0; /* return all zeros */ + break; + + case ioIOO: /* I/O data output */ if (UNIT_CPU_MODEL == UNIT_2114) /* 12607? */ - dmac[ch].cw1 = (dat & 0137707) | 010; /* mask SC, convert to 10-17 */ + dmac [ch].cw1 = (data & 0137707) | 010; /* mask SC, convert to 10-17 */ else if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* 12578? */ - dmac[ch].cw1 = dat; /* store full select code, flags */ + dmac [ch].cw1 = data; /* store full select code, flags */ else /* 12895, 12897 */ - dmac[ch].cw1 = dat & ~DMA1_PB; /* clip byte-packing flag */ + dmac [ch].cw1 = data & ~DMA1_PB; /* clip byte-packing flag */ break; + case ioPOPIO: /* power-on preset to I/O */ + dma_flag [ch] = dma_flagbuf [ch] = SET; /* set flag and flag buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - clrCMD (DMA0 + ch); /* clear command flip-flop */ + dma_xferen [ch] = CLEAR; /* clear transfer enable */ + dma_select [ch] = CLEAR; /* set secondary for word count access */ + /* fall into CLC handler */ - case ioCTL: /* control */ - if (IR & I_CTL) { clrCTL (DMA0 + ch); } /* CLC: cmd unchgd */ - else { /* STC */ - if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* slow DMA card? */ - dmac[ch].latency = 1; /* needs startup latency */ - else - dmac[ch].latency = 0; /* DCPC starts immediately */ - - dmac[ch].packer = 0; /* clear packing register */ - setCTL (DMA0 + ch); /* set ctl, cmd */ - setCMD (DMA0 + ch); - } + case ioCLC: /* clear control flip-flop */ + dma_control [ch] = CLEAR; /* clear control */ break; - default: - break; - } + case ioSTC: /* set control flip-flop */ + if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* slow DMA card? */ + dmac [ch].latency = 1; /* needs startup latency */ + else + dmac [ch].latency = 0; /* DCPC starts immediately */ -if (IR & I_HC) { clrFLG (DMA0 + ch); } /* HC option */ -return dat; + dmac [ch].packer = 0; /* clear packing register */ + dma_xferen [ch] = dma_control [ch] = SET; /* set transfer enable and control */ + break; + + case ioSIR: /* set interrupt request */ + setPRL (select_code, !(dma_control [ch] & dma_flag [ch])); + setIRQ (select_code, dma_control [ch] & dma_flag [ch] & dma_flagbuf [ch]); + break; + + case ioIAK: /* interrupt acknowledge */ + dma_flagbuf [ch] = CLEAR; /* clear flag buffer */ + break; + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + dmapio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + dmapio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + +/* Unassigned select code I/O signal handler. + + The 21xx/1000 I/O structure requires that no empty slots exist between + interface cards. This is due to the hardware priority chaining (PRH/PRL). + If it is necessary to leave unused I/O slots, HP 12777A Priority Jumper Cards + must be installed in them to maintain priority continuity. + + Under simulation, every unassigned I/O slot behaves as though a 12777A were + resident. + + Implementation notes: + + 1. For select codes < 10 octal, an IOI reads the floating S-bus (high on + the 1000, low on the 21xx). For select codes >= 10 octal, an IOI reads + the floating I/O bus (low on all machines). + + 2. If "stop_dev" is TRUE, then the simulator will stop when an unassigned + device is accessed. +*/ + +uint32 nullio (uint32 select_code, IOSIG signal, uint32 data) +{ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ + +switch (base_signal) { /* dispatch base I/O signal */ + + case ioIOI: /* I/O data input */ + if ((select_code < VARDEV) && /* internal device */ + (UNIT_CPU_TYPE == UNIT_TYPE_1000)) /* and 1000? */ + data = DMASK; /* return all ones */ + else /* external or other model */ + data = 0; /* return all zeros */ + break; + + default: /* all other signals */ + break; /* are ignored */ + } + +return (stop_dev << IOT_V_REASON) | data; /* flag missing device */ +} + + /* DMA cycle routine The 12578A card supports byte-packing. If bit 14 in control word 1 is set, @@ -2113,19 +2964,30 @@ return dat; operations in order to transfer sequential bytes to/from the device. The last cycle (word count reaches 0) logic is quite tricky. + Input cases: - CLC requested: issue CLC + Output cases: - neither STC nor CLC requested: issue CLF - STC requested but not CLC: issue STC,C - CLC requested but not STC: issue CLC,C - STC and CLC both requested: issue STC,C and CLC,C, in that order - Either: issue EDT (pass DMA channel number and I/O flag) + + Either case: issue EDT + + Implementation notes: + + 1. The EDT signal is sent to the device signal handler with the "data" + parameter set to ioIOI or ioIOO to indicate the completion of an input or + output transfer, respectively. The IPL device is the only one that uses + this (at the moment). */ -void dma_cycle (uint32 ch, uint32 map) +static void dma_cycle (uint32 ch, uint32 map) { -int32 temp, dev, MA; +uint32 temp, dev; +int32 MA; int32 inp = dmac[ch].cw2 & DMA2_OI; /* input flag */ int32 byt = dmac[ch].cw1 & DMA1_PB; /* pack bytes flag */ @@ -2138,7 +3000,7 @@ dev = dmac[ch].cw1 & I_DEVMASK; /* get device */ MA = dmac[ch].cw2 & VAMASK; /* get mem addr */ if (inp) { /* input cycle? */ - temp = devdisp (dev, ioLIX, dev, 0); /* do LIA dev */ + temp = devdisp (dev, ioIOI, 0); /* do I/O input */ if (byt) { /* byte packing? */ if (dmac[ch].packer & DMA_OE) { /* second byte? */ @@ -2169,7 +3031,7 @@ else { /* output cycle */ else /* no byte packing */ temp = ReadIO (MA, map); /* read word data */ - devdisp (dev, ioOTX, dev, temp); /* do OTA dev */ + devdisp (dev, ioIOO, temp); /* do I/O output */ } if ((dmac[ch].packer & DMA_OE) == 0) { /* new byte or no packing? */ @@ -2180,81 +3042,69 @@ if ((dmac[ch].packer & DMA_OE) == 0) { /* new byte or no packin 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 */ + devdisp (dev, ioSTC + ioCLF, 0); /* do STC,C dev */ + else devdisp (dev, ioCLF, 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 */ + devdisp (dev, ioCLC, 0); /* yes */ } /* end input */ else { /* output */ if ((dmac[ch].cw1 & (DMA1_STC | DMA1_CLC)) == 0) - devdisp (dev, ioFLG, I_HC + dev, 0); /* clear flag */ + devdisp (dev, ioCLF, 0); /* clear flag */ if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ - devdisp (dev, ioCTL, I_HC + dev, 0); /* do STC,C dev */ + devdisp (dev, ioSTC + ioCLF, 0); /* do STC,C dev */ if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ - devdisp (dev, ioCTL, I_HC + I_CTL + dev, 0); /* yes */ + devdisp (dev, ioCLC + ioCLF, 0); /* yes */ } /* end output */ - setFLG (DMA0 + ch); /* set DMA flg */ - clrCMD (DMA0 + ch); /* clr DMA cmd */ - devdisp (dev, ioEDT, dev, inp | ch); /* do EDT */ + + dmapio (DMA0 + ch, ioENF, 0); /* set DMA channel flag */ + devdisp (dev, ioEDT, (uint32) (inp ? ioIOI : ioIOO)); /* send EDT to device */ } return; } -/* Unimplemented device routine - NOTE: For SC < 10, LIx/MIx reads floating S-bus (-1 on 21MX, 0 on 211x/2100). - For SC >= 10, LIx/MIx reads floating I/O bus (0 on all machines). +/* Reset routines. + + The reset routines are called to simulate either an initial power on + condition or a front-panel PRESET button press. For initial power on + (corresponds to PON signal assertion in the CPU), the "P" command switch will + be set. For PRESET (corresponds to POPIO and CRS assertion), the switch will + be clear. + + SCP delivers a power-on reset to all devices when the simulator is started. + A RUN, BOOT, RESET, or RESET ALL command delivers a PRESET to all devices. A + RESET delivers a PRESET to a specific device. */ -int32 nulio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +/* CPU reset. - case ioSFC: /* skip flag clear */ - PC = (PC + 1) & VAMASK; - break; + If this is the first call after simulator startup, allocate the initial + memory array, set the default CPU model, and install the default BBL. - case ioLIX: /* load */ - dat = 0; + A PON reset initializes certain CPU registers. The 1000 series does a + microcoded memory clear and leaves the T and P registers set as a result. - case ioMIX: /* merge */ - if ((devd < VARDEV) && (UNIT_CPU_TYPE == UNIT_TYPE_1000)) - dat = DMASK; - break; + Front-panel PRESET performs additional initialization. We also handle MEM + preset here. - default: - break; - } - -return (stop_dev << IOT_V_REASON) | dat; -} - -/* Reset routines */ + Because PRESET is dispatched to every device separately, each of which will + handle POPIO and CRS in response, we do not need to dispatch POPIO ourselves. +*/ t_stat cpu_reset (DEVICE *dptr) { -E = 0; -O = 0; -ion = ion_defer = 0; -clrCMD (PWR); -clrCTL (PWR); -clrFLG (PWR); -clrFBF (PWR); -dev_srq[0] = dev_srq[0] & ~M_FXDEV; -dms_enb = dms_ump = 0; /* init DMS */ -dms_sr = 0; -dms_vr = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -sim_brk_types = ALL_BKPTS; -sim_brk_dflt = SWMASK ('N'); /* type is nomap as DMS is off */ +if (M == NULL) { /* initial call after startup? */ + pcq_r = find_reg ("PCQ", NULL, dptr); /* get PC queue pointer */ + + if (pcq_r) /* defined? */ + pcq_r->qptr = 0; /* initialize queue */ + else /* not defined */ + return SCPE_IERR; /* internal error */ -if (M == NULL) { /* initial call? */ M = calloc (PASIZE, sizeof (uint16)); /* alloc mem */ if (M == NULL) /* alloc fail? */ @@ -2267,70 +3117,112 @@ if (M == NULL) { /* initial call? */ cpu_set_ldr (NULL, FALSE, NULL, NULL); /* disable loader (was enabled) */ SR = 0; /* clear S */ sim_vm_post = &hp_post_cmd; /* set cmd post proc */ + sim_brk_types = ALL_BKPTS; /* register allowed breakpoint types */ } -} + } + +if (sim_switches & SWMASK ('P')) { /* PON reset? */ + AR = 0; /* clear A register */ + BR = 0; /* clear B register */ + SR = 0; /* clear S register */ + TR = 0; /* clear T register */ + E = 1; /* set E register */ + + if (UNIT_CPU_FAMILY == UNIT_FAMILY_1000) { /* 1000 series? */ + memset (M, 0, MEMSIZE * 2); /* zero allocated memory */ + MR = 0077777; /* set M register */ + PC = 0100000; /* set P register */ + } + + else { /* 21xx series */ + MR = 0; /* clear M register */ + PC = 0; /* clear P register */ + } + } + +O = 0; /* PRESET: clear O register */ +ion = CLEAR; /* PRESET: turn off interrupt system */ +ion_defer = FALSE; /* PRESET: clear interrupt deferral */ + +dms_enb = 0; /* POPIO: turn DMS off */ +dms_ump = 0; /* POPIO: init to system map */ +dms_sr = 0; /* POPIO: clear status register and BP fence */ +dms_vr = 0; /* POPIO: clear violation register */ + +sim_brk_dflt = SWMASK ('N'); /* type is nomap as DMS is off */ -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; return SCPE_OK; } + +/* Memory protect reset */ + t_stat mp_reset (DEVICE *dptr) { -clrCTL (PRO); -clrFLG (PRO); -clrFBF (PRO); -mp_fence = 0; /* init mprot */ -mp_viol = 0; -mp_mevff = 0; -mp_evrff = 1; +protio (PRO, ioPOPIO, 0); /* send POPIO signal */ + +mp_fence = 0; /* clear fence register */ +mp_viol = 0; /* clear violation register */ + return SCPE_OK; } + +/* DMA channel 1 reset */ + t_stat dma0_reset (DEVICE *tptr) { if (UNIT_CPU_MODEL != UNIT_2114) /* 2114 has only one channel */ hp_enbdis_pair (&dma0_dev, &dma1_dev); /* make pair cons */ -clrCMD (DMA0); -clrCTL (DMA0); -setFLG (DMA0); -clrSRQ (DMA0); -clrCTL (DMALT0); -dmac[0].latency = dmac[0].packer = 0; -if (sim_switches & SWMASK ('P')) /* power up? */ - dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; + +if (sim_switches & SWMASK ('P')) /* PON reset? */ + dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; /* clear control word registers */ + +dmapio (DMA0, ioPOPIO, 0); /* send POPIO signal */ + +dmac[0].latency = dmac[0].packer = 0; /* clear latency and byte packer */ return SCPE_OK; } + +/* DMA channel 2 reset */ + t_stat dma1_reset (DEVICE *tptr) { if (UNIT_CPU_MODEL != UNIT_2114) /* 2114 has only one channel */ hp_enbdis_pair (&dma1_dev, &dma0_dev); /* make pair cons */ -clrCMD (DMA1); -clrCTL (DMA1); -setFLG (DMA1); -clrSRQ (DMA1); -clrCTL (DMALT1); -dmac[1].latency = dmac[1].packer = 0; -if (sim_switches & SWMASK ('P')) /* power up? */ - dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; + +if (sim_switches & SWMASK ('P')) /* PON reset? */ + dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; /* clear control word registers */ + +dmapio (DMA1, ioPOPIO, 0); /* send POPIO signal */ + +dmac[1].latency = dmac[1].packer = 0; /* clear latency and byte packer */ return SCPE_OK; } + /* Memory examine */ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -int32 d; +uint16 d; if ((sw & ALL_MAPMODES) && (dms_enb == 0)) /* req map with DMS off? */ return SCPE_NOFNC; /* command not allowed */ -addr = dms_cons (addr, sw); -if (addr >= MEMSIZE) return SCPE_NXM; -if (!(sw & SIM_SW_REST) && (addr == 0)) d = saved_AR; -else if (!(sw & SIM_SW_REST) && (addr == 1)) d = saved_BR; -else d = M[addr]; -if (vptr != NULL) *vptr = d & DMASK; + +addr = dms_cons (addr, sw); /* translate address as indicated */ + +if (addr >= MEMSIZE) /* beyond memory limits? */ + return SCPE_NXM; /* non-existent memory */ + +if ((sw & SIM_SW_REST) || (addr >= 2)) /* restoring or memory access? */ + d = M[addr]; /* return memory value */ +else /* not restoring and A/B access */ + d = ABREG[addr]; /* return A/B register value */ + +if (vptr != NULL) + *vptr = d & DMASK; /* store return value */ return SCPE_OK; } @@ -2340,49 +3232,20 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { if ((sw & ALL_MAPMODES) && (dms_enb == 0)) /* req map with DMS off? */ return SCPE_NOFNC; /* command not allowed */ -addr = dms_cons (addr, sw); -if (addr >= MEMSIZE) return SCPE_NXM; -if (!(sw & SIM_SW_REST) && (addr == 0)) saved_AR = val & DMASK; -else if (!(sw & SIM_SW_REST) && (addr == 1)) saved_BR = val & DMASK; -else M[addr] = val & DMASK; + +addr = dms_cons (addr, sw); /* translate address as indicated */ + +if (addr >= MEMSIZE) /* beyond memory limits? */ + return SCPE_NXM; /* non-existent memory */ + +if ((sw & SIM_SW_REST) || (addr >= 2)) /* restoring or memory access? */ + M[addr] = val & DMASK; /* store memory value */ +else /* not restoring and A/B access */ + ABREG[addr] = val & DMASK; /* store A/B register value */ + return SCPE_OK; } -/* Set device number */ - -t_stat hp_setdev (UNIT *uptr, int32 num, char *cptr, void *desc) -{ -DEVICE *dptr = (DEVICE *) desc; -DIB *dibp; -int32 i, newdev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((desc == NULL) || (num > 1)) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newdev = get_uint (cptr, 8, I_DEVMASK - num, &r); -if (r != SCPE_OK) return r; -if (newdev < VARDEV) return SCPE_ARG; -for (i = 0; i <= num; i++, dibp++) dibp->devno = newdev + i; -return SCPE_OK; -} - -/* Show device number */ - -t_stat hp_showdev (FILE *st, UNIT *uptr, int32 num, void *desc) -{ -DEVICE *dptr = (DEVICE *) desc; -DIB *dibp; -int32 i; - -if ((desc == NULL) || (num > 1)) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -fprintf (st, "devno=%o", dibp->devno); -for (i = 1; i <= num; i++) fprintf (st, "/%o", dibp->devno + i); -return SCPE_OK; -} /* Make a pair of devices consistent */ @@ -2393,6 +3256,7 @@ else dcp->flags = dcp->flags & ~DEV_DIS; return; } + /* VM command post-processor Update T register to contents of memory addressed by M register @@ -2407,9 +3271,10 @@ if (MR != saved_MR) { /* M changed since last return; } + /* Test for device conflict */ -t_bool dev_conflict (void) +static t_bool dev_conflict (void) { DEVICE *dptr; DIB *dibp; @@ -2454,6 +3319,7 @@ if (is_conflict) { return is_conflict; } + /* Change CPU memory size. On a 21xx, move the current loader to the top of the new memory size. Then @@ -2496,6 +3362,7 @@ for (i = fwanxm; i < old_size; i++) M[i] = 0; /* zero non-existent mem return SCPE_OK; } + /* Change CPU models. For convenience, MP and DMA are typically enabled if available; they may be @@ -2587,6 +3454,7 @@ if (result == SCPE_OK) /* memory change OK? */ return result; } + /* Display the CPU model and optional loader status. Loader status is displayed for 21xx models and suppressed for 1000 models. @@ -2604,10 +3472,12 @@ if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) /* valid only for 21xx * return SCPE_OK; } + /* Set a CPU option. Validation: - Checks that the current CPU model supports the option selected. + - If CPU is 1000-F, ensures that VIS and IOP are mutually exclusive. - If CPU is 2100, ensures that FP/FFP and IOP are mutually exclusive. - If CPU is 2100, ensures that FP is enabled if FFP enabled (FP is required for FFP installation). @@ -2630,9 +3500,16 @@ if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { uptr->flags = uptr->flags | UNIT_FP; } +else if (UNIT_CPU_MODEL == UNIT_1000_F) + if (option == UNIT_VIS) /* 1000-F IOP and VIS options */ + uptr->flags = uptr->flags & ~UNIT_IOP; /* are mutually exclusive */ + else if (option == UNIT_IOP) + uptr->flags = uptr->flags & ~UNIT_VIS; + return SCPE_OK; } + /* Clear a CPU option. Validation: @@ -2658,6 +3535,7 @@ if ((UNIT_CPU_TYPE == UNIT_TYPE_2100) && /* disabling 2100 FP? */ return SCPE_OK; } + /* 21xx loader enable/disable function. The 21xx CPUs store their initial binary loaders in the last 64 words of @@ -2673,7 +3551,7 @@ return SCPE_OK; Under simulation, we keep both a total configured memory size (MEMSIZE) and a current configured memory size (fwanxm = "first word address of non-existent - memory). When the two are equal, the loader is enabled. When the current + memory"). When the two are equal, the loader is enabled. When the current size is less than the total size, the loader is disabled. Disabling the loader copies the last 64 words to a shadow array, zeros the @@ -2689,7 +3567,7 @@ return SCPE_OK; t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc) { -static uint16 loader[IBL_LNT]; +static BOOT_ROM loader; int32 i; t_bool is_enabled = (fwanxm == MEMSIZE); @@ -2714,12 +3592,40 @@ else if ((!is_enabled) && (enable == 1)) { /* enable loader? */ return SCPE_OK; } + +/* Idle set/clear. + + Idling must have a calibrated clock before sleeping, or the TBG rate will + be wrong. When we handle a SET CPU IDLE, we want to... + + ...do something to allow the clock to stabilize before actually enabling. + Probably set sim_idle_enab immediately, so idling is reported as on, but + don't actually call sim_idle() until clock stabilizes. Maybe "cpu_idle" = 0 + and then = 1 after 100 clocks? + */ + +t_stat cpu_set_idle (UNIT *uptr, int32 option, char *cptr, void *desc) +{ + if (option) + return sim_set_idle (uptr, 10, NULL, NULL); + else + return sim_clr_idle (uptr, 0, NULL, NULL); +} + + +/* Idle display */ + +t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc) +{ + return sim_show_idle (st, uptr, val, desc); +} + + /* IBL routine (CPU boot) */ t_stat cpu_boot (int32 unitno, DEVICE *dptr) { -extern const uint16 ptr_rom[IBL_LNT], dq_rom[IBL_LNT]; -extern const uint16 ms_rom[IBL_LNT], ds_rom[IBL_LNT]; +extern const BOOT_ROM ptr_rom, dq_rom, ms_rom, ds_rom; int32 dev = (SR >> IBL_V_DEV) & I_DEVMASK; int32 sel = (SR >> IBL_V_SEL) & IBL_M_SEL; @@ -2746,6 +3652,7 @@ switch (sel) { return SCPE_OK; } + /* IBL boot ROM copy - Use memory size to set the initial PC and base of the boot area @@ -2758,7 +3665,7 @@ return SCPE_OK; devices requiring two codes) */ -t_stat ibl_copy (const uint16 pboot[IBL_LNT], int32 dev) +t_stat ibl_copy (const BOOT_ROM rom, int32 dev) { int32 i; uint16 wd; @@ -2768,14 +3675,14 @@ cpu_set_ldr (NULL, TRUE, NULL, NULL); /* enable loader (ignore 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 */ + wd = rom[i]; /* get word */ if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */ ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ - (I_GETIOOP (wd) != ioHLT)) /* not a HALT? */ + (I_GETIOOP (wd) != soHLT)) /* 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 */ +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 60eaa550..707c4af0 100644 --- a/HP2100/hp2100_cpu.h +++ b/HP2100/hp2100_cpu.h @@ -23,6 +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. + 15-Jul-08 JDB Rearranged declarations with hp2100_cpu.c and hp2100_defs.h + 26-Jun-08 JDB Added mp_control to CPU state externals 24-Apr-08 JDB Added calc_defer() prototype 20-Apr-08 JDB Added DEB_VIS and DEB_SIG debug flags 26-Nov-07 JDB Added extern sim_deb, cpu_dev, DEB flags for debug printouts @@ -46,6 +48,9 @@ #ifndef _HP2100_CPU_H_ #define _HP2100_CPU_H_ 0 +#include + + /* CPU model definition flags */ #define CPU_V_SERIES 0 @@ -171,12 +176,98 @@ #define PCQ_MASK (PCQ_SIZE - 1) #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = err_PC -/* simulator state */ +/* Memory reference instructions */ -extern FILE *sim_deb; +#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_ASKP 0002000 /* alter/skip */ +#define I_IO 0102000 /* I/O */ +#define I_CTL 0004000 /* CTL on/off */ +#define I_HC 0001000 /* hold/clear */ +#define I_DEVMASK 0000077 /* device select code mask */ +#define I_GETIOOP(x) (((x) >> 6) & 07) /* I/O sub op */ + +/* Instruction masks */ + +#define I_MRG 0074000 /* MRG instructions */ +#define I_MRG_I (I_MRG | I_IA) /* MRG indirect instruction group */ +#define I_JSB 0014000 /* JSB instruction */ +#define I_JSB_I (I_JSB | I_IA) /* JSB,I instruction */ +#define I_JMP 0024000 /* JMP instruction */ +#define I_ISZ 0034000 /* ISZ instruction */ + +#define I_IOG 0107700 /* I/O group instruction */ +#define I_SFS 0102300 /* SFS instruction */ +#define I_STF 0102100 /* STF instruction */ + +/* 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) /* page offset */ +#define VA_M_PAG ((1 << VA_N_PAG) - 1) /* page mask */ +#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 */ + +/* DMS map entries */ + +#define MAP_V_RPR 15 /* read prot */ +#define MAP_V_WPR 14 /* write prot */ +#define RDPROT (1 << MAP_V_RPR) /* read access check */ +#define WRPROT (1 << MAP_V_WPR) /* write access check */ +#define NOPROT 0 /* no access check */ +#define MAP_RSVD 0036000 /* reserved bits */ +#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) + +/* MEM status register */ + +#define MST_ENBI 0100000 /* MEM enabled at interrupt */ +#define MST_UMPI 0040000 /* User map selected at inerrupt */ +#define MST_ENB 0020000 /* MEM enabled currently */ +#define MST_UMP 0010000 /* User map selected currently */ +#define MST_PRO 0004000 /* Protected mode enabled currently */ +#define MST_FLT 0002000 /* Base page portion mapped */ +#define MST_FENCE 0001777 /* Base page fence */ + +/* MEM 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 */ /* CPU registers */ +#define AR ABREG[0] /* A = reg 0 */ +#define BR ABREG[1] /* B = reg 1 */ + extern uint16 ABREG[2]; /* A/B regs (use AR/BR) */ extern uint32 PC; /* P register */ extern uint32 SR; /* S register */ @@ -186,47 +277,53 @@ extern uint32 XR; /* X register */ extern uint32 YR; /* Y register */ extern uint32 E; /* E register */ extern uint32 O; /* O register */ -extern uint32 dev_ctl[2]; /* device control */ /* CPU state */ -extern uint32 err_PC; -extern uint32 dms_enb; -extern uint32 dms_ump; -extern uint32 dms_sr; -extern uint32 dms_vr; -extern uint32 mp_fence; -extern uint32 mp_viol; -extern uint32 mp_mevff; -extern uint32 iop_sp; -extern uint32 ion_defer; -extern uint32 intaddr; -extern uint16 pcq[PCQ_SIZE]; -extern uint32 pcq_p; -extern uint32 stop_inst; -extern UNIT cpu_unit; -extern DEVICE cpu_dev; +extern uint32 err_PC; +extern uint32 dms_enb; +extern uint32 dms_ump; +extern uint32 dms_sr; +extern uint32 dms_vr; +extern uint32 mp_control; +extern uint32 mp_fence; +extern uint32 mp_viol; +extern uint32 mp_mevff; +extern uint32 iop_sp; +extern t_bool ion_defer; +extern uint32 intaddr; +extern uint16 pcq [PCQ_SIZE]; +extern uint32 pcq_p; +extern uint32 stop_inst; +extern UNIT cpu_unit; +extern DEVICE cpu_dev; +extern jmp_buf save_env; /* CPU functions */ -t_stat resolve (uint32 MA, uint32 *addr, uint32 irq); -uint8 ReadB (uint32 addr); -uint8 ReadBA (uint32 addr); -uint16 ReadW (uint32 addr); -uint16 ReadWA (uint32 addr); -uint16 ReadIO (uint32 addr, uint32 map); -void WriteB (uint32 addr, uint32 dat); -void WriteBA (uint32 addr, uint32 dat); -void WriteW (uint32 addr, uint32 dat); -void WriteWA (uint32 addr, uint32 dat); -void WriteIO (uint32 addr, uint32 dat, uint32 map); -t_stat iogrp (uint32 ir, uint32 iotrap); -uint32 calc_int (void); -uint32 calc_defer (void); -void mp_dms_jmp (uint32 va); -uint16 dms_rmap (uint32 mapi); -void dms_wmap (uint32 mapi, uint32 dat); -void dms_viol (uint32 va, uint32 st); -uint32 dms_upd_sr (void); +#define MP_ABORT(va) longjmp (save_env, (va)) + +extern t_stat resolve (uint32 MA, uint32 *addr, uint32 irq); +extern uint16 ReadPW (uint32 pa); +extern uint8 ReadB (uint32 va); +extern uint8 ReadBA (uint32 va); +extern uint16 ReadW (uint32 va); +extern uint16 ReadWA (uint32 va); +extern uint16 ReadIO (uint32 va, uint32 map); +extern void WritePW (uint32 pa, uint32 dat); +extern void WriteB (uint32 va, uint32 dat); +extern void WriteBA (uint32 va, uint32 dat); +extern void WriteW (uint32 va, uint32 dat); +extern void WriteWA (uint32 va, uint32 dat); +extern void WriteIO (uint32 va, uint32 dat, uint32 map); +extern t_stat iogrp (uint32 ir, uint32 iotrap); +extern uint32 calc_int (void); +extern t_bool calc_defer (void); +extern void mp_dms_jmp (uint32 va, uint32 plb); +extern uint16 dms_rmap (uint32 mapi); +extern void dms_wmap (uint32 mapi, uint32 dat); +extern void dms_viol (uint32 va, uint32 st); +extern uint32 dms_upd_vr (uint32 va); +extern uint32 dms_upd_sr (void); #endif diff --git a/HP2100/hp2100_cpu0.c b/HP2100/hp2100_cpu0.c index ad1dc33c..df199de2 100644 --- a/HP2100/hp2100_cpu0.c +++ b/HP2100/hp2100_cpu0.c @@ -1,4 +1,4 @@ -/* hp2100_cpu0.c: HP 1000 unimplemented instruction set stubs +/* hp2100_cpu0.c: HP 1000 user microcode and unimplemented instruction set stubs Copyright (c) 2006-2008, J. David Bryan @@ -23,19 +23,18 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. - CPU0 Unimplemented firmware option instructions + CPU0 User microcode and unimplemented firmware options + 18-Sep-08 JDB .FLUN and self-tests for VIS and SIGNAL are NOP if not present + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) + Added "user microcode" dispatcher for unclaimed instructions 26-Feb-08 HV Removed and implemented "cpu_vis" and "cpu_signal" 22-Nov-07 JDB Removed and implemented "cpu_rte_ema" 12-Nov-07 JDB Removed and implemented "cpu_rte_vma" and "cpu_rte_os" 01-Dec-06 JDB Removed and implemented "cpu_sis". 26-Sep-06 JDB Created - This file contains template simulations for the firmware options that have - not yet been implemented. When a given firmware option is implemented, it - should be moved out of this file and into another (or its own, depending on - complexity). - Primary references: - HP 1000 M/E/F-Series Computers Technical Reference Handbook (5955-0282, Mar-1980) @@ -46,17 +45,26 @@ Additional references are listed with the associated firmware implementations, as are the HP option model numbers pertaining to the applicable CPUs. + + + This file contains template simulations for the firmware options that have + not yet been implemented. When a given firmware option is implemented, it + should be moved out of this file and into another (or its own, depending on + complexity). + + It also contains a user-microprogram dispatcher to allow simulation of + site-specific firmware. All UIG instructions unclaimed by installed firmware + options are directed here and may be simulated by writing the appropriate + code. */ + #include "hp2100_defs.h" #include "hp2100_cpu.h" #include "hp2100_cpu1.h" -t_stat cpu_ds (uint32 IR, uint32 intrq); /* Distributed System */ - - -/* Distributed System +/* Distributed System. Distributed System firmware was provided with the HP 91740A DS/1000 product for use with the HP 12771A (12665A) Serial Interface and 12773A Modem @@ -100,9 +108,9 @@ t_stat cpu_ds (uint32 IR, uint32 intrq); /* Distributed System */ Additional references (documents unavailable): - HP 91740A M-Series Distributed System (DS/1000) Firmware Installation - Manual (91740-90007). + Manual (91740-90007). - HP 91740B Distributed System (DS/1000) Firmware Installation Manual - (91740-90009). + (91740-90009). */ static const OP_PAT op_ds[16] = { @@ -118,9 +126,6 @@ t_stat reason = SCPE_OK; OPS op; uint32 entry; -if ((cpu_unit.flags & UNIT_DS) == 0) /* DS option installed? */ - return stop_inst; - entry = IR & 017; /* mask to entry point */ if (op_ds[entry] != OP_N) @@ -131,7 +136,130 @@ switch (entry) { /* decode IR<3:0> */ default: /* others undefined */ reason = stop_inst; - } + } + +return reason; +} + + +/* User firmware dispatcher. + + All UIG instructions unclaimed by installed firmware options are directed + here. User- or site-specific firmware may be simulated by dispatching to the + appropriate simulator routine. Unimplemented instructions should return + "stop_inst" to cause a simulator stop if enabled. + + Implementation notes: + + 1. This routine may be passed any opcode in the ranges 101400-101737 and + 105000-105737. The 10x740-777 range is dedicated to the EIG instructions + and is unavailable for user microprograms. + + 2. HP operating systems and subsystems depend on the following instructions + to execute as NOP and return success if the corresponding firmware is not + installed: + + 105226 -- Fast FORTRAN Processor .FLUN instruction + 105355 -- RTE-6/VM OS self-test instruction + 105477 -- Vector Instruction Set self-test + 105617 -- SIGNAL/1000 self-test + + These instructions are executed to determine firmware configuration + dynamically. If you use any of these opcodes for your own use, be aware + that certain HP programs may fail. + + 3. User microprograms occupied one or more firmware modules, each containing + 16 potential instruction entry points. A skeleton dispatcher for the 32 + possible modules is implemented below, along with a sample module. +*/ + +t_stat cpu_user (uint32 IR, uint32 intrq) +{ +t_stat reason = SCPE_OK; + +if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* 2116/15/14 CPU? */ + return stop_inst; /* user microprograms not supported */ + +switch (IR) { /* opcodes for firmware detection */ + case 0105226: /* FFP .FLUN */ + case 0105355: /* RTE-6/VM OS self-test */ + case 0105477: /* VIS self-test */ + case 0105617: /* SIGNAL/1000 self-test */ + return SCPE_OK; /* execute as NOP */ + } + +switch ((IR >> 4) & 037) { /* decode IR<8:4> */ + +/* case 000: /* 105000-105017 */ +/* return cpu_user_00 (IR, intrq); /* uncomment to handle instruction */ + +/* case 001: /* 105020-105037 */ +/* return cpu_user_01 (IR, intrq); /* uncomment to handle instruction */ + +/* case 0nn: /* other cases as needed */ +/* return cpu_user_nn (IR, intrq); /* uncomment to handle instruction */ + + case 020: /* 10x400-10x417 */ + return cpu_user_20 (IR, intrq); /* call sample dispatcher */ + +/* case 021: /* 10x420-10x437 */ +/* return cpu_user_21 (IR, intrq); /* uncomment to handle instruction */ + +/* case 0nn: /* other cases as needed */ +/* return cpu_user_nn (IR, intrq); /* uncomment to handle instruction */ + + default: /* others undefined */ + reason = stop_inst; + } + +return reason; +} + + +/* Example user microprogram simulator. + + User- or site-specific firmware may be simulated by writing the appropriate + code below. Unimplemented instructions should return "stop_inst" to cause a + simulator stop if enabled. + + For information on the operand patterns used in the "op_user" array, see the + comments preceding the "cpu_ops" routine in "hp2100_cpu1.c" and the "operand + processing encoding" constants in "hp2100_cpu1.h". +*/ + +static const OP_PAT op_user_20[16] = { + OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */ + OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */ + OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */ + OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */ + }; + +t_stat cpu_user_20 (uint32 IR, uint32 intrq) +{ +t_stat reason = SCPE_OK; +OPS op; +uint32 entry; + +entry = IR & 017; /* mask to entry point */ + +if (op_user_20 [entry] != OP_N) + if (reason = cpu_ops (op_user_20 [entry], op, intrq)) /* get instruction operands */ + return reason; + +switch (entry) { /* decode IR<4:0> */ + + case 000: /* 10x400 */ +/* break; /* uncomment to handle instruction */ + + case 001: /* 10x401 */ +/* break; /* uncomment to handle instruction */ + +/* case 0nn: /* other cases as needed */ +/* break; /* uncomment to handle instruction */ + + default: /* others undefined */ + reason = stop_inst; + } return reason; } diff --git a/HP2100/hp2100_cpu1.c b/HP2100/hp2100_cpu1.c index e4eb4d6f..d176db83 100644 --- a/HP2100/hp2100_cpu1.c +++ b/HP2100/hp2100_cpu1.c @@ -25,6 +25,9 @@ CPU1 Extended arithmetic and optional microcode dispatchers + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Moved option-present tests to UIG dispatchers + Call "user microcode" dispatcher for unclaimed UIG instructions 20-Apr-08 JDB Fixed VIS and SIGNAL to depend on the FPP and HAVE_INT64 28-Nov-07 JDB Added fprint_ops, fprint_regs for debug printouts 17-Nov-07 JDB Enabled DIAG as NOP on 1000 F-Series @@ -45,31 +48,47 @@ - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation (92851-90001, Mar-1981) - Macro/1000 Reference Manual (92059-90001, Dec-1992) + - HP 93585A Double Integer Firmware Package Installation and Programming + Manual (93585-90007, Feb-1984) Additional references are listed with the associated firmware implementations, as are the HP option model numbers pertaining to the applicable CPUs. + This source file contains the Extended Arithmetic Unit simulator and the User Instruction Group (a.k.a. "Macro") dispatcher for the 2100 and 1000 (21MX) CPUs. The UIG simulators reside in separate source files, due to the large - number of firmware options available for the 1000 machines. Unit flags - indicate which options are present in the current system. + number of firmware options available for these machines. Unit flags indicate + which options are present in the current system. This module also provides generalized instruction operand processing. - The microcode address space of the 2100 encompassed four modules of 256 words + The 2100 and 1000 machines were microprogrammable; the 2116/15/14 machines + were not. Both user- and HP-written microprograms were supported. The + microcode address space of the 2100 encompassed four modules of 256 words each. The 1000 M-series expanded that to sixteen modules, and the 1000 E/F-series expanded that still further to sixty-four modules. Each CPU had its own microinstruction set, although the micromachines of the various 1000 models were similar internally. + The UIG instructions were divided into ranges assigned to HP firmware + options, reserved for future HP use, and reserved for user microprograms. + User microprograms could occupy any range not already used on a given + machine, but in practice, some effort was made to avoid the HP-reserved + ranges. + + User microprogram simulation is supported by routing any UIG instruction not + allocated to an installed firmware option to a user-firmware dispatcher. + Site-specific microprograms may be simulated there. In the absence of such a + simulation, an unimplemented instruction stop will occur. + Regarding option instruction sets, there was some commonality across CPU types. EAU instructions were identical across all models, and the floating point set was the same on the 2100 and 1000. Other options implemented proper instruction supersets (e.g., the Fast FORTRAN Processor from 2100 to 1000-M to 1000-E to 1000-F) or functional equivalence with differing code - points (the 2000 I/O Processor from 2100 to 1000 and extended-precision + points (the 2000 I/O Processor from 2100 to 1000, and the extended-precision floating-point instructions from 1000-E to 1000-F). The 2100 decoded the EAU and UIG sets separately in hardware and supported @@ -95,30 +114,15 @@ The design of the 1000 microinstruction set was such that executing an instruction for which no microcode was present (e.g., executing a FFP instruction when the FFP firmware was not installed) resulted in a NOP. - Under simulation, such execution causes an undefined instruction stop. + Under simulation, such execution causes an undefined instruction stop if + "stop_inst" is non-zero and a NOP otherwise. */ + #include "hp2100_defs.h" #include "hp2100_cpu.h" #include "hp2100_cpu1.h" -#if defined (HAVE_INT64) /* int64 support available */ -extern t_stat cpu_fpp (uint32 IR, uint32 intrq); /* Floating Point Processor */ -extern t_stat cpu_sis (uint32 IR, uint32 intrq); /* Scientific Instruction Set */ -extern t_stat cpu_vis (uint32 IR, uint32 intrq); /* Vector Instruction Set */ -extern t_stat cpu_signal (uint32 IR, uint32 intrq); /* SIGNAL/1000 */ -#else /* int64 support unavailable */ -extern t_stat cpu_fp (uint32 IR, uint32 intrq); /* Firmware Floating Point */ -#endif /* end of int64 support */ - -extern t_stat cpu_ffp (uint32 IR, uint32 intrq); /* Fast FORTRAN Processor */ -extern t_stat cpu_ds (uint32 IR, uint32 intrq); /* Distributed Systems */ -extern t_stat cpu_dbi (uint32 IR, uint32 intrq); /* Double integer */ -extern t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* RTE-4/6 EMA/VMA */ -extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap); /* RTE-6 OS */ -extern t_stat cpu_iop (uint32 IR, uint32 intrq); /* 2000 I/O Processor */ -extern t_stat cpu_dms (uint32 IR, uint32 intrq); /* Dynamic mapping system */ -extern t_stat cpu_eig (uint32 IR, uint32 intrq); /* Extended instruction group */ /* EAU @@ -333,6 +337,7 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */ return reason; } + /* UIG 0 The first User Instruction Group (UIG) encodes firmware options for the 2100 @@ -351,13 +356,9 @@ return reason; 105320-105337 Scientific Instruction Set - - - std 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 - 2100 IOP instructions are remapped to the equivalent 1000 instructions and - dispatched to the UIG 1 module. - - Note that if the 2100 IOP is installed, the only valid UIG instructions are - IOP instructions, as the IOP used the full 2100 microcode addressing space. + If the 2100 IOP is installed, the only valid UIG instructions are IOP + instructions, as the IOP used the full 2100 microcode addressing space. The + IOP dispatcher remaps the 2100 codes to 1000 codes for execution. The F-Series moved the three-word extended real instructions from the FFP range to the base floating-point range and added four-word double real and @@ -366,42 +367,42 @@ return reason; the rest assigned to the floating-point range. Consequently, many instruction codes for the F-Series are different from the E-Series. - Notes: + Implementation notes: - 1. Product 93585A, available from the "Specials" group, added double - integer microcode to the E-Series. The instruction codes were different - from those in the F-Series to avoid conflicting with the E-Series FFP. - HP manual number 93585-90007 documents the double integer instructions, - but no copy of this manual has been found. The Macro/1000 manual - (92059-090001) lists E-Series double integer instructions as occupying - the code points of the F-Series Scientific Instruction Set. + 1. Product 93585A, available from the "Specials" group, added double integer + microcode to the E-Series. The instruction codes were different from + those in the F-Series to avoid conflicting with the E-Series FFP. - 2. To run the double-integer instructions diagnostic in the absence of - 64-bit integer support (and therefore of F-Series simulation), a special - DBI dispatcher may be enabled by defining ENABLE_DIAG during - compilation. This dispatcher will remap the F-Series DBI instructions - to the E-Series codes, so that the F-Series diagnostic may be run. - Because several of the F-Series DBI instruction codes replace M/E-Series - FFP codes, this dispatcher will only operate if FFP is disabled. + 2. To run the double-integer instructions diagnostic in the absence of + 64-bit integer support (and therefore of F-Series simulation), a special + DBI dispatcher may be enabled by defining ENABLE_DIAG during compilation. + This dispatcher will remap the F-Series DBI instructions to the E-Series + codes, so that the F-Series diagnostic may be run. Because several of + the F-Series DBI instruction codes replace M/E-Series FFP codes, this + dispatcher will only operate if FFP is disabled. - Note that enabling the dispatcher will produce non-standard FP behavior. - For example, any code in the range 105000-105017 normally would execute - a FAD instruction. With the dispatcher enabled, 105014 would execute a - .DAD, while the other codes would execute a FAD. Therefore, ENABLE_DIAG - should only be used to run the diagnostic and is not intended for - general use. + Note that enabling the dispatcher will produce non-standard FP behavior. + For example, any code in the range 105000-105017 normally would execute a + FAD instruction. With the dispatcher enabled, 105014 would execute a + .DAD, while the other codes would execute a FAD. Therefore, ENABLE_DIAG + should only be used to run the diagnostic and is not intended for general + use. + + 3. Any instruction not claimed by an installed option will be sent to the + user microcode dispatcher. */ t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap) { if ((cpu_unit.flags & UNIT_IOP) && /* I/O Processor? */ - (UNIT_CPU_TYPE == UNIT_TYPE_2100)) /* 2100 CPU? */ + (UNIT_CPU_TYPE == UNIT_TYPE_2100)) /* and 2100 CPU? */ return cpu_iop (IR, intrq); /* dispatch to IOP */ -#if !defined (HAVE_INT64) && defined (ENABLE_DIAG) /* DBI diagnostic dispatcher wanted */ +#if !defined (HAVE_INT64) && defined (ENABLE_DIAG) /* special DBI diagnostic dispatcher */ -if ((cpu_unit.flags & UNIT_FFP) == 0) +if (((cpu_unit.flags & UNIT_FFP) == 0) && /* FFP absent? */ + (cpu_unit.flags & UNIT_DBI)) /* and DBI present? */ switch (IR & 0377) { case 0014: /* .DAD 105014 */ return cpu_dbi (0105321, intrq); @@ -440,7 +441,7 @@ if ((cpu_unit.flags & UNIT_FFP) == 0) return cpu_dbi (0105333, intrq); } /* otherwise, continue */ -#endif /* end of DBI dispatcher */ +#endif /* end of special DBI dispatcher */ switch ((IR >> 4) & 017) { /* decode IR<7:4> */ @@ -451,37 +452,58 @@ switch ((IR >> 4) & 017) { /* decode IR<7:4> */ case 003: /* 105060-105077 */ case 004: /* 105100-105117 */ case 005: /* 105120-105137 */ + if (cpu_unit.flags & UNIT_FP) /* FP option installed? */ #if defined (HAVE_INT64) /* int64 support available */ - return cpu_fpp (IR, intrq); /* Floating Point Processor */ + return cpu_fpp (IR, intrq); /* Floating Point Processor */ #else /* int64 support unavailable */ - return cpu_fp (IR, intrq); /* Firmware Floating Point */ + return cpu_fp (IR, intrq); /* Firmware Floating Point */ #endif /* end of int64 support */ + else + break; case 010: /* 105200-105217 */ case 011: /* 105220-105237 */ - return cpu_ffp (IR, intrq); /* Fast FORTRAN Processor */ + if (cpu_unit.flags & UNIT_FFP) /* FFP option installed? */ + return cpu_ffp (IR, intrq); /* Fast FORTRAN Processor */ + else + break; case 012: /* 105240-105257 */ - return cpu_rte_vma (IR, intrq); /* RTE-4/6 EMA/VMA */ + if (cpu_unit.flags & UNIT_VMAOS) /* VMA/OS option installed? */ + return cpu_rte_vma (IR, intrq); /* RTE-6 VMA */ + else if (cpu_unit.flags & UNIT_EMA) /* EMA option installed? */ + return cpu_rte_ema (IR, intrq); /* RTE-4 EMA */ + else + break; case 014: /* 105300-105317 */ - return cpu_ds (IR, intrq); /* Distributed System */ + if (cpu_unit.flags & UNIT_DS) /* DS option installed? */ + return cpu_ds (IR, intrq); /* Distributed System */ + else + break; case 015: /* 105320-105337 */ #if defined (HAVE_INT64) /* int64 support available */ if (UNIT_CPU_MODEL == UNIT_1000_F) /* F-series? */ - return cpu_sis (IR, intrq); /* Scientific Instruction */ + return cpu_sis (IR, intrq); /* Scientific Instruction is standard */ else /* M/E-series */ #endif /* end of int64 support */ + if (cpu_unit.flags & UNIT_DBI) /* DBI option installed? */ return cpu_dbi (IR, intrq); /* Double integer */ + else + break; case 016: /* 105340-105357 */ - return cpu_rte_os (IR, intrq, iotrap); /* RTE-6 OS */ + if (cpu_unit.flags & UNIT_VMAOS) /* VMA/OS option installed? */ + return cpu_rte_os (IR, intrq, iotrap); /* RTE-6 OS */ + else + break; } -return stop_inst; /* others undefined */ +return cpu_user (IR, intrq); /* try user microcode */ } + /* UIG 1 The second User Instruction Group (UIG) encodes firmware options for the @@ -490,15 +512,25 @@ return stop_inst; /* others undefined */ Instructions Option Name 1000-M 1000-E 1000-F ------------- ---------------------------- ------ ------ ------ - 10x400-10x437 2000 IOP opt opt - - 10x460-10x477 2000 IOP opt opt - + 10x400-10x437 2000 IOP opt opt opt + 10x460-10x477 2000 IOP opt opt opt 10x460-10x477 Vector Instruction Set - - opt - 105520-105537 Distributed System opt - - - 105600-105617 SIGNAL/1000 Instruction Set - - opt + 10x520-10x537 Distributed System opt - - + 10x600-10x617 SIGNAL/1000 Instruction Set - - opt 10x700-10x737 Dynamic Mapping System opt opt std 10x740-10x777 Extended Instruction Group std std std Only 1000 systems execute these instructions. + + Implementation notes: + + 1. The Distributed System (DS) microcode was mapped to different instruction + ranges for the M-Series and the E/F-Series. The sequence of instructions + was identical, though, so we remap the former range to the latter before + dispatching. + + 2. Any instruction not claimed by an installed option will be sent to the + user microcode dispatcher. */ t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap) @@ -510,35 +542,51 @@ switch ((IR >> 4) & 017) { /* decode IR<7:4> */ case 000: /* 105400-105417 */ case 001: /* 105420-105437 */ - return cpu_iop (IR, intrq); /* 2000 I/O Processor */ + if (cpu_unit.flags & UNIT_IOP) /* IOP option installed? */ + return cpu_iop (IR, intrq); /* 2000 I/O Processor */ + else + break; case 003: /* 105460-105477 */ #if defined (HAVE_INT64) /* int64 support available */ - if (UNIT_CPU_MODEL == UNIT_1000_F) /* F-series? */ + if (cpu_unit.flags & UNIT_VIS) /* VIS option installed? */ return cpu_vis (IR, intrq); /* Vector Instruction Set */ - else /* M/E-series */ + else #endif /* end of int64 support */ + if (cpu_unit.flags & UNIT_IOP) /* IOP option installed? */ return cpu_iop (IR, intrq); /* 2000 I/O Processor */ + else + break; case 005: /* 105520-105537 */ - IR = IR ^ 0000620; /* remap to 105300-105317 */ - return cpu_ds (IR, intrq); /* Distributed System */ + if (cpu_unit.flags & UNIT_DS) { /* DS option installed? */ + IR = IR ^ 0000620; /* remap to 105300-105317 */ + return cpu_ds (IR, intrq); /* Distributed System */ + } + else + break; #if defined (HAVE_INT64) /* int64 support available */ case 010: /* 105600-105617 */ - return cpu_signal (IR, intrq); /* SIGNAL/1000 Instructions */ + if (cpu_unit.flags & UNIT_SIGNAL) /* SIGNAL option installed? */ + return cpu_signal (IR, intrq); /* SIGNAL/1000 Instructions */ + else + break; #endif /* end of int64 support */ case 014: /* 105700-105717 */ case 015: /* 105720-105737 */ - return cpu_dms (IR, intrq); /* Dynamic Mapping System */ + if (cpu_unit.flags & UNIT_DMS) /* DMS option installed? */ + return cpu_dms (IR, intrq); /* Dynamic Mapping System */ + else + break; - case 016: /* 105740-105737 */ + case 016: /* 105740-105757 */ case 017: /* 105760-105777 */ return cpu_eig (IR, intrq); /* Extended Instruction Group */ } -return stop_inst; /* others undefined */ +return cpu_user (IR, intrq); /* try user microcode */ } diff --git a/HP2100/hp2100_cpu1.h b/HP2100/hp2100_cpu1.h index e563443c..52b6a8c5 100644 --- a/HP2100/hp2100_cpu1.h +++ b/HP2100/hp2100_cpu1.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. + 11-Sep-08 JDB Moved microcode function prototypes here 30-Apr-08 JDB Corrected OP_AFF to OP_AAFF for SIGNAL/1000 Removed unused operand patterns 23-Feb-08 HV Added more OP_* for SIGNAL/1000 and VIS @@ -36,7 +37,7 @@ #define _HP2100_CPU1_H_ -/* Register print encoding. */ +/* Register print encoding */ #define REG_COUNT 9 /* count of print flags */ @@ -51,10 +52,11 @@ #define REG_P_REL (1 << 8) /* print P register as relative */ -/* Operand processing encoding. */ +/* Operand processing encoding */ /* Base operand types. Note that all address encodings must be grouped together - after OP_ADR. */ + after OP_ADR. +*/ #define OP_NUL 0 /* no operand */ #define OP_IAR 1 /* 1-word int in A reg */ @@ -85,7 +87,7 @@ #define OP_V_F7 (6 * OP_N_FLAGS) /* 7th operand field */ #define OP_V_F8 (7 * OP_N_FLAGS) /* 8th operand field */ -/* Operand processing patterns. */ +/* Operand processing patterns */ #define OP_N (OP_NUL << OP_V_F1) #define OP_I (OP_IAR << OP_V_F1) @@ -233,13 +235,14 @@ typedef enum { in_s, in_d, fp_f, fp_x, fp_t, fp_e, fp_a } OPSIZE; -/* Conversion from operand size to word count. */ +/* Conversion from operand size to word count */ #define TO_COUNT(s) ((s == fp_a) ? 0 : (uint32) (s + (s < fp_f))) /* HP in-memory representation of a packed floating-point number. - Actual value will use two, three, four, or five words, as needed. */ + Actual value will use two, three, four, or five words, as needed. +*/ typedef uint16 FPK[5]; @@ -264,13 +267,43 @@ typedef OP OPS[OP_N_F]; /* operand array */ typedef uint32 OP_PAT; /* operand pattern */ -/* Microcode dispatcher functions. */ +/* Microcode dispatcher functions (grouped by cpu module number) */ -t_stat cpu_eau (uint32 IR, uint32 intrq); /* EAU group simulator */ -t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); /* UIG group 0 dispatcher */ -t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); /* UIG group 1 dispatcher */ +extern t_stat cpu_ds (uint32 IR, uint32 intrq); /* [0] Distributed System stub */ +extern t_stat cpu_user (uint32 IR, uint32 intrq); /* [0] User firmware dispatcher */ +extern t_stat cpu_user_20 (uint32 IR, uint32 intrq); /* [0] Module 20 user microprograms stub */ -/* Microcode helper functions. */ +extern t_stat cpu_eau (uint32 IR, uint32 intrq); /* [1] EAU group simulator */ +extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); /* [1] UIG group 0 dispatcher */ +extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); /* [1] UIG group 1 dispatcher */ + +#if !defined (HAVE_INT64) /* int64 support unavailable */ +extern t_stat cpu_fp (uint32 IR, uint32 intrq); /* [2] Firmware Floating Point */ +#endif +extern t_stat cpu_dms (uint32 IR, uint32 intrq); /* [2] Dynamic mapping system */ +extern t_stat cpu_eig (uint32 IR, uint32 intrq); /* [2] Extended instruction group */ +extern t_stat cpu_iop (uint32 IR, uint32 intrq); /* [2] 2000 I/O Processor */ + +extern t_stat cpu_ffp (uint32 IR, uint32 intrq); /* [3] Fast FORTRAN Processor */ +extern t_stat cpu_dbi (uint32 IR, uint32 intrq); /* [3] Double-Integer instructions */ + +#if defined (HAVE_INT64) /* int64 support available */ +extern t_stat cpu_fpp (uint32 IR, uint32 intrq); /* [4] Floating Point Processor */ +extern t_stat cpu_sis (uint32 IR, uint32 intrq); /* [4] Scientific Instruction Set */ +#endif + +extern t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* [5] RTE-6 VMA */ +extern t_stat cpu_rte_ema (uint32 IR, uint32 intrq); /* [5] RTE-IV EMA */ + +extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap); /* [6] RTE-6 OS */ + +#if defined (HAVE_INT64) /* int64 support available */ +extern t_stat cpu_vis (uint32 IR, uint32 intrq); /* [7] Vector Instruction Set */ +extern t_stat cpu_signal (uint32 IR, uint32 intrq); /* [7] SIGNAL/1000 Instructions */ +#endif + + +/* Microcode helper functions */ OP ReadOp (uint32 va, OPSIZE precision); /* generalized operand read */ void WriteOp (uint32 va, OP operand, OPSIZE precision); /* generalized operand write */ diff --git a/HP2100/hp2100_cpu2.c b/HP2100/hp2100_cpu2.c index d9ba58de..e5dac17c 100644 --- a/HP2100/hp2100_cpu2.c +++ b/HP2100/hp2100_cpu2.c @@ -1,6 +1,6 @@ /* hp2100_cpu2.c: HP 2100/1000 FP/DMS/EIG/IOP instructions - Copyright (c) 2005-2006, Robert M. Supnik + Copyright (c) 2005-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,11 @@ CPU2 Floating-point, dynamic mapping, extended, and I/O processor instructions + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) + 05-Aug-08 JDB Updated mp_dms_jmp calling sequence + Fixed DJP, SJP, and UJP jump target validation + 30-Jul-08 JDB RVA/B conditionally updates dms_vr before returning value 19-Dec-06 JDB DMS self-test now executes as NOP on 1000-M 01-Dec-06 JDB Substitutes FPP for firmware FP if HAVE_INT64 26-Sep-06 JDB Moved from hp2100_cpu1.c to simplify extensions @@ -54,16 +59,6 @@ #include "hp2100_fp.h" -t_stat cpu_fp (uint32 IR, uint32 intrq); /* Firmware Floating Point */ - -#endif /* int64 support unavailable */ - -t_stat cpu_dms (uint32 IR, uint32 intrq); /* Dynamic mapping system */ -t_stat cpu_eig (uint32 IR, uint32 intrq); /* Extended instruction group */ -t_stat cpu_iop (uint32 IR, uint32 intrq); /* 2000 I/O Processor */ - - -#if !defined (HAVE_INT64) /* int64 support unavailable */ /* Single-Precision Floating Point Instructions @@ -120,9 +115,6 @@ t_stat reason = SCPE_OK; OPS op; uint32 entry; -if ((cpu_unit.flags & UNIT_FP) == 0) /* FP option installed? */ - return stop_inst; - entry = (IR >> 4) & 017; /* mask to entry point */ if (op_fp[entry] != OP_N) @@ -210,21 +202,24 @@ return reason; corresponding instruction, although the 105xxx form is the documented instruction code. - Notes: + Implementation notes: - 1. Instruction code 10x700 will execute the XMM instruction, although - 10x720 is the documented instruction value. + 1. Instruction code 10x700 will execute the XMM instruction, although 10x720 + is the documented instruction value. - 2. Instruction code 10x701 will complement the A or B register, as - indicated, on 1000-E and F-Series machines. This instruction is a NOP - on M-Series machines. + 2. Instruction code 10x701 will complement the A or B register, as + indicated, on 1000-E and F-Series machines. This instruction is a NOP on + M-Series machines. - 3. 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*) + 3. 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*) - 4. The 1000 manual is incorrect in stating that M*I, M*W, XS* are - privileged. + 4. The 1000 manual is incorrect in stating that M*I, M*W, XS* are + privileged. + + 5. The protected memory lower bound for the DJP, SJP, UJP, and JRS + instructions is 2. */ static const OP_PAT op_dms[32] = { @@ -245,9 +240,6 @@ OPS op; uint32 entry, absel; uint32 i, t, mapi, mapj; -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 */ @@ -390,7 +382,7 @@ switch (entry) { /* decode IR<3:0> */ dms_enb = 1; if (op[0].word & 0040000) dms_ump = UMAP; /* set/clr usr */ } - mp_dms_jmp (op[1].word); /* mpck jmp target */ + mp_dms_jmp (op[1].word, 2); /* mpck jmp target */ PCQ_ENTRY; /* save old PC */ PC = op[1].word; /* jump */ ion_defer = 1; /* defer intr */ @@ -473,16 +465,16 @@ switch (entry) { /* decode IR<3:0> */ break; case 031: /* RVA, RVB 10x731 (OP_N) */ - ABREG[absel] = dms_vr; /* save viol */ + ABREG[absel] = dms_upd_vr (err_PC); /* return updated violation register */ 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].word); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0].word; /* new PC */ dms_enb = 0; /* disable map */ dms_ump = SMAP; + mp_dms_jmp (op[0].word, 2); /* validate jump addr */ + PCQ_ENTRY; /* save curr PC */ + PC = op[0].word; /* new PC */ ion_defer = 1; break; @@ -498,11 +490,11 @@ switch (entry) { /* decode IR<3:0> */ case 034: /* SJP 105734 (OP_A) */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - mp_dms_jmp (op[0].word); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0].word; /* jump */ dms_enb = 1; /* enable system */ dms_ump = SMAP; + mp_dms_jmp (op[0].word, 2); /* validate jump addr */ + PCQ_ENTRY; /* save curr PC */ + PC = op[0].word; /* jump */ ion_defer = 1; /* defer intr */ break; @@ -519,11 +511,11 @@ switch (entry) { /* decode IR<3:0> */ case 036: /* UJP 105736 (OP_A) */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - mp_dms_jmp (op[0].word); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0].word; /* jump */ dms_enb = 1; /* enable user */ dms_ump = UMAP; + mp_dms_jmp (op[0].word, 2); /* validate jump addr */ + PCQ_ENTRY; /* save curr PC */ + PC = op[0].word; /* jump */ ion_defer = 1; /* defer intr */ break; @@ -586,11 +578,13 @@ return reason; corresponding instruction, although the 105xxx form is the documented instruction code. - Notes: + Implementation 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. + 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. + + 2. The protected memory lower bound for the JLY and JPY instructions is 0. */ static const OP_PAT op_eig[32] = { @@ -714,7 +708,7 @@ switch (entry) { /* decode IR<4:0> */ break; case 022: /* JLY 105762 (OP_A) */ - mp_dms_jmp (op[0].word); /* validate jump addr */ + mp_dms_jmp (op[0].word, 0); /* validate jump addr */ PCQ_ENTRY; YR = PC; /* ret addr to YR */ PC = op[0].word; /* jump */ @@ -805,7 +799,7 @@ switch (entry) { /* decode IR<4:0> */ case 032: /* JPY 105772 (OP_C) */ op[0].word = (op[0].word + YR) & VAMASK; /* index, no indir */ - mp_dms_jmp (op[0].word); /* validate jump addr */ + mp_dms_jmp (op[0].word, 0); /* validate jump addr */ PCQ_ENTRY; PC = op[0].word; /* jump */ break; @@ -923,14 +917,14 @@ return reason; loaded directly with an OTA/B 05. Also, the 1000 implementation did not offer the MBYTE, MWORD, SBYTE, and LBYTE instructions because the equivalent instructions from the standard Extended Instruction Group were used instead. + Note that the 2100 MBYTE and MWORD instructions operate slightly differently from the 1000 MBT and MVW instructions. Specifically, the move count is signed on the 2100 and unsigned on the 1000. A negative count on the 2100 results in a NOP. - The simulator remaps the 2100 instructions to the 1000 codes. The four EIG equivalents - are dispatched to the EIG simulator. The rest are handled here. Note that the MBT and - MVW instructions operate slightly differently on the 2100; they are + The simulator remaps the 2100 instructions to the 1000 codes. The four EIG + equivalents are dispatched to the EIG simulator. The rest are handled here. Additional reference: - HP 2000 Computer System Sources and Listings Documentation @@ -951,9 +945,6 @@ 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 (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 IOP? */ if ((IR >= 0105020) && (IR <= 0105057)) /* remap LAI */ IR = 0105400 | (IR - 0105020); diff --git a/HP2100/hp2100_cpu3.c b/HP2100/hp2100_cpu3.c index 9f6585a0..028e6857 100644 --- a/HP2100/hp2100_cpu3.c +++ b/HP2100/hp2100_cpu3.c @@ -25,6 +25,9 @@ CPU3 Fast FORTRAN and Double Integer instructions + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) + 05-Aug-08 JDB Updated mp_dms_jmp calling sequence 27-Feb-08 JDB Added DBI self-test instruction 23-Oct-07 JDB Fixed unsigned-divide bug in .DDI 17-Oct-07 JDB Fixed unsigned-multiply bug in .DMP @@ -57,10 +60,6 @@ #endif /* end of int64 support */ -t_stat cpu_ffp (uint32 IR, uint32 intrq); /* Fast FORTRAN Processor */ -t_stat cpu_dbi (uint32 IR, uint32 intrq); /* Double-Integer instructions */ - - /* Fast FORTRAN Processor. The Fast FORTRAN Processor (FFP) is a set of FORTRAN language accelerators @@ -108,37 +107,38 @@ t_stat cpu_dbi (uint32 IR, uint32 intrq); /* Double-Integer instru almost all use .ENTR. Supporting the latter even on systems that do not support the former still allows such systems to boot. - Notes: + Implementation notes: - 1. The "$SETP" instruction is sometimes listed as ".SETP" in the - documentation. + 1. The "$SETP" instruction is sometimes listed as ".SETP" in the + documentation. - 2. Extended-precision arithmetic routines (e.g., .XMPY) exist on the - 1000-F, but they are assigned instruction codes in the single-precision - floating-point module range. They are replaced by several double - integer instructions, which we dispatch to the double integer handler. + 2. Extended-precision arithmetic routines (e.g., .XMPY) exist on the 1000-F, + but they are assigned instruction codes in the single-precision + floating-point module range. They are replaced by several double integer + instructions, which we dispatch to the double integer handler. - 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. + 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. - 4. The documentation for ..MAP for the 2100 FFP shows A = 0 or -1 for two - or three dimensions, respectively, but the 1000 FFP shows A = 0 or +1. - The firmware actually only checks the LSB of A. + 4. The documentation for ..MAP for the 2100 FFP shows A = 0 or -1 for two or + three dimensions, respectively, but the 1000 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 1000 FFP returns X+3 and Y+3. + 5. The .DFER and .XFER implementations for the 2100 FFP return X+4 and Y+4 + in the A and B registers, whereas the 1000 FFP returns X+3 and Y+3. - 6. The .XFER implementation for the 2100 FFP returns to P+2, whereas the - 1000 implementation returns to P+1. + 6. The .XFER implementation for the 2100 FFP returns to P+2, whereas the + 1000 implementation returns to P+1. - 7. The firmware implementations of DBLE, .BLE, and DDINT clear the overflow - flag. The software implementations do not change overflow. + 7. The firmware implementations of DBLE, .BLE, and DDINT clear the overflow + flag. The software implementations do not change overflow. - 8. The M/E-Series FFP arithmetic instructions (.XADD, etc.) return negative - infinity on negative overflow and positive infinity on positive - overflow. The equivalent F-Series instructions return positive infinity - on both. + 8. The M/E-Series FFP arithmetic instructions (.XADD, etc.) return negative + infinity on negative overflow and positive infinity on positive overflow. + The equivalent F-Series instructions return positive infinity on both. + + 9. The protected memory lower bound for the .GOTO instruction is 2. Additional references: - DOS/RTE Relocatable Library Reference Manual (24998-90001, Oct-1981) @@ -182,9 +182,6 @@ int32 i; #endif /* end of int64 support */ -if ((cpu_unit.flags & UNIT_FFP) == 0) /* FFP option installed? */ - return stop_inst; - entry = IR & 037; /* mask to entry point */ if (UNIT_CPU_MODEL != UNIT_1000_F) { /* 2100/M/E-Series? */ @@ -425,7 +422,7 @@ switch (entry) { /* decode IR<4:0> */ break; } - mp_dms_jmp (MA); /* validate jump addr */ + mp_dms_jmp (MA, 2); /* validate jump addr */ PCQ_ENTRY; /* record last PC */ PC = MA; /* jump */ BR = op[0].word; /* (for 2100 FFP compat) */ @@ -609,25 +606,25 @@ return reason; floating-point processor and the Fast FORTRAN Processor ranges. They are dispatched from those respective simulators for processing here. - Notes: + Implementation notes: - 1. Opcodes 105335-105337 are NOPs in the microcode. They generate - unimplemented instructions stops under simulation. + 1. Opcodes 105335-105337 are NOPs in the microcode. They generate + unimplemented instructions stops under simulation. - 2. This is an implementation of Revision 2 of the microcode, which was - released as ROM part numbers 93585-80003, 93585-80005, and 93585-80001 - (Revision 1 substituted -80002 for -80005). + 2. This is an implementation of Revision 2 of the microcode, which was + released as ROM part numbers 93585-80003, 93585-80005, and 93585-80001 + (Revision 1 substituted -80002 for -80005). - 3. The F-Series firmware executes .DMP and .DDI/.DDIR by floating the - 32-bit double integer to a 48-bit extended-precision number, calling the - FPP to execute the extended-precision multiply/divide, and then fixing - the product to a 32-bit double integer. We simulate these directly with - 64- or 32-bit integer arithmetic. + 3. The F-Series firmware executes .DMP and .DDI/.DDIR by floating the 32-bit + double integer to a 48-bit extended-precision number, calling the FPP to + execute the extended-precision multiply/divide, and then fixing the + product to a 32-bit double integer. We simulate these directly with 64- + or 32-bit integer arithmetic. Additional references: - 93585A Microcode Source (93585-18002 Rev. 2005) - 93585A Double Integer Instructions Installation and Reference Manual - (93585-90007) + (93585-90007) */ static const OP_PAT op_dbi[16] = { @@ -644,9 +641,6 @@ OPS op; uint32 entry, t; t_stat reason = SCPE_OK; -if ((cpu_unit.flags & UNIT_DBI) == 0) /* DBI option installed? */ - return stop_inst; - entry = IR & 017; /* mask to entry point */ if (op_dbi[entry] != OP_N) diff --git a/HP2100/hp2100_cpu4.c b/HP2100/hp2100_cpu4.c index 126da35e..acc39862 100644 --- a/HP2100/hp2100_cpu4.c +++ b/HP2100/hp2100_cpu4.c @@ -25,6 +25,8 @@ CPU4 Floating Point Processor and Scientific Instruction Set + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) 18-Mar-08 JDB Fixed B register return bug in /CMRT 01-Dec-06 JDB Substitutes FPP for firmware FP if HAVE_INT64 @@ -49,12 +51,6 @@ #include "hp2100_fp1.h" -t_stat cpu_fpp (uint32 IR, uint32 intrq); /* Floating Point Processor */ -t_stat cpu_sis (uint32 IR, uint32 intrq); /* Scientific Instruction Set */ - -extern t_stat cpu_dbi (uint32 IR, uint32 intrq); /* Double-Integer instructions */ - - /* Floating-Point Processor. The 1000 F-Series replaces the six 2100/1000-M/E single-precision firmware @@ -256,13 +252,10 @@ uint16 opcode, rtn_addr, stk_ptr; uint32 entry; t_stat reason = SCPE_OK; -if ((cpu_unit.flags & UNIT_FP) == 0) /* FP option installed? */ - return stop_inst; - if (UNIT_CPU_MODEL == UNIT_1000_F) /* F-Series? */ - opcode = (uint16) (IR & 0377); /* yes, use full opcode */ + opcode = (uint16) (IR & 0377); /* yes, use full opcode */ else - opcode = (uint16) (IR & 0160); /* no, use 6 SP FP opcodes */ + opcode = (uint16) (IR & 0160); /* no, use 6 SP FP opcodes */ entry = opcode & 0177; /* map to <6:0> */ @@ -603,9 +596,6 @@ static const OP two_over_ln2 = { { 0056125, 0016624, 0127404 } }; /* 2.0 / ln( static const OP t_one = { { 0040000, 0000000, 0000000, 0000002 } }; /* DEY 1.0 */ -if (UNIT_CPU_MODEL != UNIT_1000_F) /* F-Series? */ - return stop_inst; - entry = IR & 017; /* mask to entry point */ if (op_sis[entry] != OP_N) diff --git a/HP2100/hp2100_cpu5.c b/HP2100/hp2100_cpu5.c index ea9ce3bb..00dec44e 100644 --- a/HP2100/hp2100_cpu5.c +++ b/HP2100/hp2100_cpu5.c @@ -1,8 +1,8 @@ /* hp2100_cpu5.c: HP 1000 RTE-6/VM VMA and RTE-IV EMA instructions - Copyright (c) 2006, J. David Bryan Copyright (c) 2007-2008, Holger Veit - + Copyright (c) 2006-2008, J. David Bryan + 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 @@ -26,6 +26,10 @@ CPU5 RTE-6/VM and RTE-IV firmware option instructions + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) + 30-Jul-08 JDB Redefined ABORT to pass address, moved def to hp2100_cpu.h + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 01-May-08 HV Fixed mapping bug in "cpu_ema_emap" 21-Apr-08 JDB Added EMA support from Holger 25-Nov-07 JDB Added TF fix from Holger @@ -52,10 +56,6 @@ #include "hp2100_cpu1.h" -t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* RTE-6 VMA */ -t_stat cpu_rte_ema (uint32 IR, uint32 intrq); /* RTE-IV EMA */ - - /* RTE-6/VM Virtual Memory Area Instructions RTE-6/VM (product number 92084A) introduced Virtual Memory Area (VMA) @@ -92,17 +92,17 @@ t_stat cpu_rte_ema (uint32 IR, uint32 intrq); /* RTE-IV EMA */ .LBPR 105256 Map pointer in P+1 .LBP 105257 Map pointer in A/B registers - Notes: + Implementation notes: - 1. The opcodes 105243-247 are undocumented and do not appear to be used in - any HP software. + 1. The opcodes 105243-247 are undocumented and do not appear to be used in + any HP software. - 2. The opcode list in the CE Handbook incorrectly shows 105246 as ".MYAD - - multiply 2 signed integers." The microcode listing shows that this - instruction was deleted, and the opcode is now a NOP. + 2. The opcode list in the CE Handbook incorrectly shows 105246 as ".MYAD - + multiply 2 signed integers." The microcode listing shows that this + instruction was deleted, and the opcode is now a NOP. - 3. RTE-IV EMA and RTE-6 VMA instructions shared the same address space, so - a given machine could run one or the other, but not both. + 3. RTE-IV EMA and RTE-6 VMA instructions shared the same address space, so a + given machine could run one or the other, but not both. Additional references: - RTE-6/VM VMA/EMA Microcode Source (92084-18828, revision 3). @@ -129,23 +129,16 @@ static const uint32 page31 = 0076000; static const uint32 ptemiss = 0176000; /* frequent constants in paging */ -#define SUITMASK 0176000 +#define SUITMASK 0176000 #define NILPAGE 0176000 #define PAGEIDX 0001777 #define MSEGMASK 0076000 #define RWPROT 0141777 -/* from scp.c */ -extern int32 sim_step; -extern FILE* sim_log; - -/* MP abort handler */ -extern jmp_buf save_env; -#define ABORT(val) longjmp (save_env, (val)) /* microcode version of resolve(): allows a much higher # of indirection levels. Used for instance for LBP microcode diagnostics which will check > 100 levels. - */ + */ #define VMA_INDMAX 200 static t_stat vma_resolve (uint32 MA, uint32 *addr, t_bool debug) @@ -155,7 +148,7 @@ uint32 faultma = MA; for (i = 0; (i < VMA_INDMAX) && (MA & I_IA); i++) { /* resolve multilevel */ MA = ReadW (MA & VAMASK); /* follow address chain */ - } + } if (MA & I_IA) { if (debug) @@ -169,20 +162,20 @@ return SCPE_OK; /* $LOC ASSEMBLER CALLING SEQUENCE: - + $MTHK NOP RETURN ADDRESS OF CALL (REDONE AFTER THIS ROUTINE) JSB $LOC - .DTAB OCT LGPG# LOGICAL PAGE # AT WHICH THE NODE TO + .DTAB OCT LGPG# LOGICAL PAGE # AT WHICH THE NODE TO * BE MAPPED IN BELONGS (0-31) OCT RELPG RELATIVE PAGE OFFSET FROM BEGINING * OF PARTITION OF WHERE THAT NODE RESIDES. * (0 - 1023) - OCT RELBP RELATIVE PAGE OFFSET FROM BEGINING OF + OCT RELBP RELATIVE PAGE OFFSET FROM BEGINING OF * PARTITION OF WHERE BASE PAGE RESIDES * (0 - 1023) CNODE DEF .CNOD THIS IS THE ADDRESS OF CURRENT PATH # WORD .ORD OCT XXXXX THIS NODE'S LEAF # (IE PATH #) - .NOD# OCT XXXXX THIS NODE'S ORDINAL # + .NOD# OCT XXXXX THIS NODE'S ORDINAL # */ static t_stat cpu_vma_loc(OPS op,uint32 intrq,t_bool debug) @@ -195,7 +188,7 @@ if ((mls & 0x8000) == 0) { /* this is not an MLS prog! PC = err_PC; if (debug) fprintf(sim_deb,">>CPU VMA: cpu_vma_loc at P=%06o: not an MLS program\n", PC); - if (CTL (PRO)) ABORT (ABORT_PRO); /* allow an MP abort */ + if (mp_control) MP_ABORT (eqt+33); /* allow an MP abort */ return STOP_HALT; /* FATAL error! */ } @@ -204,7 +197,7 @@ if (pnod == 0) { /* no pages? FATAL! */ PC = err_PC; if (debug) fprintf(sim_deb,">>CPU VMA: cpu_vma_loc at P=%06o: no mem resident pages\n", PC); - if (CTL (PRO)) ABORT (ABORT_PRO); /* allow an MP abort */ + if (mp_control) MP_ABORT (eqt+33); /* allow an MP abort */ return STOP_HALT; } @@ -216,20 +209,20 @@ lgpg = op[0].word; /* lets do some consistency checks, CPU halt if they fail */ if (lstpg < lgpg || lgpg < fstpg) { /* assert LSTPG >= LGPG# >= FSTPG */ PC = err_PC; - if (debug) + if (debug) fprintf(sim_deb, ">>CPU VMA: $LOC at P=%06o: failed check LSTPG >= LGPG# >= FSTPG\n",PC); - if (CTL (PRO)) ABORT (ABORT_PRO); /* allow an MP abort */ + if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */ return STOP_HALT; } relpg = op[1].word; if (pnod < relpg || relpg < (rotsz+1)) { /* assert #PNOD >= RELPG >= ROTSZ+1 */ PC = err_PC; - if (debug) + if (debug) fprintf(sim_deb, ">>CPU VMA: $LOC at %06o: failed check #PNOD >= RELPG >= ROTSZ+1\n",PC); - if (CTL (PRO)) ABORT (ABORT_PRO); /* allow an MP abort */ + if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */ return STOP_HALT; } @@ -237,17 +230,17 @@ relbp = op[2].word; if (relbp != 0) /* assert RELBP == 0 OR */ if (pnod < relbp || relbp < (rotsz+1)) { /* #PNOD >= RELBP >= ROTSZ+1 */ PC = err_PC; - if (debug) + if (debug) fprintf(sim_deb, ">>CPU VMA: $LOC at P=%06o: failed check: #PNOD >= RELBP >= ROTSZ+1\n",PC); - if (CTL (PRO)) ABORT (ABORT_PRO); /* allow an MP abort */ + if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */ return STOP_HALT; } cnt = lstpg - lgpg + 1; /* #pages to map */ pgs = pnod - relpg + 1; /* #pages from start node to end of code */ if (pgs < cnt) cnt = pgs; /* ensure minimum, so not to map into EMA */ - + matloc = ReadIO(xmata,UMAP); /* get MAT $LOC address */ ptnpg = ReadIO(matloc+3,SMAP) & 01777; /* index to start phys pg */ physpg = ptnpg + relpg; /* phys pg # of node */ @@ -267,7 +260,7 @@ while (cnt != 0) { dms_wmap(32,relbp+ptnpg); /* map base page again */ WriteW(op[3].word,op[4].word); /* path# we are going to */ - + PC = (PC - 8) & DMASK; /* adjust PC to return address */ /* word before the $LOC microinstr. */ PC = (ReadW(PC) - 1) & DMASK; /* but the call has to be rerun, */ @@ -279,8 +272,8 @@ return SCPE_OK; } /* map pte into last page - return FALSE if page fault, nil flag in PTE or suit mismatch - return TRUE if suit match, physpg = physical page + return FALSE if page fault, nil flag in PTE or suit mismatch + return TRUE if suit match, physpg = physical page or page=0 -> last+1 page */ static t_bool cpu_vma_ptevl(uint32 pagid,uint32* physpg) @@ -310,9 +303,9 @@ if (mapr>0) /* do a safety check: first instr of $EMA$/$VMA$ must be a DST instr */ if (ReadIO(ema+1,UMAP) != 0104400) { - if (debug) + if (debug) fprintf(sim_deb, ">>CPU VMA: pg fault: no EMA/VMA user code present\n"); - if (CTL (PRO)) ABORT (ABORT_PRO); /* allow an MP abort */ + if (mp_control) MP_ABORT (ema+1); /* allow an MP abort */ return STOP_HALT; /* FATAL: no EMA/VMA! */ } @@ -323,7 +316,7 @@ AR = (ptr >> 16) & DMASK; /* restore A, B */ BR = ptr & DMASK; E = 0; /* enforce E = 0 */ if (debug) - fprintf(sim_deb, + fprintf(sim_deb, ">>CPU VMA: Call pg fault OS exit, AR=%06o BR=%06o P=%06o\n", AR, BR, PC); return SCPE_OK; @@ -359,8 +352,8 @@ return swapflag; /* true for swap bit set */ DLD PONTR TRANSLATE 32 BIT POINTER TO 15 JSB .LBP BIT POINTER. - - + + 32 bit pointer: ----------AR------------ -----BR----- 15 14....10 9....4 3...0 15.10 9....0 @@ -372,7 +365,7 @@ return swapflag; /* true for swap bit set */ OOOOOO 10 bit OFFSET */ -static t_stat cpu_vma_lbp(uint32 ptr,uint32 aoffset,uint32 faultpc,uint32 intrq,t_bool debug) +static t_stat cpu_vma_lbp(uint32 ptr,uint32 aoffset,uint32 faultpc,uint32 intrq,t_bool debug) { uint32 pagid,offset,ptrl,pgidx,ptepg; uint16 p30,p31,suit; @@ -390,12 +383,12 @@ if (ptr & 0x80000000) { /* is it a local reference? if ((ptr&I_IA) && (reason = vma_resolve (ReadW (ptrl), &ptrl, debug))) return reason; /* yes, resolve indirect ref */ BR = ptrl & VAMASK; /* address is local */ - AR = (ptr >> 16) & DMASK; + AR = (ptr >> 16) & DMASK; if (debug) fprintf(sim_deb,">>CPU VMA: cpu_vma_lbp: local ref AR=%06o BR=%06o\n",AR,BR); return SCPE_OK; } - + pagid = (ptr >> 10) & DMASK; /* extract page id (16 bit idx, incl suit*/ offset = ptr & 01777; /* and offset */ suit = pagid & SUITMASK; /* suit of page */ @@ -406,12 +399,12 @@ if (!cpu_vma_mapte(&ptepg)) /* map in PTE */ /* ok, we have the PTE mapped to page31 */ /* the microcode tries to reads two consecutive data pages into page30 and page31 */ - + /* read the 1st page value from PTE */ p30 = ReadW(page31 | pgidx) ^ suit; if (!p30) /* matched suit for 1st page */ return cpu_vma_fault(pagid,page30,30,ptepg,faultab,faultpc,debug); - + /* suit switch situation: 1st page is in last idx of PTE, then following page * must be in idx 0 of PTE */ if (pgidx==01777) { /* suit switch situation */ @@ -435,7 +428,7 @@ if (!p31) { /* matched suit for 2nd page offset += 02000; /* adjust offset to last user map because */ /* the address requested page 76xxx */ - } + } else { dms_wmap(30+UMAP,p30); if (p30 & SUITMASK) @@ -455,20 +448,20 @@ return SCPE_OK; /* .PMAP ASSEMBLER CALLING SEQUENCE: - LDA UMAPR (MSEG - 31) - LDB PAGID (0-65535) + LDA UMAPR (MSEG - 31) + LDB PAGID (0-65535) JSB .PMAP GO MAP IT IN A-REG = REASON, NOTE 1 > SEE NOTE 2> - NOTE 1 : IF BIT 15 OF A-REG SET, THEN ALL NORMAL BRANCHES TO THE - $EMA$/$VMA$ CODE WILL BE CHANGED TO P+1 EXIT. THE A-REG + NOTE 1 : IF BIT 15 OF A-REG SET, THEN ALL NORMAL BRANCHES TO THE + $EMA$/$VMA$ CODE WILL BE CHANGED TO P+1 EXIT. THE A-REG WILL BE THE REASON THE MAPPING WAS NOT SUCCESSFUL IF BIT 15 OF THE A-REG WAS NOT SET. - THIS WAS DONE SO THAT A ROUTINE ($VMA$) CAN DO A MAPPING + THIS WAS DONE SO THAT A ROUTINE ($VMA$) CAN DO A MAPPING WITHOUT THE POSSIBILITY OF BEING RE-CURRED. IT IS USED - BY $VMA$ AND PSTVM IN THE PRIVLEDGED MODE. - NOTE 2: E-REG WILL = 1 IF THE LAST+1 PAGE IS REQUESTED AND + BY $VMA$ AND PSTVM IN THE PRIVLEDGED MODE. + NOTE 2: E-REG WILL = 1 IF THE LAST+1 PAGE IS REQUESTED AND MAPPED READ/WRITE PROTECTED ON A GOOD P+2 RETURN. */ static t_stat cpu_vma_pmap(uint32 umapr,uint32 pagid, t_bool debug) @@ -486,13 +479,13 @@ if (mapnm > 31) { /* check for invalid map reg return SCPE_OK; /* return exit PC+1 */ } -ptr = (umapr << 16) | (pagid & DMASK); /* build the ptr argument for vma_fault */ +ptr = (umapr << 16) | (pagid & DMASK); /* build the ptr argument for vma_fault */ if (!cpu_vma_mapte(&pgpte)) { /* map the PTE */ if (umapr & 0x8000) { XR = 65535; YR = ptemiss; if (debug) - fprintf(sim_deb, + fprintf(sim_deb, ">>CPU VMA: .PMAP pg fault&bit15: XR=%06o YR=%06o, exit P+1\n", XR, YR); return SCPE_OK; /* use PC+1 error exit */ @@ -506,20 +499,20 @@ if (!cpu_vma_ptevl(pagid,&physpg)) { XR = pagid; YR = page31; if (debug) - fprintf(sim_deb, + fprintf(sim_deb, ">>CPU VMA: .PMAP pg map&bit15: XR=%06o YR=%06o, exit P+1\n", XR, YR); return SCPE_OK; /* use PC+1 error exit*/ } return cpu_vma_fault(pagid,page31,31,pgpte,ptr,PC-1,debug); /* page not present */ } - + E = 1; if (physpg == 0) /* last+1 page ? */ physpg = RWPROT; /* yes, use page 1023 RW/Protected */ else E = 0; /* normal page to map */ -dms_wmap(mapnm+UMAP,physpg); /* map page to user page reg */ +dms_wmap(mapnm+UMAP,physpg); /* map page to user page reg */ if (mapnm != 31) /* unless already unmapped, */ dms_wmap(31+UMAP,RWPROT); /* unmap PTE */ @@ -535,17 +528,17 @@ return SCPE_OK; /* array calc helper for .imar, .jmar, .imap, .jmap ij=in_s: 16 bit descriptors ij=in_d: 32 bit descriptors - + This helper expects mainly the following arguments: dtbl: pointer to an array descriptor table atbl: pointer to the table of actual subscripts - + where subscript table is the following: atbl-> DEF last_subscript,I (point to single or double integer) ... DEF first subscript,I (point to single or double integer) - where Descriptor_table is the following table: + where Descriptor_table is the following table: dtbl-> DEC #dimensions DEC/DIN next-to-last dimension (single or double integer) ... @@ -626,7 +619,7 @@ while (ndim-- > 0) { dtbl++; } accu *= dx; /* multiply */ - } + } din = ReadOp(dtbl,in_d); /* add base address */ accu += din.dword; @@ -651,9 +644,6 @@ OP dop0,dop1; uint32 pcsave = (PC+1) & VAMASK; /* save PC to check for redo in imap/jmap */ t_bool debug = DEBUG_PRI (cpu_dev, DEB_VMA); -if ((cpu_unit.flags & UNIT_VMAOS) == 0) /* VMA/OS option installed? */ - return cpu_rte_ema (IR, intrq); /* try EMA */ - entry = IR & 017; /* mask to entry point */ pattern = op_vma[entry]; /* get operand pattern */ @@ -673,7 +663,7 @@ if (debug) { /* debugging? */ } switch (entry) { /* decode IR<3:0> */ - + case 000: /* .PMAP 105240 (OP_N) */ reason = cpu_vma_pmap(AR,BR,debug); /* map pages */ break; @@ -715,14 +705,14 @@ switch (entry) { /* decode IR<3:0> */ break; case 010: /* .IMAP 105250 (OP_A) */ - dtbl = op[0].word; + dtbl = op[0].word; atbl = PC; if ((reason = cpu_vma_ijmar(in_s,dtbl,atbl,&ndim,intrq,debug))) /* calc the virt address to AB */ return reason; t32 = (AR << 16) | (BR & DMASK); if ((reason = cpu_vma_lbp(t32,0,PC-2,intrq,debug))) return reason; - if (PC==pcsave) + if (PC==pcsave) PC = (PC+ndim) & VAMASK; /* adjust PC: skip ndim subscript words */ break; @@ -752,8 +742,8 @@ switch (entry) { /* decode IR<3:0> */ case 014: /* .LPXR 105254 (OP_AA) */ dop0 = ReadOp(op[0].word,in_d); /* get pointer from arg */ - dop1 = ReadOp(op[1].word,in_d); - t32 = dop0.dword + dop1.dword; /* add offset to it */ + dop1 = ReadOp(op[1].word,in_d); + t32 = dop0.dword + dop1.dword; /* add offset to it */ reason = cpu_vma_lbp(t32,0,PC-3,intrq,debug); break; @@ -773,7 +763,7 @@ switch (entry) { /* decode IR<3:0> */ reason = cpu_vma_lbp(t32,0,PC-1,intrq,debug); break; } - + return reason; } @@ -869,7 +859,7 @@ return TRUE; * DEC -L(N) * DEC D(N-1) * DEC -L(N-1) lower bound (n-1)st dim - * DEC D(N-2) (n-2)st dim + * DEC D(N-2) (n-2)st dim * ... * DEC D(1) 1st dim * DEC -L(1) lower bound 1st dim @@ -891,7 +881,7 @@ if (cpu_ema_resolve(dtbl,atbl,&sum)) { /* calculate subscript * AR = 0x3230; /* error condition: */ BR = 0x454d; /* AR = '20', BR = 'EM' */ return SCPE_OK; /* return via unmodified rtn */ -} +} /* implementation of VIS RTE-IVB EMA support * .ESEG microcode routine @@ -942,7 +932,7 @@ for (i=0; i emasz) pg |= 0140000; /* write protect if outside */ pg += phys; /* adjust into EMA page range */ WriteIO(umaps+lp+i, pg, UMAP); /* copy pg to user map */ -//printf("MAP val %oB to reg %d (addr=%oB)\n",pg,lp+i,umaps+lp+i); +/* printf("MAP val %oB to reg %d (addr=%oB)\n",pg,lp+i,umaps+lp+i); */ dms_wmap(UMAP+lp+i, pg); /* set DMS reg */ } dms_wmap(UMAP+1,pg1); /* restore map #1 */ @@ -1011,7 +1001,7 @@ for (i=0; i AR) goto hard; - + easy: (*rtn)++; /* return via exit 2 */ AR = 0; @@ -1033,7 +1023,7 @@ BR = 2 * op[4].word; /* B = 2* vectors */ return SCPE_OK; vi22: /* error condition */ - AR=0x3232; /* AR = '22' */ + AR=0x3232; /* AR = '22' */ BR=0x5649; /* BR = 'VI' */ return SCPE_OK; /* return via unmodified e->rtn */ } @@ -1103,7 +1093,7 @@ dms_wmap(UMAP+1,pg0); /* map #0 into reg #1 */ for (i=0; (base+i)<32; i++) { pg = inpgs ? e->spmseg : 0140000; /* write protect if outside */ WriteIO(umaps+base+i, pg, UMAP); /* copy pg to user map */ -//printf("MAP val %d to reg %d (addr=%o)\n",pg,base+i,umaps+base+i); +/* printf("MAP val %d to reg %d (addr=%o)\n",pg,base+i,umaps+base+i); */ dms_wmap(UMAP+base+i, pg); /* set DMS reg */ e->spmseg++; } @@ -1137,7 +1127,7 @@ if ((e->ipgs % msegsz) != 0) /* non std MSEG? */ if (e->npgs > msegsz) return FALSE; /* map more pages than MSEG sz? */ eqt = ReadIO(xeqt,UMAP); emasz = ReadWA(eqt+28) & 01777; /* B EMA size in pages */ -if ((e->ipgs+e->npgs) > emasz) return FALSE; /* outside EMA? */ +if ((e->ipgs+e->npgs) > emasz) return FALSE; /* outside EMA? */ if ((e->ipgs+msegsz) > emasz) /* if MSEG overlaps end of EMA */ e->npgs = emasz - e->ipgs; /* only map until end of EMA */ @@ -1158,7 +1148,7 @@ e->ipgs = ipage; /* S6 set the arguments e->npgs = npgs; /* S5 */ AR = 0; -xidex = ReadIO(idx,UMAP); +xidex = ReadIO(idx,UMAP); if ((ipage & SIGN) || /* negative page displacement? */ (npgs & SIGN) || /* negative # of pages? */ xidex == 0 || /* no EMA? */ @@ -1171,7 +1161,7 @@ static t_bool cpu_ema_emat(EMA4* e) { uint32 xidex,idext0; uint32 curmseg,phys,msnum,lastpgs; - + xidex = ReadIO(idx,UMAP); /* read ID extension */ idext0 = ReadWA(xidex+0); /* get current segment */ curmseg = idext0 >> 5; @@ -1191,7 +1181,7 @@ return TRUE; /* and everything done * /* .EMIO microcode routine, resolves element addr for EMA array * and maps the appropriate map segment - * + * * Call: * OCT 105250B * DEF RTN error return (rtn), good return is rtn+1 @@ -1209,7 +1199,7 @@ return TRUE; /* and everything done * * DEC -L(N) * DEC D(N-1) * DEC -L(N-1) lower bound (n-1)st dim - * DEC D(N-2) (n-2)st dim + * DEC D(N-2) (n-2)st dim * ... * DEC D(1) 1st dim * DEC -L(1) lower bound 1st dim @@ -1224,7 +1214,7 @@ uint32 mseg, bufpgs, npgs; EMA4 ema4, *e = &ema4; xidex = ReadIO(idx,UMAP); /* read ID extension */ -if (bufl & SIGN || /* buffer length negative? */ +if (bufl & SIGN || /* buffer length negative? */ xidex==0) goto em16; /* no EMA declared? */ idext1 = ReadWA(xidex+1); /* |logstrt mseg|d|physstrt ema| */ @@ -1232,7 +1222,7 @@ mseg = (idext1 >> 1) & MSEGMASK; /* get logical start MSE if (!cpu_ema_emas(dtbl,atbl,e)) goto em16; /* resolve address */ bufpgs = (bufl + e->offs) >> 10; /* # of pgs reqd for buffer */ if ((bufl + e->offs) & 01777) bufpgs++; /* S11 add 1 if not at pg boundary */ -if ((bufpgs + e->pgoff) > e->emasz) goto em16; /* exceeds EMA limit? */ +if ((bufpgs + e->pgoff) > e->emasz) goto em16; /* exceeds EMA limit? */ npgs = (e->msoff + bufl) >> 10; /* # of pgs reqd for MSEG */ if ((e->msoff + bufl) & 01777) npgs++; /* add 1 if not at pg boundary */ if (npgs < e->msegsz) { @@ -1244,11 +1234,11 @@ if (npgs < e->msegsz) { e->ipgs = e->pgoff; /* S6 page offset to reqd pg */ if (!cpu_ema_mmap02(e)) goto em16; /* do nonstd mapping */ } -(*rtn)++; /* return via good exit */ +(*rtn)++; /* return via good exit */ return SCPE_OK; em16: /* error condition */ -AR=0x3136; /* AR = '16' */ +AR=0x3136; /* AR = '16' */ BR=0x454d; /* BR = 'EM' */ return SCPE_OK; /* return via unmodified rtn */ } @@ -1271,7 +1261,7 @@ return SCPE_OK; /* return via unmodified * DEC -L(N) * DEC D(N-1) * DEC -L(N-1) lower bound (n-1)st dim - * DEC D(N-2) (n-2)st dim + * DEC D(N-2) (n-2)st dim * ... * DEC D(1) 1st dim * DEC -L(1) lower bound 1st dim @@ -1297,7 +1287,7 @@ if (xidex) { /* is EMA declared? */ if (pgoff > 1023) goto em15; /* overflow? */ eqt = ReadIO(xeqt,UMAP); emasz = ReadWA(eqt+28) & 01777; /* EMA size in pages */ - phys = idext1 & 01777; /* physical start pg of EMA */ + phys = idext1 & 01777; /* physical start pg of EMA */ if (pgoff > emasz) goto em15; /* outside EMA range? */ msgn = mseg >> 10; /* get # of 1st MSEG reg */ @@ -1306,7 +1296,7 @@ if (xidex) { /* is EMA declared? */ pg0 = dms_rmap(UMAP+0); /* read base page map# */ pg1 = dms_rmap(UMAP+1); /* save map# 1 */ dms_wmap(UMAP+1,pg0); /* map #0 into reg #1 */ - + WriteIO(umaps+msgn, phys, UMAP); /* store 1st mapped pg in user map */ dms_wmap(UMAP+msgn, phys); /* and set the map register */ phys = (pgoff+1)==emasz ? 0140000 : phys+1; /* protect 2nd map if end of EMA */ @@ -1314,11 +1304,11 @@ if (xidex) { /* is EMA declared? */ dms_wmap(UMAP+msgn+1, phys); /* and set the map register */ dms_wmap(UMAP+1,pg1); /* restore map #1 */ - + idext0 = ReadWA(xidex+0) | 0100000; /* set NS flag in id extension */ WriteIO(xidex+0, idext0, SMAP); /* save back value */ AR = 0; /* was successful */ - BR = mseg + offs; /* calculate log address */ + BR = mseg + offs; /* calculate log address */ (*rtn)++; /* return via good exit */ return SCPE_OK; } @@ -1331,7 +1321,7 @@ while (ndim > 0) { resolve (MA, &MA, 0); act = ReadW(MA); /* A(N) */ low = ReadW(dtbl++); /* -L(N) */ - sub = SEXT(act) + SEXT(low); /* subscript */ + sub = SEXT(act) + SEXT(low); /* subscript */ if (sub & 0xffff8000) goto em15; /* overflow? */ sum += sub; /* accumulate */ sz = ReadW(dtbl++); @@ -1346,10 +1336,10 @@ BR = abase + sum; /* add displacement */ return SCPE_OK; em15: /* error condition */ - AR=0x3135; /* AR = '15' */ + AR=0x3135; /* AR = '15' */ BR=0x454d; /* BR = 'EM' */ return SCPE_OK; /* return via unmodified e->rtn */ -} +} t_stat cpu_rte_ema (uint32 IR, uint32 intrq) { @@ -1359,9 +1349,6 @@ OP_PAT pattern; uint32 entry, rtn; t_bool debug = DEBUG_PRI (cpu_dev, DEB_EMA); -if ((cpu_unit.flags & UNIT_EMA) == 0) /* EMA option installed? */ - return stop_inst; - entry = IR & 017; /* mask to entry point */ pattern = op_ema[entry]; /* get operand pattern */ @@ -1382,7 +1369,7 @@ if (debug) { /* debugging? */ switch (entry) { /* decode IR<3:0> */ case 000: /* .EMIO 105240 (OP_A) */ rtn = op[0].word; - reason = cpu_ema_emio(&rtn, op[1].word, + reason = cpu_ema_emio(&rtn, op[1].word, op[2].word, PC, debug); /* handle the EMIO instruction */ PC = rtn; if (debug) @@ -1417,7 +1404,7 @@ switch (entry) { /* decode IR<3:0> */ AR, BR, PC==op[0].word?"error":"good"); } break; - + default: /* others undefined */ reason = stop_inst; } diff --git a/HP2100/hp2100_cpu6.c b/HP2100/hp2100_cpu6.c index 88827eaf..f0a464de 100644 --- a/HP2100/hp2100_cpu6.c +++ b/HP2100/hp2100_cpu6.c @@ -1,6 +1,6 @@ /* hp2100_cpu6.c: HP 1000 RTE-6/VM OS instructions - Copyright (c) 2006-2007, J. David Bryan + Copyright (c) 2006-2008, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,10 @@ CPU6 RTE-6/VM OS instructions + 18-Sep-08 JDB Corrected .SIP debug formatting + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 27-Nov-07 JDB Implemented OS instructions 26-Sep-06 JDB Created @@ -136,70 +140,82 @@ enum vctr_offsets { dms_offset = 0, /* DMS status */ * These mnemonics are recognized by symbolic examine/deposit but are not official HP mnemonics. - Notes: + Implementation notes: - 1. The microcode differentiates between interrupt processing and normal - execution of the "dual use" instructions by testing the CPU flag. - Interrupt vectoring sets the flag; a normal instruction fetch clears it. - Under simulation, interrupt vectoring is indicated by the value of the - "iotrap" parameter (0 = normal instruction, 1 = trap cell instruction). + 1. The microcode differentiates between interrupt processing and normal + execution of the "dual use" instructions by testing the CPU flag. + Interrupt vectoring sets the flag; a normal instruction fetch clears it. + Under simulation, interrupt vectoring is indicated by the value of the + "iotrap" parameter (0 = normal instruction, 1 = trap cell instruction). - 2. The operand patterns for .ENTN and .ENTC normally would be coded as - "OP_A", as each takes a single address as a parameter. However, because - they might also be executed from a trap cell, we cannot assume that P+1 - is an address, or we might cause a DM abort when trying to resolve - indirects. Therefore, "OP_A" handling is done within each routine, once - the type of use is determined. + 2. The operand patterns for .ENTN and .ENTC normally would be coded as + "OP_A", as each takes a single address as a parameter. However, because + they might also be executed from a trap cell, we cannot assume that P+1 + is an address, or we might cause a DM abort when trying to resolve + indirects. Therefore, "OP_A" handling is done within each routine, once + the type of use is determined. - 3. The microcode for .ENTC, .ENTN, .FNW, .LLS, .TICK, and .TNAM explicitly - checks for interrupts during instruction execution. In addition, the - .STIO, .CPM, and .LLS instructions implicitly check for interrupts - during parameter indirect resolution. Because the simulator calculates - interrupt requests only between instructions, this behavior is not - simulated. + 3. The microcode for .ENTC, .ENTN, .FNW, .LLS, .TICK, and .TNAM explicitly + checks for interrupts during instruction execution. In addition, the + .STIO, .CPM, and .LLS instructions implicitly check for interrupts during + parameter indirect resolution. Because the simulator calculates + interrupt requests only between instructions, this behavior is not + simulated. - 4. The microcode executes certain I/O instructions (e.g., CLF 0) by - building the instruction in the IR and executing an IOG micro-order. We - simulate this behavior by calling the "iogrp" handler with the - appropriate instruction, rather than manipulating the I/O system - directly, so that we will remain unaffected by any future changes to the - underlying I/O simulation structure. + 4. The microcode executes certain I/O instructions (e.g., CLF 0) by building + the instruction in the IR and executing an IOG micro-order. We simulate + this behavior by calling the "iogrp" handler with the appropriate + instruction, rather than manipulating the I/O system directly, so that we + will remain unaffected by any future changes to the underlying I/O + simulation structure. - 5. The $OTST and .DSPI microcode uses features (reading the RPL switches - and boot loader ROM data, loading the display register) that are not - simulated. The remaining functions of the $OTST instruction are - provided. The .DSPI instruction is a NOP or unimplemented instruction - stop. + 5. The $OTST and .DSPI microcode uses features (reading the RPL switches and + boot loader ROM data, loading the display register) that are not + simulated. The remaining functions of the $OTST instruction are + provided. The .DSPI instruction is a NOP or unimplemented instruction + stop. - 6. The microcode detects a privileged system and takes some additional - actions if one is found. We provide simulations of these actions. - However, at the current time, the simulator does not provide a - privileged interrupt fence card, so this code is untested. + 6. Because of the volume of calls to the OS firmware, debug printouts + attempt to write only one line per instruction invocation. This means + that calling and returned register values are printed separately, with a + newline added at the end of execution. However, many instructions can MP + or DM abort, either intentionally or due to improper use. That would + leave debug lines without the required trailing newlines. - 7. Because of the volume of calls to the OS firmware, debug printouts - attempt to write only one line per instruction invocation. This means - that calling and returned register values are printed separately, with a - newline added at the end of execution. However, many instructions can - MP or DM abort, either intentionally or due to improper use. That would - leave debug lines without the required trailing newlines. + There are two ways to address this: either we could replace the CPU's + setjmp buffer with one that points to a routine that adds the missing + newline, or we can add a semaphore that is tested on entry to see if it + is already set, implying a longjmp occurred, and then add the newline if + so. The latter would add the newline when the MP trap cell instruction + was entered or when the next user-level instruction was executed. + However, the merged-line problem would still exist if some other module + generated intervening debug printouts. So we do the former. This does + mean that this routine must be changed if the MP abort mechanism is + changed. - There are two ways to address this: either we could replace the CPU's - setjmp buffer with one that points to a routine that adds the missing - newline, or we can add a semaphore that is tested on entry to see if it - is already set, implying a longjmp occurred, and then add the newline if - so. The latter would add the newline when the MP trap cell instruction - was entered or when the next user-level instruction was executed. - However, the merged-line problem would still exist if some other module - generated intervening debug printouts. So we do the former. This does - mean that this routine must be changed if the MP abort mechanism is - changed. + 7. The $LIBX instruction is executed to complete either a privileged or + reentrant execution. In the former case, the privileged nest counter + ($PVCN) is decremented. In the latter, $PVCN decrement is attempted but + the write will trap with an MP violation, as reentrant routines execute + with the interrupt system on. RTE will then complete the release of + memory allocated for the original $LIBR call. - 8. The $LIBX instruction is executed to complete either a privileged or - reentrant execution. In the former case, the privileged nest counter - ($PVCN) is decremented. In the latter, $PVCN decrement is attempted but - the write will trap with an MP violation, as reentrant routines execute - with the interrupt system on. RTE will then complete the release of - memory allocated for the original $LIBR call. + 8. The documentation for the .SIP and .YLD instructions is misleading in + several places. Comments in the RTE $SIP source file say that .SIP + doesn't return if a "known" interrupt is pending. Actually, .SIP always + returns, either to P+1 for no pending interrupt, or to P+2 if one is + pending. There is no check for "known" interrupt handlers. The + microcode source comments say that the interrupting select code is + returned in the B register. Actually, the B register is unchanged. The + RTE Tech Specs say that .SIP "services any pending system interrupts." + Actually, .SIP only checks for interrupts; no servicing is performed. + + For .YLD, the microcode comments say that two parameters are passed: the + new P value, and the interrupting select code. Actually, only the new P + value is passed. + + The .SIP and .YLD simulations follow the actual microcode rather than the + documentation. Additional references: - RTE-6/VM OS Microcode Source (92084-18831, revision 8). @@ -330,22 +346,22 @@ else Note that the OS flag enables the .IRT instruction trace for all cases except a TBG interrupt. - The firmware self-test instruction (105355) is always allowed, regardless of - the UNIT_VMAOS setting. This is because RTE-6/VM will always test for the - presence of OS and VMA firmware on E/F-Series machines. If the firmware is - not present, then these instructions are NOPs and return to P+1. RTE will - then HLT 21. This means that RTE-6/VM will not run on an E/F-Series machine - without the OS and VMA firmware. + The default (user microcode) dispatcher will allow the firmware self-test + instruction (105355) to execute as NOP. This is because RTE-6/VM will always + test for the presence of OS and VMA firmware on E/F-Series machines. If the + firmware is not present, then these instructions will return to P+1, and RTE + will then HLT 21. This means that RTE-6/VM will not run on an E/F-Series + machine without the OS and VMA firmware. Howwever, RTE allows the firmware instructions to be disabled for debugging purposes. If the firmware is present and returns to P+2 but sets the X register to 0, then RTE will use software equivalents. We enable this condition when the OS firmware is enabled (SET CPU VMA), the OS debug flag is set (SET CPU DEBUG=OS), but debug output has been disabled (SET CONSOLE - NODEBUG). That is: + NODEBUG). That is: OS Debug - Firmware Flag Output Tracing Self-Test Instruction + Firmware Debug Output Tracing Self-Test Instruction ======== ===== ====== ======= ===================== disabled x x off NOP enabled clear x off X = revision code @@ -373,10 +389,6 @@ int abortval; t_bool debug_print; static t_bool tbg_tick = FALSE; /* set if processing TBG interrupt */ -if ((IR != 0105355) && /* allow self-test with OS disabled */ - (cpu_unit.flags & UNIT_VMAOS) == 0) /* VMA/OS option installed? */ - return stop_inst; - entry = IR & 017; /* mask to entry point */ pattern = op_os[entry]; /* get operand pattern */ @@ -411,7 +423,7 @@ switch (entry) { /* decode IR<3:0> */ case 000: /* $LIBR 105340 (OP_A) */ if ((op[0].word != 0) || /* reentrant call? */ - (CTL (PRO) && (ReadW (dummy) != 0))) { /* or priv call + MP on + priv sys? */ + (mp_control && (ReadW (dummy) != 0))) { /* or priv call + MP on + priv sys? */ if (dms_ump) { /* called from user map? */ dms_viol (err_PC, MVI_PRV); /* privilege violation */ } @@ -422,8 +434,8 @@ switch (entry) { /* decode IR<3:0> */ } else { /* privileged call */ - if (CTL (PRO)) { /* memory protect on? */ - clrCTL (PRO); /* turn it off */ + if (mp_control) { /* memory protect on? */ + mp_control = CLEAR; /* turn it off */ reason = iogrp (CLF_0, iotrap); /* turn interrupt system off */ WriteW (mptfl, 1); /* show MP is off */ save_area = ReadW (xsusp); /* get addr of P save area */ @@ -636,7 +648,7 @@ switch (entry) { /* decode IR<3:0> */ /* P+0 return for no pending IRQ */ if (debug_print) /* debugging? */ fprintf (sim_deb, /* print return registers */ - "CIR = %02o, return = P+%d", + ", CIR = %02o, return = P+%d", intrq, PC - (err_PC + 1)); break; @@ -739,25 +751,22 @@ switch (entry) { /* decode IR<3:0> */ } else { /* self-test instruction */ - if (cpu_unit.flags & UNIT_VMAOS) { /* VMA/OS option installed? */ - YR = 0000000; /* RPL switch (not implemented) */ - AR = 0000000; /* LDR [B] (not implemented) */ - SR = 0102077; /* test passed code */ - PC = (PC + 1) & VAMASK; /* P+1 return for firmware OK */ + YR = 0000000; /* RPL switch (not implemented) */ + AR = 0000000; /* LDR [B] (not implemented) */ + SR = 0102077; /* test passed code */ + PC = (PC + 1) & VAMASK; /* P+1 return for firmware OK */ - if ((cpu_dev.dctrl & DEB_OS) && /* OS debug flag set, */ - (sim_deb == NULL)) /* but debugging disabled? */ - XR = 0; /* rev = 0 means RTE won't use ucode */ - else - XR = 010; /* firmware revision 10B = 8 */ - } + if ((cpu_dev.dctrl & DEB_OS) && /* OS debug flag set, */ + (sim_deb == NULL)) /* but debugging disabled? */ + XR = 0; /* rev = 0 means RTE won't use ucode */ + else + XR = 010; /* firmware revision 10B = 8 */ if (debug_print) /* debugging? */ fprint_regs (",", REG_X | REG_P_REL, /* print return registers */ err_PC + 1); } - - break; /* self-test is NOP if no firmware */ + break; case 016: /* .ENTC/$DEV 105356 (OP_N) */ if (iotrap) { /* in trap cell? */ diff --git a/HP2100/hp2100_cpu7.c b/HP2100/hp2100_cpu7.c index 5b0e3d0c..daf9df21 100644 --- a/HP2100/hp2100_cpu7.c +++ b/HP2100/hp2100_cpu7.c @@ -1,7 +1,7 @@ /* hp2100_cpu7.c: HP 1000 VIS and SIGNAL/1000 microcode - Copyright (c) 2006, J. David Bryan Copyright (c) 2008, Holger Veit + Copyright (c) 2006-2008, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,8 @@ CPU7 Vector Instruction Set and SIGNAL firmware + 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h + 05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers) 30-Apr-08 JDB Updated SIGNAL code from Holger 24-Apr-08 HV Implemented SIGNAL 20-Apr-08 JDB Updated comments @@ -52,9 +54,6 @@ #include "hp2100_fp1.h" -t_stat cpu_vis (uint32 IR, uint32 intrq); /* Vector Instruction Set */ -t_stat cpu_signal (uint32 IR, uint32 intrq); /* SIGNAL/1000 Instructions */ - static const OP zero = { { 0, 0, 0, 0, 0 } }; /* DEC 0.0D0 */ @@ -372,9 +371,6 @@ OP_PAT pattern; OPSIZE opsize; t_bool debug = DEBUG_PRI (cpu_dev, DEB_VIS); -if ((cpu_unit.flags & UNIT_VIS) == 0) /* VIS option installed? */ - return stop_inst; - opsize = (IR & 004000) ? fp_t : fp_f; /* double or single precision */ entry = IR & 017; /* mask to entry point */ pattern = op_vis[entry]; @@ -383,7 +379,7 @@ if (entry==0) { /* retrieve sub opcode ret = ReadOp (PC, in_s); /* get it */ subcode = ret.word; if (subcode & 0100000) /* special property of ucode */ - subcode = AR; /* for reentry */ + subcode = AR; /* for reentry */ PC = (PC + 1) & VAMASK; /* bump to real argument list */ pattern = (subcode & 0400) ? OP_AAKAKK : OP_AKAKAKK; /* scalar or vector operation */ } @@ -451,13 +447,13 @@ switch (entry) { /* decode IR<3:0> */ reason = cpu_ema_eres(&rtn,op[2].word,PC,debug); /* handle the ERES instruction */ PC = rtn; if (debug) - fprintf (sim_deb, + fprintf (sim_deb, ">>CPU VIS: return .ERES: AR = %06o, BR = %06o, rtn=%s\n", AR, BR, PC==op[0].word ? "error" : "good"); break; case 015: /* .ESEG (OP_(A)A) */ - reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */ + reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */ PC = rtn; if (debug) fprintf (sim_deb, @@ -470,7 +466,7 @@ switch (entry) { /* decode IR<3:0> */ PC = rtn; if (debug) fprintf (sim_deb, ">>CPU VIS: return .VSET: AR = %06o BR = %06o, rtn=%s\n", - AR, BR, + AR, BR, rtn==rtn1 ? "error" : (rtn==(rtn1+1) ? "hard" : "easy") ); break; @@ -561,10 +557,10 @@ static void sig_btrfy(uint32 re,uint32 im,OP wr,OP wi,uint32 k, uint32 n2) * v(k)-------->o-->o----> v(k) * \ / * x - * / \ + * / \ * v(k+N/2)---->o-->o----> v(k+N/2) * Wn -1 - * + * */ OP p1,p2,p3,p4; @@ -610,7 +606,7 @@ if (rev < idx) return; /* avoid swapping same pair t idx *= sz; /* adjust for element size */ rev *= sz; /* (REAL*4 vs COMPLEX*8) */ -v1r = ReadOp(re+idx, fp_f); /* read 1st element */ +v1r = ReadOp(re+idx, fp_f); /* read 1st element */ v1i = ReadOp(im+idx, fp_f); v2r = ReadOp(re+rev, fp_f); /* read 2nd element */ v2i = ReadOp(im+rev, fp_f); @@ -652,8 +648,6 @@ uint32 entry, v, idx1, idx2; int32 exc, exd; t_bool debug = DEBUG_PRI (cpu_dev, DEB_SIG); -if ((cpu_unit.flags & UNIT_SIGNAL) == 0) /* SIGNAL option installed? */ - return stop_inst; entry = IR & 017; /* mask to entry point */ @@ -685,7 +679,7 @@ switch (entry) { /* decode IR<3:0> */ sig_bitrev(op[1].word, op[1].word+2, op[2].word-1, op[3].word, 4); PC = op[0].word & VAMASK; break; - + case 001: /* BTRFY (OP_AAFFKK) */ /* BTRFY - butterfly operation * JSB BTRFY @@ -696,7 +690,7 @@ switch (entry) { /* decode IR<3:0> */ * DEF node,I index of 1st op (1 based) * DEF lmax,I offset to 2nd op (0 based) */ sig_btrfy(op[1].word, op[1].word+2, - op[2], op[3], + op[2], op[3], 2*(op[4].word-1), 2*op[5].word); PC = op[0].word & VAMASK; break; @@ -724,17 +718,17 @@ switch (entry) { /* decode IR<3:0> */ sig_cmul(&m1, &m2, wr, wi, c, d); /* (WR,WI) * (c,d) */ c = sig_scadd(000, TRUE, p1, p2); /* 0.5*(p1+p2) */ d = sig_scadd(020, TRUE, p3, p4); /* 0.5*(p3-p4) */ - (void)fp_exec(000, &p1, c, m1); /* VR[idx1] := 0.5*(p1+p2) + real(W*(c,d)) */ - WriteOp(RE(v + idx1), p1, fp_f); + (void)fp_exec(000, &p1, c, m1); /* VR[idx1] := 0.5*(p1+p2) + real(W*(c,d)) */ + WriteOp(RE(v + idx1), p1, fp_f); (void)fp_exec(000, &p2, d, m2); /* VI[idx1] := 0.5*(p3-p4) + imag(W*(c,d)) */ - WriteOp(IM(v + idx1), p2, fp_f); + WriteOp(IM(v + idx1), p2, fp_f); (void)fp_exec(020, &p1, c, m1); /* VR[idx2] := 0.5*(p1+p2) - imag(W*(c,d)) */ - WriteOp(RE(v + idx2), p1, fp_f); + WriteOp(RE(v + idx2), p1, fp_f); (void)fp_exec(020, &p2, d, m2); /* VI[idx2] := 0.5*(p3-p4) - imag(W*(c,d)) */ - WriteOp(IM(v + idx2), p2, fp_f); + WriteOp(IM(v + idx2), p2, fp_f); PC = op[0].word & VAMASK; - break; - + break; + case 003: /* PRSCR (OP_AAFFKK) */ /* PRSCR unscramble for phasor MPY * JSB PRSCR @@ -754,18 +748,18 @@ switch (entry) { /* decode IR<3:0> */ p3 = ReadOp(IM(v + idx1), fp_f); /* VI[idx1] */ p4 = ReadOp(IM(v + idx2), fp_f); /* VI[idx2] */ c = sig_scadd(020, FALSE, p1, p2); /* p1-p2 */ - d = sig_scadd(000, FALSE, p3, p4); /* p3+p4 */ + d = sig_scadd(000, FALSE, p3, p4); /* p3+p4 */ sig_cmul(&m1,&m2, wr, wi, c, d); /* (WR,WI) * (c,d) */ c = sig_scadd(000, FALSE, p1, p2); /* p1+p2 */ d = sig_scadd(020, FALSE, p3,p4); /* p3-p4 */ (void)fp_exec(020, &p1, c, m2); /* VR[idx1] := (p1-p2) - imag(W*(c,d)) */ - WriteOp(RE(v + idx1), p1, fp_f); - (void)fp_exec(000, &p2, d, m1); /* VI[idx1] := (p3-p4) + real(W*(c,d)) */ - WriteOp(IM(v + idx1), p2, fp_f); + WriteOp(RE(v + idx1), p1, fp_f); + (void)fp_exec(000, &p2, d, m1); /* VI[idx1] := (p3-p4) + real(W*(c,d)) */ + WriteOp(IM(v + idx1), p2, fp_f); (void)fp_exec(000, &p1, c, m2); /* VR[idx2] := (p1+p2) + imag(W*(c,d)) */ - WriteOp(RE(v + idx2), p1, fp_f); + WriteOp(RE(v + idx2), p1, fp_f); (void)fp_exec(020, &p2, m1, d); /* VI[idx2] := imag(W*(c,d)) - (p3-p4) */ - WriteOp(IM(v + idx2), p2, fp_f); + WriteOp(IM(v + idx2), p2, fp_f); PC = op[0].word & VAMASK; break; @@ -788,7 +782,7 @@ switch (entry) { /* decode IR<3:0> */ PC = op[0].word & VAMASK; break; - + case 005: /* BTRF1 (OP_AAAFFKK) */ /* BTRF1 - butterfly operation with real*4 vectors * JSB BTRF1 @@ -804,7 +798,7 @@ switch (entry) { /* decode IR<3:0> */ op[5].word-1, op[6].word); PC = op[0].word & VAMASK; break; - + case 006: /* .CADD (OP_AAA) */ /* .CADD Complex addition * JSB .CADD @@ -814,7 +808,7 @@ switch (entry) { /* decode IR<3:0> */ * complex addition is: (a+bi) + (c+di) => (a+c) + (b+d)i */ sig_caddsub(000,op); break; - + case 007: /* .CSUB (OP_AAA) */ /* .CSUB Complex subtraction * JSB .CSUB @@ -841,7 +835,7 @@ switch (entry) { /* decode IR<3:0> */ WriteOp(RE(op[0].word), p1, fp_f); /* write real result */ WriteOp(IM(op[0].word), p2, fp_f); /* write imag result */ break; - + case 011: /* .CDIV (OP_AAA) */ /* .CDIV Complex division * call: @@ -875,7 +869,7 @@ switch (entry) { /* decode IR<3:0> */ (void)fp_exec(070, &p3, NOP, p2); /* p3 := (b-ad/c)/(c+dd/c) == (bc-ad)/cc+dd) */ WriteOp(IM(op[0].word), p3, fp_f); /* Write imag result */ break; - + case 012: /* CONJG (OP_AAA) */ /* CONJG build A-Bi from A+Bi * call: @@ -889,7 +883,7 @@ switch (entry) { /* decode IR<3:0> */ WriteOp(RE(op[1].word), a, fp_f); /* write real */ WriteOp(IM(op[1].word), b, fp_f); /* write imag */ break; - + case 013: /* ..CCM (OP_A) */ /* ..CCM complement complex * call @@ -905,7 +899,7 @@ switch (entry) { /* decode IR<3:0> */ WriteOp(RE(v), a, fp_f); /* write real */ WriteOp(IM(v), b, fp_f); /* write imag */ break; - + case 014: /* AIMAG (OP_AA) */ /* AIMAG return the imaginary part in AB * JSB AIMAG @@ -924,7 +918,7 @@ switch (entry) { /* decode IR<3:0> */ * DEF result,I complex number * DEF repart,I real value * DEF impart,I imaginary value */ - WriteOp(RE(op[1].word), op[2], fp_f); /* write real part */ + WriteOp(RE(op[1].word), op[2], fp_f); /* write real part */ WriteOp(IM(op[1].word), op[3], fp_f); /* write imag part */ break; diff --git a/HP2100/hp2100_defs.h b/HP2100/hp2100_defs.h index f5b935fd..b0e8ff40 100644 --- a/HP2100/hp2100_defs.h +++ b/HP2100/hp2100_defs.h @@ -23,6 +23,12 @@ be 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-Sep-08 JDB Added POLL_FIRST to indicate immediate connection attempt + 15-Jul-08 JDB Rearranged declarations with hp2100_cpu.h + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 25-Jun-08 JDB Added PIF device + 17-Jun-08 JDB Declared fmt_char() function + 26-May-08 JDB Added MPX device 24-Apr-08 JDB Added I_MRG_I, I_JSB, I_JSB_I, and I_JMP instruction masks 14-Apr-08 JDB Changed TMR_MUX to TMR_POLL for idle support Added POLLMODE, sync_poll() declaration @@ -52,11 +58,14 @@ 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 */ + /* Simulator stop and notification codes */ #define STOP_RSRV 1 /* must be 1 */ @@ -70,12 +79,9 @@ #define STOP_PWROFF 9 /* device powered off */ #define NOTE_IOG 10 /* I/O instr executed */ -#define ABORT_PRO 1 /* protection abort */ - /* Memory */ #define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < fwanxm) #define VA_N_SIZE 15 /* virtual addr size */ #define VASIZE (1 << VA_N_SIZE) #define VAMASK 077777 /* virt addr mask */ @@ -92,8 +98,6 @@ #define DMASK 0177777 /* 16b data mask/maximum value */ #define DMAX 0077777 /* 16b maximum signed value */ #define DMASK8 0377 /* 8b data mask/maximum value */ -#define AR ABREG[0] /* A = reg 0 */ -#define BR ABREG[1] /* B = reg 1 */ /* Portable conversions (sign-extension, unsigned-to-signed) */ @@ -102,132 +106,90 @@ #define INT16(u) ((u) > DMAX ? (-(int16) (DMASK - (u)) - 1) : (int16) (u)) #define INT32(u) ((u) > DMAX32 ? (-(int32) (DMASK32 - (u)) - 1) : (int32) (u)) -/* Memory reference instructions */ - -#define I_IA 0100000 /* indirect address */ -#define I_AB 0004000 /* A/B select */ -#define I_CP 0002000 /* current page */ -#define I_DISP 0001777 /* page displacement */ -#define I_PAGENO 0076000 /* page number */ - -/* Other instructions */ - -#define I_NMRMASK 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 */ - -/* Instruction masks */ - -#define I_MRG 0074000 /* MRG instructions */ -#define I_MRG_I (I_MRG | I_IA) /* MRG indirect instruction group */ -#define I_JSB 0014000 /* JSB instruction */ -#define I_JSB_I (I_JSB | I_IA) /* JSB,I instruction */ -#define I_JMP 0024000 /* JMP instruction */ -#define I_ISZ 0034000 /* ISZ instruction */ - -#define I_IOG 0107700 /* I/O group instruction */ -#define I_SFS 0102300 /* SFS instruction */ -#define I_STF 0102100 /* STF instruction */ - -/* DMA channels */ - -#define DMA_OE 020000000000 /* byte packing odd/even flag */ -#define DMA1_STC 0100000 /* DMA - issue STC */ -#define DMA1_PB 0040000 /* DMA - pack bytes */ -#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 */ - uint32 latency; /* 1st cycle delay */ - uint32 packer; /* byte-packer holding reg */ - }; - -/* Memory management */ - -#define VA_N_OFF 10 /* offset width */ -#define VA_M_OFF ((1 << VA_N_OFF) - 1) /* offset mask */ -#define VA_GETOFF(x) ((x) & VA_M_OFF) -#define VA_N_PAG (VA_N_SIZE - VA_N_OFF) /* page width */ -#define VA_V_PAG (VA_N_OFF) -#define VA_M_PAG ((1 << VA_N_PAG) - 1) -#define VA_GETPAG(x) (((x) >> VA_V_PAG) & VA_M_PAG) - -/* Maps */ - -#define MAP_NUM 4 /* num maps */ -#define MAP_LNT (1 << VA_N_PAG) /* map length */ -#define MAP_MASK ((MAP_NUM * MAP_LNT) - 1) -#define SMAP 0 /* system map */ -#define UMAP (SMAP + MAP_LNT) /* user map */ -#define PAMAP (UMAP + MAP_LNT) /* port A map */ -#define PBMAP (PAMAP + MAP_LNT) /* port B map */ - -/* 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) - -/* Map status register */ - -#define MST_ENBI 0100000 /* mem enb @ int */ -#define MST_UMPI 0040000 /* usr map @ int */ -#define MST_ENB 0020000 /* mem enb */ -#define MST_UMP 0010000 /* usr map */ -#define MST_PRO 0004000 /* protection */ -#define MST_FLT 0002000 /* fence comp */ -#define MST_FENCE 0001777 /* base page fence */ - -/* Map violation register */ - -#define MVI_V_RPR 15 /* 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_POLL 1 /* input polling */ #define POLL_RATE 100 /* poll 100 times per second */ +#define POLL_FIRST 1 /* first poll is "immediate" */ #define POLL_WAIT 15800 /* initial poll ~ 10 msec. */ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization modes */ -/* I/O sub-opcodes */ +/* I/O instruction 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 ioCRS 9 /* control reset ("CLC 0") */ +#define soHLT 0 /* halt */ +#define soFLG 1 /* set/clear flag */ +#define soSFC 2 /* skip on flag clear */ +#define soSFS 3 /* skip on flag set */ +#define soMIX 4 /* merge into A/B */ +#define soLIX 5 /* load into A/B */ +#define soOTX 6 /* output from A/B */ +#define soCTL 7 /* set/clear control */ + + +/* I/O backplane signals. + + The IOSIG declarations mirror the I/O backplane signals. These are sent to + the device I/O signal handlers for action. Normally, only one signal may be + sent at a time. However, the ioCLF signal may be added (arithmetically) to + another signal; the handlers will process the other signal first and then the + CLF signal. + + Implementation notes: + + 1. The first valid signal must have a value > 0, and ioCLF must be + enumerated last, so that adding ioCLF produces a result > ioCLF. + + 2. The signals are structured so that all those that might change the + interrupt state are enumerated after ioSIR. The handlers will detect + this and add an ioSIR signal automatically. + + 3. In hardware, the POPIO signal is asserted concurrently with the CRS + signal. Under simulation, ioPOPIO implies ioCRS, so the handlers are + structured to fall from POPIO handling into CRS handling. It is not + necessary to send both signals for a PRESET. + + 4. In hardware, the SIR signal is generated unconditionally every T5 period + to time the setting of the IRQ flip-flop. Under simulation, ioSIR is + sent to set the PRL, IRQ, and SRQ signals as indicated by the interface + logic. It is necessary to send ioSIR only when that logic indicates a + change in one or more of the three signals. + + 5. In hardware, the ENF signal is unconditionally generated every T2 period + to time the setting of the flag flip-flop and to reset the IRQ flip-flop. + If the flag buffer flip-flip is set, then flag will be set by ENF. If + the flag buffer is clear, ENF will not affect flag. Under simulation, + ioENF is sent to set the flag buffer and flag flip-flops. For those + interfaces where this action is identical to that provided by STF, the + ioENF handler may simply fall into the ioSTF handler. + + 6. The ioSKF signal is never sent to an I/O device. Rather, it is returned + from the device if the SFC or SFS condition is true. + + 7. A device will receive ioNONE when a HLT instruction is executed, and the + H/C bit is clear (i.e., no CLF generated). +*/ + +typedef enum { CLEAR, SET } FLIP_FLOP; /* flip-flop type and values */ + +typedef enum { ioNONE, /* no signal asserted */ + ioSKF, /* skip on flag */ + ioSFC, /* skip if flag is clear */ + ioSFS, /* skip if flag is set */ + ioIOI, /* I/O data input */ + ioIOO, /* I/O data output */ + ioEDT, /* end data transfer */ + ioSIR, /* set interrupt request */ + ioIAK, /* interrupt acknowledge */ + ioCRS, /* control reset */ + ioPOPIO, /* power-on preset to I/O */ + ioCLC, /* clear control flip-flop */ + ioSTC, /* set control flip-flop */ + ioENF, /* enable flag */ + ioSTF, /* set flag flip-flop */ + ioCLF } IOSIG; /* clear flag flip-flop */ /* I/O devices - fixed assignments */ @@ -239,6 +201,7 @@ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization #define PRO 005 /* parity/mem protect */ #define DMA0 006 /* DMA channel 0 */ #define DMA1 007 /* DMA channel 1 */ +#define OPTDEV DMALT0 /* start of optional devices */ #define VARDEV (DMA1 + 1) /* start of var assign */ #define M_NXDEV (INT_M (CPU) | INT_M (OVF) | \ INT_M (DMALT0) | INT_M (DMALT1)) @@ -267,6 +230,8 @@ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization #define IPLO 033 /* 12566B link out */ #define DS 034 /* 13037A control */ #define BACI 035 /* 12966A Buffered Async Comm Interface */ +#define MPX 036 /* 12792A/B/C 8-channel multiplexer */ +#define PIF 037 /* 12620A/12936A Privileged Interrupt Fence */ #define MUXL 040 /* 12920A lower data */ #define MUXU 041 /* 12920A upper data */ #define MUXC 042 /* 12920A control */ @@ -285,59 +250,75 @@ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization #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_LNT 64 /* boot ROM 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 */ +typedef uint16 BOOT_ROM [IBL_LNT]; /* boot ROM data */ + /* Dynamic device information table */ +typedef uint32 IODISP (uint32 select_code, IOSIG signal, uint32 data); /* I/O signal dispatch function */ + 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 */ + uint32 devno; /* device select code */ + IODISP *iot; /* pointer to I/O signal dispatcher */ } 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 IOBASE(S) ((S) > ioCLF ? (S) - ioCLF : (S)) /* base signal from compound signal */ + +#define INT_V(x) ((x) & 037) /* device bit position */ +#define INT_M(x) (1u << INT_V (x)) /* device bit mask */ + +#define setSKF(B) data = (uint32) ((B) ? ioSKF : ioNONE) + +#define setPRL(S,B) dev_prl[(S)/32] = dev_prl[(S)/32] & ~INT_M (S) | (((B) & 1) << INT_V (S)) +#define setIRQ(S,B) dev_irq[(S)/32] = dev_irq[(S)/32] & ~INT_M (S) | (((B) & 1) << INT_V (S)) +#define setSRQ(S,B) dev_srq[(S)/32] = dev_srq[(S)/32] & ~INT_M (S) | (((B) & 1) << INT_V (S)) + +#define setstdSKF(N) setSKF ((base_signal == ioSFC) && !N ## _flag || \ + (base_signal == ioSFS) && N ## _flag) + +#define setstdPRL(S,N) setPRL ((S), !(N ## _control & N ## _flag)); +#define setstdIRQ(S,N) setIRQ ((S), N ## _control & N ## _flag & N ## _flagbuf); +#define setstdSRQ(S,N) setSRQ ((S), N ## _flag); + +#define PRL(S) ((dev_prl[(S)/32] >> INT_V (S)) & 1) +#define IRQ(S) ((dev_irq[(S)/32] >> INT_V (S)) & 1) +#define SRQ(S) ((dev_srq[(S)/32] >> INT_V (S)) & 1) #define IOT_V_REASON 16 -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ +#define IORETURN(F,V) ((F) ? (V) : SCPE_OK) /* stop on I/O error */ -/* Function prototypes */ +/* CPU state */ -int32 sync_poll (POLLMODE poll_mode); -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); -t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); +extern uint32 SR; /* S register (for IBL) */ +extern uint32 dev_prl [2], dev_irq [2], dev_srq [2]; /* I/O signal vectors */ + +/* Simulator state */ + +extern FILE *sim_deb; +extern FILE *sim_log; +extern int32 sim_step; +extern int32 sim_switches; + +/* CPU functions */ + +extern t_stat ibl_copy (const BOOT_ROM rom, int32 dev); +extern void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp); + +/* System functions */ + +extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); +extern const char *fmt_char (uint8 ch); +extern t_stat hp_setdev (UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, void *desc); + +/* Standard device functions */ + +extern int32 sync_poll (POLLMODE poll_mode); #endif diff --git a/HP2100/hp2100_diag.txt b/HP2100/hp2100_diag.txt index 27db3549..c605c425 100644 --- a/HP2100/hp2100_diag.txt +++ b/HP2100/hp2100_diag.txt @@ -1,6 +1,6 @@ SIMH/HP 21XX DIAGNOSTICS PERFORMANCE ==================================== - Last update: 2008-05-10 + Last update: 2008-08-07 The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation. @@ -55,7 +55,8 @@ The results of the diagnostic runs are summarized below: 102103 Memory Expansion Unit 1830 3.2-3 Passed 102103 Semiconductor Memory Microcoded 21MX 1644 - No simulation 103301 Time Base Generator 1830 3.2-3 Passed -103115 12936 Privileged Interrupt 1643 - No simulation +103115 12936 Privileged Interrupt 1643 3.8-1 Passed +143300 12620 Breadboard Interface/Priv Int 1813 3.8-1 Passed 103105 12908/12978 WCS 256 Word 1502 - No simulation 103023 13197 WCS 1024 Word 1640 - No simulation 103207 12889 Hardwired Serial Interface 1717 - No simulation @@ -114,7 +115,7 @@ The following stand-alone diagnostics were run for devices not supported by the Part Number DSN Diagnostic Name Code Vers. Result ----------- ------ ------------------------------------ ---- ----- ---------- 13207-16001 101217 2000/Access Comm Processor for 21MX 1728 3.2-3 Passed -20433-????? -- HP 3030 Magnetic Tape Subsystem -- - Not tested +20433-60001 -- HP 3030 Magnetic Tape Subsystem -- - Not tested 22682-16017 177777 HP 2100 Fixed Head Disc/Drum (277x) 1612 3.3-0 Passed 24197-60001 -- 12875 Processor Interconnect Cable B 3.7-1 Passed 24203-60001 -- HP2100A Cartridge Disc Memory (2871) A 3.3-0 Partial @@ -536,7 +537,7 @@ CONFIGURATION: sim> set CPU 2116 HALT instruction 102074 - sim> deposit S 040000 + sim> deposit S 000000 sim> reset sim> go @@ -555,6 +556,61 @@ TEST RESULT: Passed. +---------------------------------------------- +DSN 101105 - Direct Memory Access (2114/15/16) +---------------------------------------------- + +TESTED DEVICE: DMA0 (hp2100_cpu.c) + +CONFIGURATION: sim> set CPU 2114 + sim> set CPU 16K + sim> set LPS diag + + sim> deposit 003612 004036 + + sim> deposit S 000014 + sim> reset + sim> go 100 + + HALT instruction 102074 + + sim> deposit S 000000 + sim> reset + sim> go + +TEST REPORT: H0. START DMA DIAGNOSTIC + + HALT instruction 102027 + + sim> reset + sim> go + + H77. END DIAGNOSTIC + + HALT instruction 102077 + +TEST RESULT: Passed. + +TEST NOTES: Diagnostic tapes 24322-16001 Revs. 1431 and 1502 have a bug in + Test 17. Test 17 checks byte unpacking for output transfers on + 2115 and 2116 computers. The documentation says that it is not + performed on 2114 computers. The prolog for Test 17 does check + if packing is supported, and if not, it skips the test. + + However, the target of the skip is not the entry to Test 20 but + is instead the short version of Test 17. When DMA channel 2 is + tested in Test 17, it fails with: + + E53. D2 FLG CLR + E71. D2 OUT. GOOD=000001, BAD=000000 + + ...because there is no DMA channel 2 on the 2114. + + We work around this problem by setting the jump target to Test + 20 with "deposit 003612 004036". + + + --------------------------------------------- DSN 101220 - Direct Memory Access (2100/21MX) --------------------------------------------- @@ -999,6 +1055,87 @@ TEST RESULT: Passed. +--------------------------------- +DSN 103115 - Privileged Interrupt +--------------------------------- + +TESTED DEVICE: PIF (hp2100_pif.c) + +CONFIGURATION: sim> set PIF 12936A + sim> set LPT DEV=44 + + sim> deposit S 004414 + sim> reset + sim> go 100 + + HALT instruction 102070 + + sim> deposit S 000037 + sim> go + + HALT instruction 102074 + + sim> deposit S 000000 + sim> go + +TEST REPORT: 12936 PRIVILEGED INTERRUPT CARD DIAGNOSTIC + H032 PRESS PRESET(EXT), RUN + + HALT instruction 102032 + + sim> reset + sim> go + + PASS 000001 + + HALT instruction 102077 + +TEST RESULT: Passed. + + + +------------------------------------- +DSN 143300 - General Purpose Register +------------------------------------- + +TESTED DEVICE: PIF (hp2100_pif.c) + +CONFIGURATION: sim> set PIF 12620A + + sim> deposit S 000037 + sim> reset + sim> go 100 + + HALT instruction 102074 + + sim> deposit S 001000 + sim> go + +TEST REPORT: GENERAL PURPOSE REGISTER DIAGNOSTIC, DSN 143300 + + HALT instruction 102075 + + sim> deposit A 000001 + sim> deposit S 000000 + sim> go + + H024 PRESS PRESET (EXT&INT),RUN + + HALT instruction 102024 + + sim> reset + sim> go + + H025 BASIC I-O COMPLETED + + PASS 000001 + + HALT instruction 102077 + +TEST RESULT: Passed. + + + --------------------------------------------------- DSN 103110 - 12920A Asynchronous Multiplexer (Data) --------------------------------------------------- @@ -2228,7 +2365,7 @@ TEST NOTES: Steps 4, 8, and 10 test the protected cylinder bit. Step 7 DSN 112200 - 9-Track Magnetic Tape (7970B, 13181) ------------------------------------------------- -DEVICE: MS (hp2100_ms.c) +TESTED DEVICE: MS (hp2100_ms.c) CONFIGURATION: sim> detach MSC0 sim> set MSC 13181A @@ -2389,7 +2526,7 @@ TEST NOTES: Test 23 verifies the LRCC and CRCC values obtained from the DSN 112200 - 9-Track Magnetic Tape (7970E, 13183) ------------------------------------------------- -DEVICE: MS (hp2100_ms.c) +TESTED DEVICE: MS (hp2100_ms.c) CONFIGURATION: sim> detach MSC0 sim> set MSC 13183A @@ -2769,9 +2906,8 @@ TEST REPORT: (none) TEST RESULT: Not tested. -TEST NOTES: The limited documentation available for this unit suggests that - the diagnostic is HP product number 20433, but no copy of this - diagnostic has been found. +TEST NOTES: No copy of the diagnostic (HP product number 20433) has been + found. diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c index 17c5c216..86e4ed6c 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-2006, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,10 +23,12 @@ 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 + DP 12557A 2871 disk subsystem 13210A 7900 disk subsystem - 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified) + 10-Aug-08 JDB Added REG_FIT to register variables < 32-bit size + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 28-Dec-06 JDB Added ioCRS state to I/O decoders 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 @@ -60,6 +62,14 @@ 29-Nov-00 RMS Made variable names unique 21-Nov-00 RMS Fixed flag, buffer power up state + References: + - 7900A Disc Drive Operating and Service Manual (07900-90002, Feb-1975) + - 13210A Disc Drive Interface Kit Operating and Service Manual + (13210-90003, Nov-1974) + - 12557A Cartridge Disc Interface Kit Operating and Service Manual + (12557-90001, Sep-1970) + + The simulator uses a number of state variables: dpc_busy set to drive number + 1 when the controller is busy @@ -97,13 +107,6 @@ drive's current position register during a read, i.e., the "on-disc" address field is assumed to match the current position. - References: - - 7900A Disc Drive Operating and Service Manual (07900-90002, Feb-1975) - - 13210A Disc Drive Interface Kit Operating and Service Manual - (13210-90003, Nov-1974) - - 12557A Cartridge Disc Interface Kit Operating and Service Manual - (12557-90001, Sep-1970) - The following implemented behaviors have been inferred from secondary sources (diagnostics, operating system drivers, etc.), due to absent or contradictory authoritative information; future correction may be needed: @@ -203,11 +206,12 @@ #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; +FLIP_FLOP dpc_command = CLEAR; /* cch command flip-flop */ +FLIP_FLOP dpc_control = CLEAR; /* cch control flip-flop */ +FLIP_FLOP dpc_flag = CLEAR; /* cch flag flip-flop */ +FLIP_FLOP dpc_flagbuf = CLEAR; /* cch flag buffer flip-flop */ -int32 dp_ctype = 1; /* ctrl type */ +enum { A12557, A13210 } dp_ctype = A13210; /* ctrl type */ int32 dpc_busy = 0; /* cch unit */ int32 dpc_poll = 0; /* cch poll enable */ int32 dpc_cnt = 0; /* check count */ @@ -218,6 +222,12 @@ 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 */ + +FLIP_FLOP dpd_command = CLEAR; /* dch command flip-flop */ +FLIP_FLOP dpd_control = CLEAR; /* dch control flip-flop */ +FLIP_FLOP dpd_flag = CLEAR; /* dch flag flip-flop */ +FLIP_FLOP dpd_flagbuf = CLEAR; /* dch flag buffer flip-flop */ + int32 dpd_xfer = 0; /* xfer in prog */ int32 dpd_wval = 0; /* write data valid */ int32 dp_ptr = 0; /* buffer ptr */ @@ -229,8 +239,8 @@ uint16 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */ uint16 dpxb[DP_NUMWD]; /* sector buffer */ DEVICE dpd_dev, dpc_dev; -int32 dpdio (int32 inst, int32 IR, int32 dat); -int32 dpcio (int32 inst, int32 IR, int32 dat); +uint32 dpdio (uint32 select_code, IOSIG signal, uint32 data); +uint32 dpcio (uint32 select_code, IOSIG signal, uint32 data); t_stat dpc_svc (UNIT *uptr); t_stat dpd_svc (UNIT *uptr); t_stat dpc_reset (DEVICE *dptr); @@ -251,8 +261,8 @@ t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); */ DIB dp_dib[] = { - { DPD, 0, 0, 0, 0, 0, &dpdio }, - { DPC, 0, 0, 0, 0, 0, &dpcio } + { DPD, &dpdio }, + { DPC, &dpcio } }; #define dpd_dib dp_dib[0] @@ -265,11 +275,10 @@ REG dpd_reg[] = { { 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 (CMD, dpd_command, 0) }, + { FLDATA (CTL, dpd_control, 0) }, + { FLDATA (FLG, dpd_flag, 0) }, + { FLDATA (FBF, dpd_flagbuf, 0) }, { FLDATA (XFER, dpd_xfer, 0) }, { FLDATA (WVAL, dpd_wval, 0) }, { ORDATA (DEVNO, dpd_dib.devno, 6), REG_HRO }, @@ -313,16 +322,15 @@ 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 (CMD, dpc_command, 0) }, + { FLDATA (CTL, dpc_control, 0) }, + { FLDATA (FLG, dpc_flag, 0) }, + { FLDATA (FBF, dpc_flagbuf, 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 }, + { DRDATA (RARC, dpc_rarc, 8), PV_RZRO | REG_FIT }, + { DRDATA (RARH, dpc_rarh, 2), PV_RZRO | REG_FIT }, + { DRDATA (RARS, dpc_rars, 5), PV_RZRO | REG_FIT }, { 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 }, @@ -362,113 +370,237 @@ DEVICE dpc_dev = { &dpc_dib, DEV_DISABLE }; -/* IO instructions */ -int32 dpdio (int32 inst, int32 IR, int32 dat) +/* Data channel I/O signal handler. + + For the 12557A, the card contains the usual control, flag, and flag buffer + flip-flops. PRL, IRQ, and SRQ are standard. A command flip-flop indicates + that data is available. + + For the 13210A, the card has a flag and a flag buffer flip-flop, but no + control or interrupt flip-flop. SRQ is standard. IRQ and PRL are not + driven, and the card does not respond to IAK. STC sets the command flip-flop + to initiate a data transfer. CLC has no effect. + + Implementation notes: + + 1. The CRS signal clears the drive attention register. Under simulation, + drive attention status is generated dynamically, so there is no attention + register. +*/ + +uint32 dpdio (uint32 select_code, IOSIG signal, uint32 data) { -int32 devd; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + dpd_flag = dpd_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + dpd_flag = dpd_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (dpd); break; - case ioOTX: /* output */ - dpd_obuf = dat; - if (!dpc_busy || dpd_xfer) dpd_wval = 1; /* if !overrun, valid */ + + case ioSFS: /* skip if flag is set */ + setstdSKF (dpd); break; - case ioMIX: /* merge */ - dat = dat | dpd_ibuf; + + case ioIOI: /* I/O data input */ + data = dpd_ibuf; break; - case ioLIX: /* load */ - dat = dpd_ibuf; + + case ioIOO: /* I/O data output */ + dpd_obuf = data; + + if (!dpc_busy || dpd_xfer) /* if !overrun */ + dpd_wval = 1; /* valid */ break; - case ioCRS: /* control reset (action unverif) */ - 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; + + case ioPOPIO: /* power-on preset to I/O */ + dpd_flag = dpd_flagbuf = SET; /* set flag buffer and flag */ + + if (dp_ctype == A12557) /* 12557? */ + dpd_obuf = 0; /* clear output buffer */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + dpd_command = CLEAR; /* clear command */ + + if (dp_ctype == A12557) /* 12557? */ + dpd_control = CLEAR; /* clear control */ + + else { /* 13210 */ + dpc_rarc = 0; /* clear controller cylinder address */ + dpc_ucyl [CW_GETDRV (dpc_obuf)] = 0; /* clear last drive addressed cylinder */ } break; - default: - break; - } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ -return dat; + case ioCLC: /* clear control flip-flop */ + if (dp_ctype == A12557) /* 12557? */ + dpd_control = CLEAR; /* clear control */ + + dpd_xfer = 0; /* clr xfer in progress */ + break; + + + case ioSTC: /* set control flip-flop */ + if (dp_ctype == A12557) /* 12557? */ + dpd_control = SET; /* set control */ + + dpd_command = SET; /* set cmd */ + + if (dpc_busy && !dpd_xfer) /* overrun? */ + dpc_sta[dpc_busy - 1] |= STA_OVR; + break; + + + case ioSIR: /* set interrupt request */ + if (dp_ctype == A12557) { /* 12557? */ + setstdPRL (select_code, dpd); /* set standard PRL signal */ + setstdIRQ (select_code, dpd); /* set standard IRQ signal */ + } + + setstdSRQ (select_code, dpd); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + if (dp_ctype == A12557) /* 12557? */ + dpd_flagbuf = CLEAR; /* clear flag buffer */ + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + dpdio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + dpdio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } -int32 dpcio (int32 inst, int32 IR, int32 dat) + +/* Command channel I/O signal handler. + + The 12557A and 13210A have the usual control, flag, and flag buffer + flip-flops. Only the 12557A has a command flip-flop. IRQ, PRL, and SRQ are + standard. + + Implementation notes: + + 1. In hardware, the command channel card passes PRH to PRL. The data card + actually drives PRL with the command channel's control and flag states, + even though the command channel's control, flag, and flag buffer drive + IRQH. That is, the priority chain is broken at the data card, although + the command card is interrupting. This works in hardware, but we must + break PRL at the command card under simulation to allow the command card + to interrupt. +*/ + +uint32 dpcio (uint32 select_code, IOSIG signal, uint32 data) { -int32 i, devc, fnc, drv; -int32 devd = dpd_dib.devno; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 i, fnc, drv; -devc = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + dpc_flag = dpc_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + dpc_flag = dpc_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (dpc); 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); + + case ioSFS: /* skip if flag is set */ + setstdSKF (dpc); break; - case ioOTX: /* output */ - dpc_obuf = dat; - if (!dp_ctype) break; - IR = IR | I_CTL; /* 13210 OTx causes CLC */ - case ioCRS: /* control reset (action unverif) */ - 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 ioIOI: /* I/O data input */ + data = 0; + + for (i = 0; i < DP_NUMDRV; i++) /* form attention register value */ + if (dpc_sta[i] & STA_ATN) data = data | (1 << i); + break; + + + case ioIOO: /* I/O data output */ + dpc_obuf = data; + + if (dp_ctype == A13210) /* 13210? */ + dpcio (select_code, ioCLC, 0); /* OTx causes CLC */ + break; + + + case ioPOPIO: /* power-on preset to I/O */ + dpc_flag = dpc_flagbuf = SET; /* set flag buffer and flag */ + + if (dp_ctype == A12557) /* 12557? */ + dpd_obuf = 0; /* clear output buffer */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + dpc_control = CLEAR; /* clear control */ + + if (dp_ctype == A12557) /* 12557? */ + dpc_command = CLEAR; /* clear command */ + break; + + + case ioCLC: /* clear control flip-flop */ + dpc_control = CLEAR; /* clr ctl */ + + if (dp_ctype == A12557) /* 12557? */ + dpc_command = CLEAR; /* 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 */ + break; + + + case ioSTC: /* set control flip-flop */ + dpc_control = SET; /* set ctl */ + + if ((dp_ctype == A13210) || !dpc_command) { /* 13210 or command is clear? */ + if (dp_ctype == A12557) /* 12557? */ + dpc_command = SET; /* set command */ + + 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 */ @@ -476,7 +608,9 @@ switch (inst) { /* case on opcode */ break; case FNC_STA: /* rd sta */ - if (dp_ctype) { clrFSR (devd); } /* 13210? clr dch flag */ + if (dp_ctype == A13210) /* 13210? clr dch flag */ + dpdio (dpd_dib.devno, ioCLF, 0); + case FNC_CHK: /* check */ case FNC_AR: /* addr rec */ dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */ @@ -486,19 +620,37 @@ switch (inst) { /* case on opcode */ case FNC_REF: case FNC_INIT: /* refine, init */ dp_goc (fnc, drv, dpc_ctime); /* sched drive */ break; - } /* end case */ - } /* end if */ - } /* end else */ + } /* end case */ + } /* end if */ break; - default: - break; - } -if (IR & I_HC) { clrFSR (devc); } /* H/C option */ -return dat; + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, dpc); /* set standard PRL signal */ + setstdIRQ (select_code, dpc); /* set standard IRQ signal */ + setstdSRQ (select_code, dpc); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + dpc_flagbuf = CLEAR; /* clear flag buffer */ + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + dpcio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + dpcio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Start data channel operation */ void dp_god (int32 fnc, int32 drv, int32 time) @@ -509,6 +661,7 @@ sim_activate (&dpd_unit, time); return; } + /* Start controller operation */ void dp_goc (int32 fnc, int32 drv, int32 time) @@ -530,6 +683,7 @@ sim_activate (&dpc_unit[drv], time); /* activate unit */ return; } + /* Data channel unit service This routine handles the data channel transfers. It also handles @@ -551,37 +705,40 @@ return; t_stat dpd_svc (UNIT *uptr) { -int32 i, drv, devc, devd, st; +int32 i, drv, 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 */ case FNC_AR: /* arec, need cyl */ case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ + if (dpd_command) { /* 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 */ + + dpd_command = CLEAR; /* clr dch cmd */ + dpdio (dpd_dib.devno, ioENF, 0); /* set dch flg */ + 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? */ + case FNC_AR1: /* arec, need hd/sec */ + case FNC_SEEK1: /* seek, need hd/sec */ + if (dpd_command) { /* 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 */ + + dpd_command = CLEAR; /* clr dch cmd */ + dpdio (dpd_dib.devno, ioENF, 0); /* set dch flg */ + if (uptr->FNC == FNC_AR1) { - setFSR (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ + dpc_command = CLEAR; /* clr cch cmd */ + dpcio (dpc_dib.devno, ioENF, 0); /* set cch flg */ + dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set drv attn */ break; /* done if Address Record */ } @@ -590,7 +747,8 @@ switch (uptr->FNC) { /* case function */ break; /* allow prev seek to cmpl */ } if ((dpc_rarc >= DP_NUMCY) || /* invalid cyl? */ - (dp_ctype && (dpc_rars >= DP_NUMSC3))) { /* invalid sector? (13210A) */ + ((dp_ctype == A13210) && /* or 13210A */ + (dpc_rars >= DP_NUMSC3))) { /* and invalid sector? */ 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 */ @@ -607,21 +765,23 @@ switch (uptr->FNC) { /* case function */ else sim_activate (uptr, dpc_xtime); /* no, wait more */ break; - case FNC_STA: /* read status */ - if (CMD (devd) || dp_ctype) { /* dch act or 13210? */ + case FNC_STA: /* read status */ + if (dpd_command || (dp_ctype == A13210)) { /* 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? */ + if (dp_ctype == A13210) 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_command = CLEAR; /* clr cch cmd */ + dpd_command = CLEAR; /* clr dch cmd */ + dpdio (dpd_dib.devno, ioENF, 0); /* set dch flg */ } + dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */ ~(STA_ATN | STA_1ST | STA_OVR | STA_RWU | STA_ACU | STA_EOC | @@ -629,14 +789,14 @@ switch (uptr->FNC) { /* case function */ 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 */ + dpcio (dpc_dib.devno, ioENF, 0); /* set cch flg */ break; } } break; - case FNC_CHK: /* check, need cnt */ - if (CMD (devd)) { /* dch active? */ + case FNC_CHK: /* check, need cnt */ + if (dpd_command) { /* 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 */ @@ -651,6 +811,7 @@ switch (uptr->FNC) { /* case function */ return SCPE_OK; } + /* Drive unit service This routine handles the data transfers. @@ -669,15 +830,15 @@ return SCPE_OK; t_stat dpc_svc (UNIT *uptr) { -int32 da, drv, devc, devd, err; +int32 da, drv, 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_command = CLEAR; /* clr cch cmd */ + dpcio (dpc_dib.devno, ioENF, 0); /* set cch flg */ + dpc_sta[drv] = 0; /* clr status */ dpc_busy = 0; /* ctlr is free */ dpc_poll = 0; /* polling disabled */ @@ -691,8 +852,8 @@ switch (uptr->FNC) { /* case function */ 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 */ + dpc_command = CLEAR; /* clr cch cmd */ + dpcio (dpc_dib.devno, ioENF, 0); /* set cch flg */ } return SCPE_OK; @@ -702,7 +863,7 @@ switch (uptr->FNC) { /* case function */ case FNC_RD: /* read */ case FNC_CHK1: /* check */ if (dp_ptr == 0) { /* new sector? */ - if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; + if (!dpd_command && (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? */ @@ -732,17 +893,17 @@ switch (uptr->FNC) { /* case function */ } dp_ptr = 0; /* wrap buf ptr */ } - if (CMD (devd) && dpd_xfer) { /* dch on, xfer? */ - setFSR (devd); /* set flag */ - } - clrCMD (devd); /* clr dch cmd */ + if (dpd_command && dpd_xfer) /* dch on, xfer? */ + dpdio (dpd_dib.devno, ioENF, 0); /* set dch flg */ + + dpd_command = CLEAR; /* 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 (!dpd_command && !dpd_wval) break; /* xfer done? */ if (uptr->flags & UNIT_WPRT) { /* wr prot? */ dpc_sta[drv] = dpc_sta[drv] | STA_FLG; /* set status */ break; /* done */ @@ -772,10 +933,10 @@ switch (uptr->FNC) { /* case function */ 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 */ + if (dpd_command && dpd_xfer) /* dch on, xfer? */ + dpdio (dpd_dib.devno, ioENF, 0); /* set dch flg */ + + dpd_command = CLEAR; /* clr dch cmd */ sim_activate (uptr, dpc_xtime); /* sched next word */ return SCPE_OK; @@ -784,10 +945,13 @@ switch (uptr->FNC) { /* case function */ } /* end case fnc */ dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set ATN */ -setFSR (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ + +dpc_command = CLEAR; /* clr cch cmd */ +dpcio (dpc_dib.devno, ioENF, 0); /* set cch flg */ + dpc_busy = 0; /* ctlr is free */ dpd_xfer = dpd_wval = 0; + if (err != 0) { /* error? */ perror ("DP I/O error"); clearerr (uptr->fileref); @@ -796,6 +960,7 @@ if (err != 0) { /* error? */ return SCPE_OK; } + /* Reset routine */ t_stat dpc_reset (DEVICE *dptr) @@ -804,19 +969,28 @@ int32 drv; 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; + +if (sim_switches & SWMASK ('P')) { /* PON reset? */ + dpd_ibuf = 0; /* clear buffers */ + dpd_obuf = 0; + dpc_obuf = 0; + dpc_rarc = dpc_rarh = dpc_rars = 0; /* clear RAR */ + } + +if (dptr == &dpc_dev) /* command channel reset? */ + dpcio (dpc_dib.devno, ioPOPIO, 0); /* send POPIO signal to command channel */ +else /* data channel reset */ + dpdio (dpd_dib.devno, ioPOPIO, 0); /* send POPIO signal to data channel */ + +dpc_busy = 0; /* reset controller state */ dpc_poll = 0; -dpd_xfer = dpd_wval = 0; +dpd_xfer = 0; +dpd_wval = 0; +dpc_eoc = 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 */ @@ -825,9 +999,11 @@ for (drv = 0; drv < DP_NUMDRV; drv++) { /* loop thru drives */ dpc_sta[drv] = dpc_sta[drv] & STA_1ST; /* first seek status */ else dpc_sta[drv] = 0; /* clear status */ } + return SCPE_OK; } + /* Attach routine */ t_stat dpc_attach (UNIT *uptr, char *cptr) @@ -839,6 +1015,7 @@ if (r == SCPE_OK) dpc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */ return r; } + /* Detach routine */ t_stat dpc_detach (UNIT* uptr) @@ -847,6 +1024,7 @@ dpc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ return detach_unit (uptr); /* detach unit */ } + /* Load and unload heads */ t_stat dpc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) @@ -861,15 +1039,13 @@ 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 (dpc_poll) /* polling enabled? */ + dpcio (dpc_dib.devno, ioENF, 0); /* set flag */ } return SCPE_OK; } + /* Set controller type */ t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -886,18 +1062,20 @@ dp_ctype = val; return SCPE_OK; } + /* Show controller type */ t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (dp_ctype) fprintf (st, "13210A"); +if (dp_ctype == A13210) fprintf (st, "13210A"); else fprintf (st, "12557A"); return SCPE_OK; } + /* 7900/7901 bootstrap routine (HP 12992F ROM) */ -const uint16 dp_rom[IBL_LNT] = { +const BOOT_ROM dp_rom = { 0106710, /*ST CLC DC ; clr dch */ 0106711, /* CLC CC ; clr cch */ 0017757, /* JSB STAT ; get status */ diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c index 50227a7e..216dfc03 100644 --- a/HP2100/hp2100_dq.c +++ b/HP2100/hp2100_dq.c @@ -1,6 +1,7 @@ /* hp2100_dq.c: HP 2100 12565A disk simulator Copyright (c) 1993-2006, Bill McDermith + Copyright (c) 2004-2008 J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -19,13 +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 the author shall not be + Except as contained in this notice, the names of the authors 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. + in this Software without prior written authorization from the authors. - dq 12565A 2883 disk system + DQ 12565A 2883 disk system - 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified) + 10-Aug-08 JDB Added REG_FIT to register variables < 32-bit size + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 28-Dec-06 JDB Added ioCRS state to I/O decoders 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) @@ -40,6 +43,10 @@ 10-Nov-02 RMS Added boot command, rebuilt like 12559/13210 09-Jan-02 WOM Copied dp driver and mods for 2883 + Reference: + - 12565A Disc Interface Kit Operating and Service Manual (12565-90003, Aug-1973) + + Differences between 12559/13210 and 12565 controllers - 12565 stops transfers on address miscompares; 12559/13210 only stops writes - 12565 does not set error on positioner busy @@ -60,9 +67,6 @@ drive's current position register during a read, i.e., the "on-disc" address field is assumed to match the current position. - Reference: - - 12565A Disc Interface Kit Operating and Service Manual (12565-90003, Aug-1973) - The following implemented behaviors have been inferred from secondary sources (diagnostics, operating system drivers, etc.), due to absent or contradictory authoritative information; future correction may be needed: @@ -140,8 +144,10 @@ #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]; +FLIP_FLOP dqc_command = CLEAR; /* cch command flip-flop */ +FLIP_FLOP dqc_control = CLEAR; /* cch control flip-flop */ +FLIP_FLOP dqc_flag = CLEAR; /* cch flag flip-flop */ +FLIP_FLOP dqc_flagbuf = CLEAR; /* cch flag buffer flip-flop */ int32 dqc_busy = 0; /* cch xfer */ int32 dqc_cnt = 0; /* check count */ @@ -149,6 +155,12 @@ int32 dqc_stime = 100; /* seek time */ int32 dqc_ctime = 100; /* command time */ int32 dqc_xtime = 3; /* xfer time */ int32 dqc_dtime = 2; /* dch time */ + +FLIP_FLOP dqd_command = CLEAR; /* dch command flip-flop */ +FLIP_FLOP dqd_control = CLEAR; /* dch control flip-flop */ +FLIP_FLOP dqd_flag = CLEAR; /* dch flag flip-flop */ +FLIP_FLOP dqd_flagbuf = CLEAR; /* dch flag buffer flip-flop */ + int32 dqd_obuf = 0, dqd_ibuf = 0; /* dch buffers */ int32 dqc_obuf = 0; /* cch buffers */ int32 dqd_xfer = 0; /* xfer in prog */ @@ -163,8 +175,8 @@ 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); -int32 dqcio (int32 inst, int32 IR, int32 dat); +uint32 dqdio (uint32 select_code, IOSIG signal, uint32 data); +uint32 dqcio (uint32 select_code, IOSIG signal, uint32 data); t_stat dqc_svc (UNIT *uptr); t_stat dqd_svc (UNIT *uptr); t_stat dqc_reset (DEVICE *dptr); @@ -183,8 +195,8 @@ void dq_goc (int32 fnc, int32 drv, int32 time); */ DIB dq_dib[] = { - { DQD, 0, 0, 0, 0, 0, &dqdio }, - { DQC, 0, 0, 0, 0, 0, &dqcio } + { DQD, &dqdio }, + { DQC, &dqcio } }; #define dqd_dib dq_dib[0] @@ -197,11 +209,10 @@ REG dqd_reg[] = { { 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 (CMD, dqd_command, 0) }, + { FLDATA (CTL, dqd_control, 0) }, + { FLDATA (FLG, dqd_flag, 0) }, + { FLDATA (FBF, dqd_flagbuf, 0) }, { FLDATA (XFER, dqd_xfer, 0) }, { FLDATA (WVAL, dqd_wval, 0) }, { ORDATA (DEVNO, dqd_dib.devno, 6), REG_HRO }, @@ -241,14 +252,13 @@ 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 }, + { FLDATA (CMD, dqc_command, 0) }, + { FLDATA (CTL, dqc_control, 0) }, + { FLDATA (FLG, dqc_flag, 0) }, + { FLDATA (FBF, dqc_flagbuf, 0) }, + { DRDATA (RARC, dqc_rarc, 8), PV_RZRO | REG_FIT }, + { DRDATA (RARH, dqc_rarh, 5), PV_RZRO | REG_FIT }, + { DRDATA (RARS, dqc_rars, 5), PV_RZRO | REG_FIT }, { 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) }, @@ -280,108 +290,176 @@ DEVICE dqc_dev = { &dqc_dib, DEV_DISABLE }; -/* IO instructions */ -int32 dqdio (int32 inst, int32 IR, int32 dat) +/* Data channel I/O signal handler */ + +uint32 dqdio (uint32 select_code, IOSIG signal, uint32 data) { -int32 devd; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + dqd_flag = dqd_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + dqd_flag = dqd_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (dqd); break; - case ioOTX: /* output */ - dqd_obuf = dat; - if (!dqc_busy || dqd_xfer) dqd_wval = 1; /* if !overrun, valid */ + + case ioSFS: /* skip if flag is set */ + setstdSKF (dqd); break; - case ioMIX: /* merge */ - dat = dat | dqd_ibuf; + + case ioIOI: /* I/O data input */ + data = dqd_ibuf; break; - case ioLIX: /* load */ - dat = dqd_ibuf; + + case ioIOO: /* I/O data output */ + dqd_obuf = data; + + if (!dqc_busy || dqd_xfer) + dqd_wval = 1; /* if !overrun, valid */ break; - case ioCRS: /* control reset (action unverif) */ - 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; - } + + case ioPOPIO: /* power-on preset to I/O */ + dqd_flag = dqd_flagbuf = SET; /* set flag and flag buffer */ + dqd_obuf = 0; /* clear output buffer */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + dqd_command = CLEAR; /* clear command */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + dqd_control = CLEAR; /* clear control */ + dqd_xfer = 0; /* clr xfer */ break; - default: - break; - } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ -return dat; + case ioSTC: /* set control flip-flop */ + dqd_command = SET; /* set ctl, cmd */ + dqd_control = SET; + + if (dqc_busy && !dqd_xfer) /* overrun? */ + dqc_sta[dqc_busy - 1] |= STA_DTE; + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, dqd); /* set standard PRL signal */ + setstdIRQ (select_code, dqd); /* set standard IRQ signal */ + setstdSRQ (select_code, dqd); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + dqd_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + dqdio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + dqdio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } -int32 dqcio (int32 inst, int32 IR, int32 dat) + +/* Command channel I/O signal handler. + + Implementation notes: + + 1. The input buffer register is not connected to the disc controller. + Pullups on the card and an inversion result in reading zeros when IOI is + signalled. +*/ + +uint32 dqcio (uint32 select_code, IOSIG signal, uint32 data) { -int32 devc, fnc, drv; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 fnc, drv; -devc = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + dqc_flag = dqc_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + dqc_flag = dqc_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (dqc); break; - case ioOTX: /* output */ - dqc_obuf = dat; + + case ioSFS: /* skip if flag is set */ + setstdSKF (dqc); break; - case ioLIX: /* load */ - dat = 0; - case ioMIX: /* merge */ - break; /* no data */ - case ioCRS: /* control reset (action unverif) */ - 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 ioIOI: /* I/O data input */ + data = 0; /* no data */ + break; + + + case ioIOO: /* I/O data output */ + dqc_obuf = data; + break; + + + case ioPOPIO: /* power-on preset to I/O */ + dqc_flag = dqc_flagbuf = SET; /* set flag and flag buffer */ + dqc_obuf = 0; /* clear output buffer */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + dqc_command = CLEAR; /* clear command */ + dqc_control = CLEAR; /* clear control */ + + 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 */ + break; + + + case ioSTC: /* set control flip-flop */ + dqc_control = SET; /* set ctl */ + + if (!dqc_command) { /* cmd clr? */ + dqc_command = SET; /* set cmd */ + 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 */ @@ -393,19 +471,37 @@ switch (inst) { /* case on opcode */ case FNC_AS: /* address skip */ dq_goc (fnc, drv, dqc_ctime); /* sched drive */ break; - } /* end case */ - } /* end if !CMD */ - } /* end else */ + } /* end case */ + } /* end if !CMD */ break; - default: - break; - } -if (IR & I_HC) { clrFSR (devc); } /* H/C option */ -return dat; + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, dqc); /* set standard PRL signal */ + setstdIRQ (select_code, dqc); /* set standard IRQ signal */ + setstdSRQ (select_code, dqc); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + dqc_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + dqcio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + dqcio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Start data channel operation */ void dq_god (int32 fnc, int32 drv, int32 time) @@ -458,20 +554,19 @@ return; t_stat dqd_svc (UNIT *uptr) { -int32 drv, devc, devd, st; +int32 drv, 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 */ case FNC_LA: /* arec, need cyl */ case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ + if (dqd_command) { /* 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 */ + dqd_command = CLEAR; /* clr dch cmd */ + dqdio (dqd_dib.devno, ioENF, 0); /* set dch flg */ if (uptr->FNC == FNC_LA) uptr->FNC = FNC_LA1; else uptr->FNC = FNC_SEEK1; /* advance state */ } @@ -480,15 +575,15 @@ switch (uptr->FNC) { /* case function */ case FNC_LA1: /* arec, need hd/sec */ case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ + if (dqd_command) { /* 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 */ + dqd_command = CLEAR; /* clr dch cmd */ + dqdio (dqd_dib.devno, ioENF, 0); /* set dch flg */ if (uptr->FNC == FNC_LA1) { - setFSR (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ + dqc_command = CLEAR; /* clr cch cmd */ + dqcio (dqc_dib.devno, ioENF, 0); /* set cch flg */ break; /* done if Load Address */ } if (sim_is_active (&dqc_unit[drv])) break; /* if busy, seek check */ @@ -515,23 +610,23 @@ switch (uptr->FNC) { /* case function */ break; case FNC_STA: /* read status */ - if (CMD (devd)) { /* dch active? */ + if (dqd_command) { /* 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_command = CLEAR; /* clr cch cmd */ + dqd_command = CLEAR; /* clr dch cmd */ + dqdio (dqd_dib.devno, ioENF, 0); /* set dch flg */ 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? */ + if (dqd_command) { /* 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 */ @@ -575,8 +670,8 @@ 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_command = CLEAR; /* clr cch cmd */ + dqcio (dqc_dib.devno, ioENF, 0); /* set cch flg */ dqc_sta[drv] = 0; /* clr status */ dqc_busy = 0; /* ctlr is free */ dqd_xfer = dqd_wval = 0; @@ -591,18 +686,18 @@ switch (uptr->FNC) { /* case function */ } else dqc_sta[drv] = dqc_sta[drv] & ~STA_BSY; /* drive not busy */ case FNC_SEEK3: - if (dqc_busy || FLG (devc)) { /* ctrl busy? */ + if (dqc_busy || dqc_flag) { /* 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 */ + dqc_command = CLEAR; /* clr cch cmd */ + dqcio (dqc_dib.devno, ioENF, 0); /* set cch flg */ } return SCPE_OK; case FNC_RA: /* read addr */ - if (!CMD (devd)) break; /* dch clr? done */ + if (!dqd_command) 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 */ @@ -611,8 +706,8 @@ switch (uptr->FNC) { /* case function */ } else break; dq_ptr = dq_ptr + 1; - setFSR (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ + dqd_command = CLEAR; /* clr dch cmd */ + dqdio (dqd_dib.devno, ioENF, 0); /* set dch flg */ sim_activate (uptr, dqc_xtime); /* sched next word */ return SCPE_OK; @@ -620,7 +715,7 @@ switch (uptr->FNC) { /* case function */ case FNC_RD: /* read */ case FNC_CHK1: /* check */ if (dq_ptr == 0) { /* new sector? */ - if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; + if (!dqd_command && (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? */ @@ -648,17 +743,17 @@ switch (uptr->FNC) { /* case function */ } dq_ptr = 0; /* wrap buf ptr */ } - if (CMD (devd) && dqd_xfer) { /* dch on, xfer? */ - setFSR (devd); /* set flag */ + if (dqd_command && dqd_xfer) { /* dch on, xfer? */ + dqdio (dqd_dib.devno, ioENF, 0); /* set flag */ } - clrCMD (devd); /* clr dch cmd */ + dqd_command = CLEAR; /* 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 (!dqd_command && !dqd_wval) break; /* xfer done? */ if (uptr->flags & UNIT_WPRT) { /* write protect? */ dqc_sta[drv] = dqc_sta[drv] | STA_FLG; break; /* done */ @@ -687,10 +782,10 @@ switch (uptr->FNC) { /* case function */ if (err = ferror (uptr->fileref)) break; dq_ptr = 0; } - if (CMD (devd) && dqd_xfer) { /* dch on, xfer? */ - setFSR (devd); /* set flag */ + if (dqd_command && dqd_xfer) { /* dch on, xfer? */ + dqdio (dqd_dib.devno, ioENF, 0); /* set flag */ } - clrCMD (devd); /* clr dch cmd */ + dqd_command = CLEAR; /* clr dch cmd */ sim_activate (uptr, dqc_xtime); /* sched next word */ return SCPE_OK; @@ -698,8 +793,8 @@ switch (uptr->FNC) { /* case function */ return SCPE_IERR; } /* end case fnc */ -setFSR (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ +dqc_command = CLEAR; /* clr cch cmd */ +dqcio (dqc_dib.devno, ioENF, 0); /* set cch flg */ dqc_busy = 0; /* ctlr is free */ dqd_xfer = dqd_wval = 0; if (err != 0) { /* error? */ @@ -718,23 +813,33 @@ int32 drv; 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; + +if (sim_switches & SWMASK ('P')) { /* PON reset? */ + dqd_ibuf = 0; /* clear buffers */ + dqd_obuf = 0; + dqc_obuf = 0; + dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */ + } + +if (dptr == &dqc_dev) /* command channel reset? */ + dqcio (dqc_dib.devno, ioPOPIO, 0); /* send POPIO signal to command channel */ +else /* data channel reset */ + dqdio (dqd_dib.devno, ioPOPIO, 0); /* send POPIO signal to data channel */ + +dqc_busy = 0; /* reset controller state */ +dqd_xfer = 0; +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 */ } + return SCPE_OK; } @@ -770,7 +875,7 @@ return SCPE_OK; /* 7900/7901/2883/2884 bootstrap routine (HP 12992A ROM) */ -const uint16 dq_rom[IBL_LNT] = { +const BOOT_ROM dq_rom = { 0102501, /*ST LIA 1 ; get switches */ 0106501, /* LIB 1 */ 0013765, /* AND D7 ; isolate hd */ diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c index 2796e8cb..d8af0a68 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-2006, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,10 +23,12 @@ 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 + DR 12606B 2770/2771 fixed head disk 12610B 2773/2774/2775 drum - 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified) + 09-Jul-08 JDB Revised drc_boot to use ibl_copy + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 28-Dec-06 JDB Added ioCRS state to I/O decoders 07-Oct-04 JDB Fixed enable/disable from either device Fixed sector return in status word Provided protected tracks and "Writing Enabled" status bit @@ -47,6 +49,13 @@ Fixed variable capacity interaction with SAVE/RESTORE 10-Nov-02 RMS Added BOOT command + References: + - 12606B Disc Memory Interface Kit Operating and Service Manual + (12606-90012, Mar-1970) + - 12610B Drum Memory Interface Kit Operating and Service Manual + (12610-9001, Feb-1970) + + These head-per-track devices are buffered in memory, to minimize overhead. The drum data channel does not have a command flip-flop. Its control @@ -90,15 +99,10 @@ - 3450 RPM = 17.4 ms/revolution - data timing = 8.5 us/word, 550 us/sector - inst timing = 6 inst/word, 12288 inst/revolution - - References: - - 12606B Disc Memory Interface Kit Operating and Service Manual - (12606-90012, Mar-1970) - - 12610B Drum Memory Interface Kit Operating and Service Manual - (12610-9001, Feb-1970) */ #include "hp2100_defs.h" +#include "hp2100_cpu.h" #include /* Constants */ @@ -106,7 +110,7 @@ #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_NUMSC ((drc_unit.flags & UNIT_DRUM)? 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 */ @@ -116,7 +120,7 @@ #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 UNIT_DRUM (1 << UNIT_V_SZ) /* low order bit */ #define SZ_180K 000 /* disks */ #define SZ_360K 002 #define SZ_720K 004 @@ -136,21 +140,21 @@ #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)? \ +#define MAX_TRK (((drc_unit.flags & UNIT_DRUM)? CW_M_DTRK: CW_M_FTRK) + 1) +#define CW_GETTRK(x) ((drc_unit.flags & UNIT_DRUM)? \ (((x) >> CW_V_DTRK) & CW_M_DTRK): \ (((x) >> CW_V_FTRK) & CW_M_FTRK)) -#define CW_PUTTRK(x) ((drc_unit.flags & UNIT_DR)? \ +#define CW_PUTTRK(x) ((drc_unit.flags & UNIT_DRUM)? \ (((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)? \ +#define CW_GETSEC(x) ((drc_unit.flags & UNIT_DRUM)? \ (((x) >> CW_V_DSEC) & CW_M_DSEC): \ (((x) >> CW_V_FSEC) & CW_M_FSEC)) -#define CW_PUTSEC(x) ((drc_unit.flags & UNIT_DR)? \ +#define CW_PUTSEC(x) ((drc_unit.flags & UNIT_DRUM)? \ (((x) & CW_M_DSEC) << CW_V_DSEC): \ (((x) & CW_M_FSEC) << CW_V_FSEC)) @@ -170,14 +174,13 @@ #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 */ + +FLIP_FLOP drd_control = CLEAR; +FLIP_FLOP drd_flag = CLEAR; + int32 drd_ibuf = 0; /* input buffer */ int32 drd_obuf = 0; /* output buffer */ int32 drd_ptr = 0; /* sector pointer */ @@ -190,8 +193,8 @@ static int32 sz_tab[16] = { 0, 655360, 0, 786432, 0, 917504, 0, 0 }; DEVICE drd_dev, drc_dev; -int32 drdio (int32 inst, int32 IR, int32 dat); -int32 drcio (int32 inst, int32 IR, int32 dat); +uint32 drdio (uint32 select_code, IOSIG signal, uint32 data); +uint32 drcio (uint32 select_code, IOSIG signal, uint32 data); t_stat drc_svc (UNIT *uptr); t_stat drc_reset (DEVICE *dptr); t_stat drc_attach (UNIT *uptr, char *cptr); @@ -199,6 +202,7 @@ t_stat drc_boot (int32 unitno, DEVICE *dptr); int32 dr_incda (int32 trk, int32 sec, int32 ptr); int32 dr_seccntr (double simtime); t_stat dr_set_prot (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat dr_show_prot (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); /* DRD data structures @@ -209,8 +213,8 @@ t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); */ DIB dr_dib[] = { - { DRD, 0, 0, 0, 0, 0, &drdio }, - { DRC, 0, 0, 0, 0, 0, &drcio } + { DRD, &drdio }, + { DRC, &drcio } }; #define drd_dib dr_dib[0] @@ -227,11 +231,8 @@ UNIT drd_unit[] = { 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) }, + { FLDATA (CTL, drd_control, 0) }, + { FLDATA (FLG, drd_flag, 0) }, { ORDATA (BPTR, drd_ptr, 6) }, { ORDATA (DEVNO, drd_dib.devno, 6), REG_HRO }, { NULL } @@ -261,7 +262,7 @@ DEVICE drd_dev = { UNIT drc_unit = { UDATA (&drc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ - UNIT_MUSTBUF+UNIT_DR+UNIT_BINK, DR_SIZE) + UNIT_MUSTBUF+UNIT_DRUM+UNIT_BINK, DR_SIZE) }; REG drc_reg[] = { @@ -269,11 +270,6 @@ REG drc_reg[] = { { 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 }, @@ -282,8 +278,8 @@ REG drc_reg[] = { }; MTAB drc_mod[] = { - { UNIT_DR, 0, "disk", NULL, NULL }, - { UNIT_DR, UNIT_DR, "drum", NULL, NULL }, + { UNIT_DRUM, 0, "disk", NULL, NULL }, + { UNIT_DRUM, UNIT_DRUM, "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 }, @@ -296,8 +292,8 @@ MTAB drc_mod[] = { { 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, 0, "TRACKPROT", "TRACKPROT", + &dr_set_prot, &dr_show_prot, NULL }, { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &drd_dev }, { 0 } @@ -311,63 +307,131 @@ DEVICE drc_dev = { &drc_dib, DEV_DISABLE }; -/* IO instructions */ -int32 drdio (int32 inst, int32 IR, int32 dat) +/* Data channel I/O signal handler. + + The data channel card does not follow the usual interface I/O configuration. + PRL is always asserted, the card does not drive IRQ, FLG, or SKF and does not + respond to IAK. SRQ is driven by the output of the flag flip-flop, which + obeys CLF only. There is no flag buffer. The control flip-flop obeys STC + and CLC. Clearing control clears the flag flip-flop, and setting control + sets the flag flip-flop if the interface is configured for writing. On the + 12606B, POPIO and CRS clear the track address register. + + Implementation notes: + + 1. In response to CRS, the 12606B data channel clears only the track address + register; the command channel clears the sector address register and the + direction flip-flop. Under simulation, all three form the control word, + and as CRS is sent to all devices, we simply clear the control word here. +*/ + +uint32 drdio (uint32 select_code, IOSIG signal, uint32 data) { -int32 devd, t; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 t; -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioOTX: /* output */ - drd_obuf = dat; + case ioCLF: /* clear flag flip-flop */ + drd_flag = CLEAR; break; - case ioMIX: /* merge */ - dat = dat | drd_ibuf; + + case ioENF: /* enable flag */ + drd_flag = SET; break; - case ioLIX: /* load */ - dat = drd_ibuf; + + case ioIOI: /* I/O data input */ + data = drd_ibuf; break; - case ioCRS: /* control reset (action unverif) */ - 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); - } + + case ioIOO: /* I/O data output */ + drd_obuf = data; break; - default: - break; - } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ -return dat; + case ioPOPIO: /* power-on preset to I/O */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + if (!(drc_unit.flags & UNIT_DRUM)) /* 12606B? */ + drc_cw = 0; /* clear control word */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + drd_flag = drd_control = CLEAR; /* clear control and flag */ + + if (!drc_run) /* cancel curr op */ + sim_cancel (&drc_unit); + + drc_sta = drc_sta & ~DRS_SAC; /* clear SAC flag */ + break; + + + case ioSTC: /* set control flip-flop */ + drd_control = SET; /* set ctl */ + + if (drc_cw & CW_WR) /* writing? */ + drd_flag = SET; /* 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; + + + case ioSIR: /* set interrupt request */ + setstdSRQ (select_code, drd); /* set SRQ signal */ + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + drdio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + drdio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } -int32 drcio (int32 inst, int32 IR, int32 dat) + +/* Command channel I/O signal dispatcher. + + The command channel card does not follow the usual interface I/O + configuration. PRL is always asserted, the card does not drive IRQ, FLG, or + SRQ and does not respond to IAK. There are no control, flag, or flag buffer + flip-flops. CLF clears the track origin flip-flop; STF is ignored. The + 12606B drives SKF, whereas the 12610B does not. On the 12610B, SFS tests the + Track Origin flip-flop, and SFC tests the Sector Clock Phase (SCP) flip-flop. + + Implementation notes: + + 1. CRS clears the Run Flip-Flop, stopping the current operation. Under + simulation, we allow the data channel signal handler to do this, as the + same operation is invoked by CLC DC, and as CRS is sent to all devices. + + 2. The command channel cannot interrupt, so there is no SIR handler. +*/ + +uint32 drcio (uint32 select_code, IOSIG signal, uint32 data) { +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ int32 sec; -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) && !(drc_unit.flags & UNIT_DR)) { /* CLF disk */ + case ioCLF: /* clear flag flip-flop */ + if (!(drc_unit.flags & UNIT_DRUM)) { /* disk? */ sec = dr_seccntr (sim_gtime ()); /* current sector */ sim_cancel (&drd_unit[TMR_ORG]); /* sched origin tmr */ sim_activate (&drd_unit[TMR_ORG], @@ -375,57 +439,73 @@ switch (inst) { /* case on opcode */ } 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 */ + + case ioSFC: /* skip if flag is clear */ + if (!(drc_unit.flags & UNIT_DRUM)) /* 12606? */ + setSKF (!(CALC_SCP (sim_gtime()))); /* skip if nearing end of sector */ 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 */ + + case ioSFS: /* skip if flag is set */ + if (!(drc_unit.flags & UNIT_DRUM)) /* 12606? */ + setSKF (!sim_is_active (&drd_unit[TMR_ORG])); /* skip if origin seen */ break; - case ioOTX: /* output */ - if (!(drc_unit.flags & UNIT_DR)) { /* disk? */ + + case ioIOI: /* I/O data input */ + data = drc_sta; /* static bits */ + + if (!(drc_unit.flags & UNIT_PROT) || /* not protected? */ + (CW_GETTRK(drc_cw) >= drc_pcount)) /* or not in range? */ + data = data | DRS_WEN; /* set wrt enb status */ + + if (drc_unit.flags & UNIT_ATT) { /* attached? */ + data = data | (dr_seccntr (sim_gtime()) << DRS_V_NS) | DRS_RDY; + if (sim_is_active (&drc_unit)) /* op in progress? */ + data = data | DRS_BSY; + if (CALC_SCP (sim_gtime())) /* SCP ff set? */ + data = data | DRS_SEC; /* set sector flag */ + if (sim_is_active (&drd_unit[TMR_INH]) && /* inhibit timer on? */ + !(drc_cw & CW_WR)) + data = data | DRS_RIF; /* set read inh flag */ + } + break; + + + case ioIOO: /* I/O data output */ + if (!(drc_unit.flags & UNIT_DRUM)) { /* 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 */ + drc_cw = data; /* 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; - } + case ioPOPIO: /* power-on preset to I/O */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + break; /* allow data channel to handle this */ + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + drcio (select_code, ioCLF, 0); /* issue CLF */ + +return data; -return dat; } + /* Unit service */ t_stat drc_svc (UNIT *uptr) { -int32 devd, trk, sec; +int32 trk, sec; uint32 da; uint16 *bptr = (uint16 *) uptr->filebuf; @@ -434,7 +514,6 @@ if ((uptr->flags & UNIT_ATT) == 0) { return IORETURN (dr_stopioe, SCPE_UNATT); } -devd = drd_dib.devno; /* get dch devno */ trk = CW_GETTRK (drc_cw); sec = CW_GETSEC (drc_cw); da = ((trk * DR_NUMSC) + sec) * DR_NUMWD; @@ -448,25 +527,25 @@ if (drc_cw & CW_WR) { /* write? */ 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 */ + if (drd_control) { /* dch active? */ + drdio (drd_dib.devno, ioENF, 0); /* set SRQ */ 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? */ + if (!(drc_unit.flags & UNIT_DRUM)) /* 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 (drd_control) { /* 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 */ + drdio (drd_dib.devno, ioENF, 0); /* set SRQ */ sim_activate (uptr, dr_time); /* sched next word */ } else drc_run = 0; /* clear run ff */ @@ -515,7 +594,7 @@ curword = (int32) fmod (simtime / (double) dr_time, (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_DRUM)? 0: 1)); } /* Reset routine */ @@ -524,15 +603,19 @@ t_stat drc_reset (DEVICE *dptr) { 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 */ + +if (sim_switches & SWMASK ('P')) /* PON reset? */ + drc_sta = drc_cw = drd_ptr = 0; /* clear controller state variables */ + +if (dptr == &drc_dev) /* command channel reset? */ + drcio (drc_dib.devno, ioPOPIO, 0); /* send POPIO signal to command channel */ +else /* data channel reset */ + drdio (drd_dib.devno, ioPOPIO, 0); /* send POPIO signal to data channel */ + sim_cancel (&drc_unit); sim_cancel (&drd_unit[TMR_ORG]); sim_cancel (&drd_unit[TMR_INH]); + return SCPE_OK; } @@ -554,9 +637,11 @@ t_stat dr_set_prot (UNIT *uptr, int32 val, char *cptr, void *desc) int32 count; t_stat status; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; count = (int32) get_uint (cptr, 10, 768, &status); -if (status != SCPE_OK) return status; +if (status != SCPE_OK) + return status; else switch (count) { case 1: case 2: @@ -571,7 +656,8 @@ else switch (count) { case 256: case 512: case 768: - if (drc_unit.flags & UNIT_DR) drc_pcount = count; + if (drc_unit.flags & UNIT_DRUM) + drc_pcount = count; else return SCPE_ARG; break; default: @@ -580,6 +666,14 @@ else switch (count) { return SCPE_OK; } +/* Show protected track count */ + +t_stat dr_show_prot (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "protected tracks=%d", drc_pcount); +return SCPE_OK; +} + /* Set size routine */ t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -591,7 +685,7 @@ 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_DRUM) dr_time = DR_DTIME; /* drum */ else { dr_time = DR_FTIME; /* disk */ if (drc_pcount > 128) drc_pcount = 128; /* max prot track count */ @@ -601,10 +695,15 @@ return SCPE_OK; /* Fixed head disk/drum bootstrap routine (disc subset of disc/paper tape loader) */ -#define BOOT_BASE 056 #define BOOT_START 060 -static const uint16 dr_rom[IBL_LNT - BOOT_BASE] = { +static const BOOT_ROM dr_rom = { /* padded to start at x7760 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0020010, /*DMA 20000+DC */ 0000000, /* 0 */ 0107700, /* CLC 0,C */ @@ -627,20 +726,15 @@ static const uint16 dr_rom[IBL_LNT - BOOT_BASE] = { t_stat drc_boot (int32 unitno, DEVICE *dptr) { -int32 i, dev, ad; -uint16 wd; +const int32 dev = drd_dib.devno; /* data chan select code */ -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) /* only unit 0 */ + return SCPE_NOFNC; +if (ibl_copy (dr_rom, dev)) /* copy boot to memory */ + return SCPE_IERR; + +WritePW (PC + IBL_DPC, dr_rom [IBL_DPC]); /* restore overwritten word */ +WritePW (PC + IBL_END, dr_rom [IBL_END]); /* restore overwritten word */ +PC = PC + BOOT_START; /* correct starting address */ return SCPE_OK; } diff --git a/HP2100/hp2100_ds.c b/HP2100/hp2100_ds.c index 08d38143..7017736c 100644 --- a/HP2100/hp2100_ds.c +++ b/HP2100/hp2100_ds.c @@ -1,6 +1,6 @@ /* hp2100_ds.c: HP 2100 13037 disk controller simulator - Copyright (c) 2004-2007, Robert M. Supnik + Copyright (c) 2004-2008, Robert 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,8 +23,9 @@ 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 + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 31-Dec-07 JDB Corrected and verified ioCRS action 20-Dec-07 JDB Corrected DPTR register definition from FLDATA to DRDATA 28-Dec-06 JDB Added ioCRS state to I/O decoders @@ -33,6 +34,10 @@ 18-Mar-05 RMS Added attached test to detach routine 01-Mar-05 JDB Added SET UNLOAD/LOAD + Reference: + - 13037 Disc Controller Technical Information Package (13037-90902, Aug-1980) + + 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 when there's an event to process: change in CPU interface state, change in @@ -59,13 +64,10 @@ - Spare, defective, protected. The disk files carry only data. - Formatting. The disk files carry only data. - ECC. Data errors are always uncorrectable. - - Reference: - - 13037 Disc Controller Technical Information Package (13037-90902, Aug-1980) */ -#include "hp2100_defs.h" #include +#include "hp2100_defs.h" #define DS_NUMDR 8 /* max drives */ #define DS_DRMASK (DS_NUMDR - 1) @@ -344,9 +346,10 @@ static struct drvtyp drv_tab[] = { { 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; +FLIP_FLOP ds_control = CLEAR; +FLIP_FLOP ds_flag = CLEAR; +FLIP_FLOP ds_flagbuf = CLEAR; +FLIP_FLOP ds_srq = CLEAR; uint32 ds_fifo[DS_FIFO_SIZE] = { 0 }; /* fifo */ uint32 ds_fifo_ip = 0; /* insertion ptr */ @@ -409,7 +412,7 @@ static const uint32 ds_opflags[32] = { /* flags for ops */ }; DEVICE ds_dev; -int32 dsio (int32 inst, int32 IR, int32 dat); +uint32 dsio (uint32 select_code, IOSIG signal, uint32 data); t_stat ds_svc_c (UNIT *uptr); t_stat ds_svc_u (UNIT *uptr); t_stat ds_svc_t (UNIT *uptr); @@ -438,7 +441,7 @@ void ds_cont_rd (UNIT *uptr, uint32 bsize); t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize); void ds_end_rw (UNIT *uptr, uint32 newst); t_stat ds_set_uncorr (UNIT *uptr); -t_stat ds_reset_cmn (DEVICE *dptr); +t_stat ds_clear (void); void ds_sched_atn (UNIT *uptr); uint32 ds_fifo_read (void); void ds_fifo_write (uint32 dat); @@ -452,7 +455,7 @@ void ds_fifo_reset (void); ds_mod DS modifier list */ -DIB ds_dib = { DS, 0, 0, 0, 0, 0, &dsio }; +DIB ds_dib = { DS, &dsio }; UNIT ds_unit[] = { { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | @@ -488,11 +491,10 @@ REG ds_reg[] = { { 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 (CTL, ds_control, 0) }, + { FLDATA (FLG, ds_flag, 0) }, + { FLDATA (FBF, ds_flagbuf, 0) }, + { FLDATA (SRQ, ds_srq, 0) }, { FLDATA (BUSY, ds_busy, 0) }, { FLDATA (CMDF, ds_cmdf, 0) }, { FLDATA (CMDP, ds_cmdp, 0) }, @@ -563,75 +565,132 @@ DEVICE ds_dev = { &ds_dib, DEV_DISABLE }; -/* IO instructions */ -int32 dsio (int32 inst, int32 IR, int32 dat) +/* I/O signal handler. + + The 13175A disc interface is unusual in that the flag and SRQ signals are + decoupled. This is done to allow DMA transfers at the maximum possible speed + (driving SRQ from the flag limits transfers to only every other cycle). SRQ + is based on the card's FIFO; if data or room in the FIFO is available, SRQ is + set to transfer it. The flag is only used to signal an interrupt at the end + of a command. + + Also unusual is that SFC and SFS test different things, rather than + complementaty states of the same thing. SFC tests the busy flip-flop, and + SFS tests the flag flip-flop. + + Implementation notes: + + 1. The dispatcher runs the command poll after each I/O signal, except for + SIR and ENF. Running the poll for these two will cause multi-drive + access to fail. +*/ + +uint32 dsio (uint32 select_code, IOSIG signal, uint32 data) { -uint32 dev = IR & I_DEVMASK; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + ds_flag = ds_flagbuf = CLEAR; /* clear flag */ + ds_srq = CLEAR; /* CLF clears SRQ */ break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + ds_flag = ds_flagbuf = SET; /* set flag and flag buffer */ break; - case ioSFC: /* skip flag clear */ - if (ds_busy == 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setSKF (ds_busy == 0); /* skip if not busy */ break; - case ioOTX: /* output */ + + case ioSFS: /* skip if flag is set */ + setstdSKF (ds); + break; + + + case ioIOI: /* I/O data input */ + data = ds_fifo_read (); + break; + + + case ioIOO: /* I/O data output */ if (ds_cmdf) { /* expecting command? */ - ds_cmd = dat; /* save command */ + ds_cmd = data; /* save command */ ds_cmdf = 0; ds_cmdp = 1; /* command present */ } - else ds_fifo_write (dat); /* put in fifo */ + + else + ds_fifo_write (data); /* put in fifo */ break; - case ioMIX: /* merge */ - dat = dat | ds_fifo_read (); - break; - case ioLIX: /* load */ - dat = ds_fifo_read (); - break; + case ioPOPIO: /* power-on preset to I/O */ + ds_flag = ds_flagbuf = SET; /* set flag and flag buffer */ + ds_cmdp = 0; /* clear command ready */ + /* fall into CRS handler */ case ioCRS: /* control reset */ - clrCTL (dev); /* clear control */ + ds_control = CLEAR; /* clear control */ ds_cmdf = 0; /* not expecting command */ - ds_cmdp = 0; /* and none pending */ - ds_reset_cmn (&ds_dev); /* reset ctrl */ + ds_clear (); /* do controller CLEAR */ 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 */ - } + + case ioCLC: /* clear control flip-flop */ + ds_control = CLEAR; /* clear control */ + ds_cmdf = 1; /* expecting command */ + ds_cmdp = 0; /* none pending */ + ds_eod = 1; /* set EOD flag */ + ds_fifo_reset (); /* clear fifo */ break; - case ioEDT: /* end of transfer */ + + case ioSTC: /* set control flip-flop */ + ds_control = SET; /* set control */ + break; + + + case ioEDT: /* end data 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; + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, ds); /* set standard PRL signal */ + setstdIRQ (select_code, ds); /* set standard IRQ signal */ + setSRQ (select_code, ds_srq); /* set SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + ds_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + dsio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + dsio (select_code, ioSIR, 0); /* set interrupt request */ + + +if ((signal != ioSIR) && (signal != ioENF)) /* if not IRQ update */ + ds_poll (); /* run the controller */ + +return data; } + /* Run the controller polling loop, based on ds_state: IDLE commands and ATN interrupts @@ -641,13 +700,14 @@ return dat; 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_BUSY) && ds_cmdp) /* cmd pending? */ + ds_docmd (ds_cmd); /* do it */ +if ((ds_state == DS_IDLE) && ds_control) /* idle? */ + ds_doatn (); /* check ATN */ return; } + /* Process a command - ctrl state is either IDLE or WAIT. - A drive may be processing a seek or recalibrate @@ -762,18 +822,18 @@ switch (op) { return; } + /* Check for attention */ void ds_doatn (void) { -uint32 i, dev; +uint32 i; -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 */ + dsio (ds_dib.devno, ioENF, 0); /* request interrupt */ ds_sr1 = DS1_ATN | ds_lastatn; /* set up status 1 */ ds_state = DS_WAIT; /* block atn intrs */ return; @@ -782,16 +842,16 @@ for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */ return; } + /* Controller service The argument for the function, if any, is stored in uptr->CYL */ t_stat ds_svc_c (UNIT *uptr) { -uint32 op, dev; +uint32 op; op = uptr->FNC; -dev = ds_dib.devno; switch (op) { case DSC_AREC: /* address record */ @@ -827,9 +887,12 @@ switch (op) { break; case DSC_CLEAR: /* clear */ - ds_reset_cmn (&ds_dev); /* reset ctrl */ - clrCTL (dev); /* clear CTL, SRQ */ - clrSRQ (dev); + ds_clear (); /* reset ctrl */ + + ds_control = CLEAR; /* clear CTL, SRQ */ + ds_srq = CLEAR; + dsio (ds_dib.devno, ioSIR, 0); /* set interrupt request */ + ds_cmd_done (1, DS1_OK); /* op done, set flag */ break; @@ -863,6 +926,7 @@ ds_poll (); /* run the controller */ return SCPE_OK; } + /* Timeout service */ t_stat ds_svc_t (UNIT *uptr) @@ -877,16 +941,17 @@ ds_poll (); /* run the controller */ return SCPE_OK; } + /* Unit service */ t_stat ds_svc_u (UNIT *uptr) { -uint32 op, dev, dtyp; +uint32 op, dtyp; t_stat r; op = uptr->FNC; -dev = ds_dib.devno; dtyp = GET_DTYPE (uptr->flags); + switch (op) { /* case on function */ /* Seek and recalibrate */ @@ -936,7 +1001,7 @@ switch (op) { /* case on function */ if (!DS_FIFO_EMPTY) { /* OTA ds? new state */ ds_fifo_read (); /* drain fifo */ uptr->FNC = DSC_READ; - setFLG (dev); /* handshake */ + dsio (ds_dib.devno, ioENF, 0); /* handshake */ } sim_activate (uptr, ds_ctime); /* schedule unit */ break; @@ -1046,6 +1111,7 @@ ds_poll (); return SCPE_OK; } + /* Schedule timed wait for CPU response - Set flag to get CPU attention @@ -1054,9 +1120,7 @@ return SCPE_OK; void ds_wait_for_cpu (UNIT *uptr, uint32 newst) { -uint32 dev = ds_dib.devno; - -setFLG (dev); /* set flag */ +dsio (ds_dib.devno, ioENF, 0); /* set flag */ uptr->FNC = newst; /* new state */ sim_activate (uptr, ds_ctime); /* activate unit */ sim_cancel (&ds_timer); /* activate timeout */ @@ -1064,6 +1128,7 @@ sim_activate (&ds_timer, ds_tmo); return; } + /* Set idle state - Controller is set to idle state @@ -1078,6 +1143,7 @@ sim_cancel (&ds_timer); /* no timeout */ return; } + /* Set wait state - Set flag if required @@ -1087,9 +1153,9 @@ return; void ds_cmd_done (t_bool sf, uint32 sr1) { -uint32 dev = ds_dib.devno; +if (sf) /* set host flag? */ + dsio (ds_dib.devno, ioENF, 0); /* set flag */ -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 */ @@ -1098,6 +1164,7 @@ sim_activate (&ds_timer, ds_tmo); return; } + /* Return drive status (status word 2) */ uint32 ds_updds2 (UNIT *uptr) @@ -1115,6 +1182,7 @@ if (sta & DS2_ALLERR) sta = sta | DS2_ERR; /* set error */ return sta; } + /* Schedule controller operation */ void ds_sched_ctrl_op (uint32 op, uint32 arg, uint32 busy) @@ -1128,6 +1196,7 @@ sim_activate (&ds_timer, ds_tmo); return; } + /* Request address - if pending eoc, report cylinder + 1 */ void ds_reqad (uint16 *cyl, uint16 *hs) @@ -1137,6 +1206,7 @@ void ds_reqad (uint16 *cyl, uint16 *hs) return; } + /* Start seek - schedule whether in bounds or out of bounds */ void ds_start_seek (UNIT *uptr, uint32 cyl, uint32 newst) @@ -1164,6 +1234,7 @@ sim_activate (uptr, ds_stime * (t + 1)); /* schedule */ return; } + /* Start next sector for read or write - If error, set command done, return TRUE, nothing is scheduled @@ -1211,6 +1282,7 @@ sim_activate (uptr, tm); /* activate unit */ return FALSE; } + /* Start next sector for read - Do common start for read and write @@ -1234,6 +1306,7 @@ ds_next_sec (uptr); /* increment hd, sc */ return SCPE_OK; } + /* Start next sector for write - Do common start for read and write @@ -1246,7 +1319,6 @@ return SCPE_OK; 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? */ @@ -1255,10 +1327,12 @@ if ((uptr->flags & UNIT_WPR) || /* write protected? */ } 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 */ +ds_srq = SET; /* request word */ +dsio (ds_dib.devno, ioSIR, 0); /* set interrupt request */ return; } + /* Advance to next sector (but not next cylinder) */ void ds_next_sec (UNIT *uptr) @@ -1277,6 +1351,7 @@ ds_eoc = 1; /* flag end cylinder */ return; } + /* Advance to next cylinder - If autoseek enabled, seek to cylinder +/- 1 @@ -1294,6 +1369,7 @@ else ds_cmd_done (1, DS1_EOCYL); /* no, end of cyl err */ return; } + /* Transfer word for read - If end of data, terminate command, nothing scheduled @@ -1301,21 +1377,22 @@ return; 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? */ +else if (ds_srq) { /* overrun? */ ds_cmd_done (1, DS1_OVRUN); /* set done */ return; } -else { ds_fifo_write (dsxb[ds_ptr++]); /* next word */ - setSRQ (dev); /* request service */ +else { + ds_fifo_write (dsxb[ds_ptr++]); /* next word */ + ds_srq = SET; /* request service */ + dsio (ds_dib.devno, ioSIR, 0); /* set interrupt request */ if (ds_ptr >= bsize) uptr->FNC += DSC_NEXT; /* sec done? next state */ sim_activate (uptr, ds_dtime); /* schedule */ } return; } + /* Transfer word for write - Copy word from fifo to buffer @@ -1326,9 +1403,8 @@ return; t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize) { uint32 i, dat; -uint32 dev = ds_dib.devno; -if (SRQ (dev)) { /* overrun? */ +if (ds_srq) { /* overrun? */ ds_cmd_done (1, DS1_OVRUN); /* set done */ return SCPE_OK; } @@ -1345,11 +1421,15 @@ if (ds_eod || (ds_ptr >= bsize)) { /* xfr or sector done? * } else uptr->FNC += DSC_NEXT; /* no, next state */ } -else { setSRQ (dev); } /* request next word */ +else { + ds_srq = SET; /* request next word */ + dsio (ds_dib.devno, ioSIR, 0); /* set interrupt request */ + } sim_activate (uptr, ds_dtime); /* schedule */ return SCPE_OK; } + /* End sector for read or write - If end of data, terminate command, nothing scheduled @@ -1365,6 +1445,7 @@ else sim_activate (uptr, ds_rtime); /* normal transfer */ return; } + /* Report uncorrectable data error */ t_stat ds_set_uncorr (UNIT *uptr) @@ -1377,6 +1458,7 @@ ds_poll (); /* force poll */ return SCPE_IOERR; } + /* Fifo read */ uint32 ds_fifo_read (void) @@ -1407,9 +1489,10 @@ for (i = 0; i < DS_FIFO_SIZE; i++) ds_fifo[i] = 0; return; } -/* Reset routine */ -t_stat ds_reset_cmn (DEVICE *dptr) +/* Controller clear */ + +t_stat ds_clear (void) { int32 i; @@ -1435,16 +1518,23 @@ sim_cancel (&ds_timer); return SCPE_OK; } + +/* Reset routine. + + The PON signal clears the Interface Selected flip-flop, disconnecting the + interface from the disc controller. Under simulation, the interface always + remains connected to the controller, so we take no special action on + power-up. +*/ + 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 */ +dsio (ds_dib.devno, ioPOPIO, 0); /* send POPIO signal */ +ds_srq = CLEAR; /* clear SRQ */ +return SCPE_OK; } + /* Device attach */ t_stat ds_attach (UNIT *uptr, char *cptr) @@ -1469,6 +1559,7 @@ for (i = 0; drv_tab[i].sc != 0; i++) { /* find best fit */ return SCPE_OK; } + /* Device detach */ t_stat ds_detach (UNIT *uptr) @@ -1477,6 +1568,7 @@ ds_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads if attac return detach_unit (uptr); } + /* Load and unload heads */ t_stat ds_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) @@ -1494,13 +1586,14 @@ else { /* load heads */ return SCPE_OK; } + /* Schedule attention interrupt if CTL set, not restore, and controller idle */ void ds_sched_atn (UNIT *uptr) { int32 i; -if (!ds_dib.ctl || (sim_switches & SIM_SW_REST)) return; +if (!ds_control || (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; } @@ -1509,6 +1602,7 @@ sim_activate (uptr, 1); /* do immediately */ return; } + /* Set size command validation routine */ t_stat ds_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -1518,9 +1612,10 @@ uptr->capac = drv_tab[GET_DTYPE (val)].size; return SCPE_OK; } + /* 13037 bootstrap routine (HP 12992B ROM) */ -const uint16 ds_rom[IBL_LNT] = { +const BOOT_ROM ds_rom = { 0017727, /* STRT JSB STAT ; get status */ 0002021, /* SSA,RSS ; is drive ready? */ 0027742, /* JMP DMA ; yes, set up DMA */ diff --git a/HP2100/hp2100_fp.c b/HP2100/hp2100_fp.c index 7e431ba0..10331795 100644 --- a/HP2100/hp2100_fp.c +++ b/HP2100/hp2100_fp.c @@ -34,15 +34,6 @@ 21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms - Implementation note: The 2100/1000-M/E Fast FORTRAN Processor (FFP) and 1000 - F-Series Floating Point Processor (FPP) simulations require that the host - compiler support 64-bit integers and the HAVE_INT64 symbol be defined during - compilation. If this symbol is defined, two-word floating-point operations - are handled in the FPP code, and this module is not used. If it is not - defined, then FFP and FPP operations are not available, and this module - provides the floating-point support. - - The HP2100 uses a unique binary floating point format: 15 14 0 @@ -79,9 +70,20 @@ inputs may cause the packup code to produce the wrong sign. - "Unclean" zeros (zero fraction, non-zero exponent) are processed like normal operands. + + Implementation notes: + + 1. The 2100/1000-M/E Fast FORTRAN Processor (FFP) and 1000 F-Series Floating + Point Processor (FPP) simulations require that the host compiler support + 64-bit integers and the HAVE_INT64 symbol be defined during compilation. + If this symbol is defined, two-word floating-point operations are handled + in the FPP code, and this module is not used. If it is not defined, then + FFP and FPP operations are not available, and this module provides the + floating-point support. */ #include "hp2100_defs.h" +#include "hp2100_cpu.h" #include "hp2100_cpu1.h" #include "hp2100_fp.h" @@ -122,8 +124,6 @@ struct ufp { /* unpacked fp */ #define FR_NEG(v) ((~(v) + 1) & DMASK32) -extern uint16 ABREG[2]; - uint32 UnpackFP (struct ufp *fop, uint32 opnd); void NegFP (struct ufp *fop); void NormFP (struct ufp *fop); diff --git a/HP2100/hp2100_fp1.c b/HP2100/hp2100_fp1.c index 21793fdf..0ca50848 100644 --- a/HP2100/hp2100_fp1.c +++ b/HP2100/hp2100_fp1.c @@ -23,6 +23,7 @@ in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. + 08-Jun-08 JDB Quieted bogus gcc warning in fp_exec 10-May-08 JDB Fixed uninitialized return in fp_accum when setting 19-Mar-08 JDB Reworked "complement" to avoid inlining bug in gcc-4.x 01-Dec-06 JDB Reworked into generalized multiple-precision ops for FPP @@ -1082,6 +1083,13 @@ return; operation opcode and returned to the caller. Pass NULL for both of the operands if only the result precision is wanted. Pass NULL for the result if only the operand precisions are wanted. + + Implementation note: + + 1. gcc-4.3.0 complains at -O3 that operand_l/r may not be initialized. + Because of the mask, the switch statement covers all cases, but gcc + doesn't realize this. The "default" case is redundant but eliminates the + warning. */ void fp_prec (uint16 opcode, OPSIZE *operand_l, OPSIZE *operand_r, OPSIZE *result) @@ -1109,6 +1117,7 @@ if (operand_l && operand_r) { /* want operand precisio break; case 0120: /* flt/accum as float */ + default: /* keeps compiler quiet for uninit warning */ *operand_l = int_size; /* first op is integer */ *operand_r = fp_a; /* second op is always null */ break; diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c index b36e4cdf..69eebc90 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-2007, Robert M Supnik + Copyright (c) 2002-2008, Robert 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,8 +23,12 @@ 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 12875A interprocessor link + IPLI, IPLO 12875A interprocessor link + 07-Sep-08 JDB Changed Telnet poll to connect immediately after reset or attach + 15-Jul-08 JDB Revised EDT handler to refine completion delay conditions + 09-Jul-08 JDB Revised ipl_boot to use ibl_copy + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 01-Mar-07 JDB IPLI EDT delays DMA completion interrupt for TSB Added debug printouts 28-Dec-06 JDB Added ioCRS state to I/O decoders @@ -36,6 +40,11 @@ 09-May-03 RMS Added network device flag 31-Jan-03 RMS Links are full duplex (found by Mike Gemeny) + Reference: + - 12875A Processor Interconnect Kit Operating and Service Manual + (12875-90002, Jan-1974) + + The 12875A Processor Interconnect Kit consists four 12566A Microcircuit Interface cards. Two are used in each processor. One card in each system is used to initiate transmissions to the other, and the second card is used to @@ -45,13 +54,11 @@ on the lower priority card and received on the higher priority card. Two sets of cards are used to support simultaneous transmission in both directions. - - Reference: - - 12875A Processor Interconnect Kit Operating and Service Manual - (12875-90002, Jan-1974) */ + #include "hp2100_defs.h" +#include "hp2100_cpu.h" #include "sim_sock.h" #include "sim_tmxr.h" @@ -74,19 +81,21 @@ #define DEB_CPU (1 << 1) /* CPU I/O */ #define DEB_XFER (1 << 2) /* Socket receive and transmit */ -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -extern FILE *sim_log; -extern FILE *sim_deb; +extern DIB ptr_dib; /* need PTR select code for boot */ + +typedef enum { CIN, COUT } CARD; /* ipli/iplo selector */ + int32 ipl_edtdelay = 1; /* EDT delay (msec) */ int32 ipl_ptime = 31; /* polling interval */ int32 ipl_stopioe = 0; /* stop on error */ int32 ipl_hold[2] = { 0 }; /* holding character */ +FLIP_FLOP ipl_control [2] = { CLEAR, CLEAR }; +FLIP_FLOP ipl_flag [2] = { CLEAR, CLEAR }; +FLIP_FLOP ipl_flagbuf [2] = { CLEAR, CLEAR }; + DEVICE ipli_dev, iplo_dev; -int32 ipliio (int32 inst, int32 IR, int32 dat); -int32 iploio (int32 inst, int32 IR, int32 dat); -int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat); +uint32 iplio (uint32 select_code, IOSIG signal, uint32 data); t_stat ipl_svc (UNIT *uptr); t_stat ipl_reset (DEVICE *dptr); t_stat ipl_attach (UNIT *uptr, char *cptr); @@ -112,8 +121,8 @@ DEBTAB ipl_deb[] = { */ DIB ipl_dib[] = { - { IPLI, 0, 0, 0, 0, 0, &ipliio }, - { IPLO, 0, 0, 0, 0, 0, &iploio } + { IPLI, &iplio }, + { IPLO, &iplio } }; #define ipli_dib ipl_dib[0] @@ -130,12 +139,10 @@ UNIT ipl_unit[] = { 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) }, + { FLDATA (CTL, ipl_control [CIN], 0) }, + { FLDATA (FLG, ipl_flag [CIN], 0) }, + { FLDATA (FBF, ipl_flagbuf [CIN], 0) }, + { ORDATA (HOLD, ipl_hold[CIN], 8) }, { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, { FLDATA (STOP_IOE, ipl_stopioe, 0) }, { ORDATA (DEVNO, ipli_dib.devno, 6), REG_HRO }, @@ -171,12 +178,10 @@ DEVICE ipli_dev = { 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) }, + { FLDATA (CTL, ipl_control [COUT], 0) }, + { FLDATA (FLG, ipl_flag [COUT], 0) }, + { FLDATA (FBF, ipl_flagbuf [COUT], 0) }, + { ORDATA (HOLD, ipl_hold[COUT], 8) }, { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, { ORDATA (DEVNO, iplo_dib.devno, 6), REG_HRO }, { NULL } @@ -191,28 +196,28 @@ DEVICE iplo_dev = { 0, ipl_deb, NULL, NULL }; -/* I/O instructions */ -int32 ipliio (int32 inst, int32 IR, int32 dat) -{ -return iplio (&ipli_unit, inst, IR, dat); -} +/* I/O signal handler for the IPLI and IPLO devices. -int32 iploio (int32 inst, int32 IR, int32 dat) -{ -return iplio (&iplo_unit, inst, IR, dat); -} + In the link mode, the IPLI and IPLO devices are linked via network + connections to the corresponding cards in another CPU instance. In the + diagnostic mode, we simulate the attachment of the interprocessor cable + between IPLI and IPLO in this machine. -/* I/O handler for the IPLI and IPLO devices. + Implementation notes: - Implementation note: 2000 Access has a race condition that manifests itself - by an apparently normal boot and operational system console but no PLEASE LOG - IN response to terminals connected to the multiplexer. The frequency of - occurrence is higher on multiprocessor host systems, where the SP and IOP - instances may execute concurrently. + 1. Because this routine is written to handle two devices, the flip-flops are + stored in arrays, preventing the use of the "setstd" macros for PRL, IRQ, + and SRQ signals. The logic for all three is standard, however. - The cause is this code in the SP disc loader source (2883.asm, 7900.asm, - 790X.asm, 79X3.asm, and 79XX.asm): + 2. 2000 Access has a race condition that manifests itself by an apparently + normal boot and operational system console but no PLEASE LOG IN response + to terminals connected to the multiplexer. The frequency of occurrence + is higher on multiprocessor host systems, where the SP and IOP instances + may execute concurrently. + + The cause is this code in the SP disc loader source (2883.asm, 7900.asm, + 790X.asm, 79X3.asm, and 79XX.asm): LDA SDVTR REQUEST JSB IOPMA,I DEVICE TABLE @@ -223,180 +228,231 @@ return iplio (&iplo_unit, inst, IR, dat); STC CH2,C SET CORRECT CLC CH2 FLAG DIRECTION - The STC/CLC normally would cause a second "request device table" command to - be recognized by the IOP, except that the IOP DMA setup routine "DMAXF" (in - D61.asm) has specified an end-of-block CLC that holds off the IPL interrupt, - and the completion interrupt routine "DMACP" ends with a STC,C that clears - the IPL flag. + The STC/CLC normally would cause a second "request device table" command + to be recognized by the IOP, except that the IOP DMA setup routine + "DMAXF" (in D61.asm) has specified an end-of-block CLC that holds off the + IPL interrupt, and the completion interrupt routine "DMACP" ends with a + STC,C that clears the IPL flag. - In hardware, the two CPUs are essentially interlocked by the DMA transfer, - and DMA completion interrupts occur almost simultaneously. Therefore, the - STC/CLC in the SP is guaranteed to occur before the STC,C in the IOP. Under - simulation, and especially on multiprocessor hosts, that guarantee does not - hold. If the STC/CLC occurs after the STC,C, then the IOP starts a second - device table DMA transfer, which the SP is not expecting. The IOP never - processes the subsequent "start timesharing" command, and the muxtiplexer is - non-reponsive. + In hardware, the two CPUs are essentially interlocked by the DMA + transfer, and DMA completion interrupts occur almost simultaneously. + Therefore, the STC/CLC in the SP is guaranteed to occur before the STC,C + in the IOP. Under simulation, and especially on multiprocessor hosts, + that guarantee does not hold. If the STC/CLC occurs after the STC,C, + then the IOP starts a second device table DMA transfer, which the SP is + not expecting. The IOP never processes the subsequent "start + timesharing" command, and the muxtiplexer is non-reponsive. - We employ a workaround that decreases the incidence of the problem: DMA - output completion interrupts are delayed to allow the other SIMH instance a - chance to process its own DMA completion. We do this by processing the EDT - (End Data Transfer) I/O backplane signal and "sleep"ing for a short time if - the transfer was an output transfer ("dat" contains the DMA channel number - and direction flag for EDT signals). + We employ a workaround that decreases the incidence of the problem: DMA + output completion interrupts are delayed to allow the other SIMH instance + a chance to process its own DMA completion. We do this by processing the + EDT (End Data Transfer) I/O backplane signal and "sleep"ing for a short + time if the transfer was an output transfer to the input channel, i.e., + a data response to the SP. This improves the race condition by delaying + the IOP until the SP has a chance to receive the last word, recognize its + own DMA input completion, drop out of the SFS loop, and execute the + STC/CLC. + + The condition is only improved, and not solved, because "sleep"ing the + IOP doesn't guarantee that the SP will actually execute. It's possible + that a higher-priority host process will preempt the SP, and that at the + sleep expiration, the SP still has not executed the STC/CLC. Still, in + testing, the incidence dropped dramatically, so the problem is much less + intrusive. */ -int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat) +uint32 iplio (uint32 select_code, IOSIG signal, uint32 data) { -uint32 u, dev, odev; +const CARD card = (select_code == iplo_dib.devno); /* set card selector */ +UNIT *const uptr = &(ipl_unit [card]); /* associated unit pointer */ +const char uc = (card == CIN) ? 'I' : 'O'; /* identify unit for debug */ +const DEVICE *dbdev = (card == CIN) ? &ipli_dev : &iplo_dev; /* identify device for debug */ +const char *iotype[] = { "Status", "Command" }; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ int32 sta; -char msg[2], uc; -DEVICE *dbdev; /* device ptr for debug */ -static const char *iotype[] = { "Status", "Command" }; +char msg[2]; -uc = (uptr == &ipli_unit) ? 'I' : 'O'; /* identify unit for debug */ -dbdev = (uptr == &ipli_unit) ? &ipli_dev : &iplo_dev; /* identify device for debug */ +switch (base_signal) { /* dispatch base I/O signal */ -u = (uptr - ipl_unit); /* get unit number */ -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 */ + case ioCLF: /* clear flag flip-flop */ + ipl_flag [card] = ipl_flagbuf [card] = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + ipl_flag [card] = ipl_flagbuf [card] = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setSKF (!ipl_flag [card]); break; - case ioOTX: /* output */ - uptr->OBUF = dat; + + case ioSFS: /* skip if flag is set */ + setSKF (ipl_flag [card]); + break; + + + case ioIOI: /* I/O data input */ + data = uptr->IBUF; /* get return data */ if (DEBUG_PRJ (dbdev, DEB_CPU)) - fprintf (sim_deb, ">>IPL%c OTx: %s = %06o\n", uc, iotype[u], dat); + fprintf (sim_deb, ">>IPL%c LIx: %s = %06o\n", uc, iotype [card ^ 1], data); break; - case ioLIX: /* load */ - dat = 0; - case ioMIX: /* merge */ - dat = dat | uptr->IBUF; /* get return data */ + case ioIOO: /* I/O data output */ + uptr->OBUF = data; if (DEBUG_PRJ (dbdev, DEB_CPU)) - fprintf (sim_deb, ">>IPL%c LIx: %s = %06o\n", uc, iotype[u ^ 1], dat); + fprintf (sim_deb, ">>IPL%c OTx: %s = %06o\n", uc, iotype [card], data); break; + + case ioPOPIO: /* power-on preset to I/O */ + ipl_flag [card] = ipl_flagbuf [card] = SET; /* set flag buffer and flag */ + uptr->OBUF = 0; /* clear output buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); + ipl_control [card] = CLEAR; /* clear control */ + + if (DEBUG_PRJ (dbdev, DEB_CMDS)) + fprintf (sim_deb, ">>IPL%c CRS: Control cleared\n", uc); break; - case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); - if (DEBUG_PRJ (dbdev, DEB_CMDS)) - fprintf (sim_deb, ">>IPL%c CLC: Command cleared\n", uc); - } + case ioCLC: /* clear control flip-flop */ + ipl_control [card] = CLEAR; /* clear ctl */ - else { /* STC */ - setCMD (dev); /* set ctl, cmd */ - setCTL (dev); - - if (DEBUG_PRJ (dbdev, DEB_CMDS)) - fprintf (sim_deb, ">>IPL%c STC: Command set\n", uc); - - 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 (DEBUG_PRJ (dbdev, DEB_XFER)) - fprintf (sim_deb, - ">>IPL%c STC: Socket write = %06o, status = %d\n", - uc, uptr->OBUF, sta); - - 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 */ - } + if (DEBUG_PRJ (dbdev, DEB_CMDS)) + fprintf (sim_deb, ">>IPL%c CLC: Control cleared\n", uc); break; - case ioEDT: /* End of DMA data transfer */ - if ((dat & DMA2_OI) == 0) { /* output transfer? */ + + case ioSTC: /* set control flip-flop */ + ipl_control [card] = SET; /* set ctl */ + + if (DEBUG_PRJ (dbdev, DEB_CMDS)) + fprintf (sim_deb, ">>IPL%c STC: Control set\n", uc); + + if (uptr->flags & UNIT_ATT) { /* attached? */ + if ((uptr->flags & UNIT_ESTB) == 0) /* established? */ + if (!ipl_check_conn (uptr)) { /* not established? */ + data = STOP_NOCONN << IOT_V_REASON; /* lose */ + break; + } + + msg[0] = (uptr->OBUF >> 8) & 0377; + msg[1] = uptr->OBUF & 0377; + sta = sim_write_sock (uptr->DSOCKET, msg, 2); + + if (DEBUG_PRJ (dbdev, DEB_XFER)) + fprintf (sim_deb, + ">>IPL%c STC: Socket write = %06o, status = %d\n", + uc, uptr->OBUF, sta); + + if (sta == SOCKET_ERROR) { + printf ("IPL: socket write error\n"); + data = SCPE_IOERR << IOT_V_REASON; + break; + } + + sim_os_sleep (0); + } + + else if (uptr->flags & UNIT_DIAG) { /* diagnostic mode? */ + ipl_unit [card ^ 1].IBUF = uptr->OBUF; /* output to other */ + iplio (ipl_dib [card ^ 1].devno, ioENF, 0); /* set other flag */ + } + + else + data = SCPE_UNATT << IOT_V_REASON; /* lose */ + break; + + + case ioEDT: /* end data transfer */ + if ((cpu_unit.flags & UNIT_IOP) && /* are we the IOP? */ + ((IOSIG) data == ioIOO) && (card == CIN)) { /* and doing output on input card? */ + if (DEBUG_PRJ (dbdev, DEB_CMDS)) fprintf (sim_deb, ">>IPL%c EDT: Delaying DMA completion interrupt for %d msec\n", uc, ipl_edtdelay); + sim_os_ms_sleep (ipl_edtdelay); /* delay completion */ } break; - default: - break; - } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -return dat; + case ioSIR: /* set interrupt request */ + setPRL (select_code, !(ipl_control [card] & ipl_flag [card])); + setIRQ (select_code, ipl_control [card] & ipl_flag [card] & ipl_flagbuf [card]); + setSRQ (select_code, ipl_flag [card]); + break; + + + case ioIAK: /* interrupt acknowledge */ + ipl_flagbuf [card] = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + iplio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + iplio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service - poll for input */ t_stat ipl_svc (UNIT *uptr) { -int32 u, nb, dev; +CARD card; +int32 nb; char msg[2], uc; DEVICE *dbdev; /* device ptr for debug */ -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; - } + +if ((uptr->flags & UNIT_ESTB) == 0) /* not established? */ + if (!ipl_check_conn (uptr)) /* check for conn */ + return SCPE_OK; /* cot connected */ + 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? */ + +card = (uptr == &iplo_unit); /* set card selector */ + if (uptr->flags & UNIT_HOLD) { /* holdover byte? */ - uptr->IBUF = (ipl_hold[u] << 8) | (((int32) msg[0]) & 0377); + uptr->IBUF = (ipl_hold[card] << 8) | (((int32) msg[0]) & 0377); uptr->flags = uptr->flags & ~UNIT_HOLD; } else if (nb == 1) { - ipl_hold[u] = ((int32) msg[0]) & 0377; + ipl_hold[card] = ((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 */ -setFSR (dev); -uc = (uptr == &ipli_unit) ? 'I' : 'O'; /* identify unit for debug */ -dbdev = (uptr == &ipli_unit) ? &ipli_dev : &iplo_dev; /* identify device for debug */ +iplio (ipl_dib [card].devno, ioENF, 0); /* set flag */ + +uc = (card == CIN) ? 'I' : 'O'; /* identify unit for debug */ +dbdev = (card == CIN) ? &ipli_dev : &iplo_dev; /* identify device for debug */ if (DEBUG_PRJ (dbdev, DEB_XFER)) fprintf (sim_deb, ">>IPL%c svc: Socket read = %06o, status = %d\n", @@ -405,6 +461,7 @@ if (DEBUG_PRJ (dbdev, DEB_XFER)) return SCPE_OK; } + t_bool ipl_check_conn (UNIT *uptr) { SOCKET sock; @@ -422,24 +479,42 @@ uptr->flags = uptr->flags | UNIT_ESTB; /* conn established */ return TRUE; } -/* Reset routine */ + +/* Reset routine. + + Implementation notes: + + 1. We set up the first poll for socket connections to occur "immediately" + upon execution, so that clients will be connected before execution + begins. Otherwise, a fast program may access the IPL before the poll + service routine activates. +*/ 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 */ -if (uptr->flags & UNIT_ATT) sim_activate (uptr, ipl_ptime); -else sim_cancel (uptr); /* deactivate unit */ -uptr->flags = uptr->flags & ~UNIT_HOLD; + +if (sim_switches & SWMASK ('P')) /* PON reset? */ + uptr->IBUF = uptr->OBUF = 0; /* clr buffers */ + +if (dptr == &ipli_dev) /* input channel reset? */ + iplio (ipli_dib.devno, ioPOPIO, 0); /* send POPIO signal */ +else /* output channel reset */ + iplio (iplo_dib.devno, ioPOPIO, 0); /* send POPIO signal */ + +if (uptr->flags & UNIT_ATT) /* socket attached? */ + sim_activate (uptr, POLL_FIRST); /* activate first poll "immediately" */ +else + sim_cancel (uptr); /* deactivate unit */ + +uptr->flags = uptr->flags & ~UNIT_HOLD; /* clear holding flag */ return SCPE_OK; } + /* Attach routine attach -l - listen for connection on port @@ -448,7 +523,6 @@ return SCPE_OK; t_stat ipl_attach (UNIT *uptr, char *cptr) { -extern int32 sim_switches; SOCKET newsock; uint32 i, t, ipa, ipp, oldf; char *tptr; @@ -493,7 +567,7 @@ if (tptr == NULL) { /* no memory? */ } strcpy (tptr, cptr); /* copy ipaddr:port */ uptr->filename = tptr; /* save */ -sim_activate (uptr, ipl_ptime); /* activate poll */ +sim_activate (uptr, POLL_FIRST); /* activate first poll "immediately" */ if (sim_switches & SWMASK ('W')) { /* wait? */ for (i = 0; i < 30; i++) { /* check for 30 sec */ if (t = ipl_check_conn (uptr)) break; /* established? */ @@ -562,7 +636,7 @@ return SCPE_OK; #define IPL_DEVA 076 #define PTR_DEVA 077 -static const uint32 pboot[IBL_LNT] = { +static const BOOT_ROM ipl_rom = { 0163774, /*BBL LDA ICK,I ; IPL sel code */ 0027751, /* JMP CFG ; go configure */ 0107700, /*ST CLC 0,C ; intr off */ @@ -631,21 +705,15 @@ static const uint32 pboot[IBL_LNT] = { t_stat ipl_boot (int32 unitno, DEVICE *dptr) { -int32 i, devi, devp; -extern DIB ptr_dib; -extern UNIT cpu_unit; -extern uint32 SR; -extern uint16 *M; +const int32 devi = ipli_dib.devno; +const int32 devp = ptr_dib.devno; -devi = ipli_dib.devno; /* get device no */ -devp = ptr_dib.devno; -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ +ibl_copy (ipl_rom, devi); /* copy bootstrap to memory */ 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; -M[PC + PTR_DEVA] = devp; +WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */ +WritePW (PC + IPL_PNTR, ipl_rom[IPL_PNTR] | PC); +WritePW (PC + PTR_PNTR, ipl_rom[PTR_PNTR] | PC); +WritePW (PC + IPL_DEVA, devi); +WritePW (PC + PTR_DEVA, devp); return SCPE_OK; } diff --git a/HP2100/hp2100_lps.c b/HP2100/hp2100_lps.c index 9f26a28c..5d165358 100644 --- a/HP2100/hp2100_lps.c +++ b/HP2100/hp2100_lps.c @@ -1,6 +1,6 @@ /* hp2100_lps.c: HP 2100 12653A/2767 line printer simulator - Copyright (c) 1993-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,9 +23,10 @@ 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 + LPS 12653A 2767 line printer 12566B microcircuit interface with loopback diagnostic connector + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 10-May-07 RMS Added UNIT_TEXT flag 11-Jan-07 JDB CLC cancels I/O event if DIAG (jumper W9 in "A" pos) Added ioCRS state to I/O decoders @@ -50,6 +51,12 @@ Added command flop 15-Oct-00 RMS Added variable device number support + References: + - 2767A Line Printer Operating and Service Manual (02767-90002, Oct-1973) + - 12566B, 12566B-001, 12566B-002, 12566B-003 Microcircuit Interface Kits + Operating and Service Manual (12566-90015, Apr-1976) + + This module simulates two different devices. In "diagnostic mode," it simulates a 12566B microcircuit interface card with a loopback connector and the jumpers set as required for execution of the General Purpose Register @@ -102,11 +109,6 @@ ATT LPS --> paper loaded DET LPS --> paper out - References: - - 2767A Line Printer Operating and Service Manual (02767-90002, Oct-1973) - - 12566B, 12566B-001, 12566B-002, 12566B-003 Microcircuit Interface Kits - Operating and Service Manual (12566-90015, Apr-1976) - The following implemented behaviors have been inferred from secondary sources (diagnostics, operating system drivers, etc.), due to absent or contradictory authoritative information; future correction may be needed: @@ -142,9 +144,9 @@ #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; +FLIP_FLOP lps_control = CLEAR; +FLIP_FLOP lps_flag = CLEAR; +FLIP_FLOP lps_flagbuf = CLEAR; int32 lps_ccnt = 0; /* character count */ int32 lps_lcnt = 0; /* line count */ @@ -188,7 +190,7 @@ const TIMESET lps_times[2] = { }; DEVICE lps_dev; -int32 lpsio (int32 inst, int32 IR, int32 dat); +uint32 lpsio (uint32 select_code, IOSIG signal, uint32 data); t_stat lps_svc (UNIT *uptr); t_stat lps_reset (DEVICE *dptr); t_stat lps_restart (UNIT *uptr, int32 value, char *cptr, void *desc); @@ -205,7 +207,7 @@ t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc); lps_reg LPS register list */ -DIB lps_dib = { LPS, 0, 0, 0, 0, 0, &lpsio }; +DIB lps_dib = { LPS, &lpsio }; UNIT lps_unit = { UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE+UNIT_TEXT, 0) @@ -215,11 +217,9 @@ 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) }, + { FLDATA (CTL, lps_control, 0) }, + { FLDATA (FLG, lps_flag, 0) }, + { FLDATA (FBF, lps_flagbuf, 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 }, @@ -259,120 +259,172 @@ DEVICE lps_dev = { &lps_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG }; -/* IO instructions */ -int32 lpsio (int32 inst, int32 IR, int32 dat) +/* I/O signal handler */ + +uint32 lpsio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev, sched; +const t_bool clf = (signal > ioCLF); +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 sched; -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + lps_flag = lps_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + lps_flag = lps_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (lps); break; - case ioOTX: /* output */ - if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", dat); - lps_unit.buf = dat; + + case ioSFS: /* skip if flag is set */ + setstdSKF (lps); 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? */ + + case ioIOI: /* I/O data input */ + 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 = 0; } - else lps_sta = LPS_PWROFF; + + else + lps_sta = LPS_PWROFF; } - dat = dat | lps_sta; /* diag, rtn status */ + + data = lps_sta; /* diag, rtn status */ + if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat); + fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", data); break; + + case ioIOO: /* I/O data output */ + if (DEBUG_PRS (lps_dev)) + fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", data); + + lps_unit.buf = data; + break; + + + case ioPOPIO: /* power-on preset to I/O */ + lps_flag = lps_flagbuf = SET; /* set flag and flag buffer */ + lps_unit.buf = 0; /* clear output buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - clrCTL (dev); /* clear control */ - clrCMD (dev); /* clear command */ + lps_control = CLEAR; /* clear control */ sim_cancel (&lps_unit); /* deactivate unit */ break; - case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (dev); /* clear control */ - if (lps_unit.flags & UNIT_DIAG) { /* diagnostic mode? */ - clrCMD (dev); /* clear command (jumper W9-A) */ - if (IR & I_HC) /* clear flag too? */ - sim_cancel (&lps_unit); /* prevent FLG/SRQ */ - } + + case ioCLC: /* clear control flip-flop */ + lps_control = CLEAR; + + if ((lps_unit.flags & UNIT_DIAG) && clf) /* diagnostic mode and clearing flag? */ + sim_cancel (&lps_unit); /* prevent FLG/SRQ */ + break; + + + case ioSTC: /* set control flip-flop */ + lps_control = SET; /* set control */ + + if (lps_unit.flags & UNIT_DIAG) { /* diagnostic? */ + lps_sta = lps_unit.buf; /* loop back data */ + sim_activate (&lps_unit, 2); /* schedule flag */ } - else { /* STC */ - setCTL (dev); /* set ctl */ - setCMD (dev); /* set cmd */ - if (lps_unit.flags & UNIT_DIAG) { /* diagnostic? */ - lps_sta = lps_unit.buf; /* loop back data */ - sim_activate (&lps_unit, 2); /* schedule flag */ + + 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 { /* 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 { /* 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; - } + + 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); } + + 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; + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, lps); /* set standard PRL signal */ + setstdIRQ (select_code, lps); /* set standard IRQ signal */ + setstdSRQ (select_code, lps); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + lps_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + lpsio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + lpsio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service */ t_stat lps_svc (UNIT *uptr) { -int32 dev; int32 c = uptr->buf & 0177; if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */ @@ -382,10 +434,8 @@ if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */ 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? */ - clrCMD (dev); /* clear cmd */ - setFSR (dev); /* set flag, fbf */ + lpsio (lps_dib.devno, ioENF, 0); /* set flag */ return SCPE_OK; /* done */ } if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ @@ -394,8 +444,9 @@ 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 */ + +lpsio (lps_dib.devno, ioENF, 0); /* set flag */ + if (((c < ' ') || (c > '_')) && /* non-printing char? */ (c != '\f') && (c != '\n') && (c != '\r')) { if (DEBUG_PRS (lps_dev)) @@ -427,16 +478,20 @@ if (ferror (uptr->fileref)) { return SCPE_OK; } -/* Reset routine - called from SCP, flags in DIB */ +/* Reset routine */ 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_sta = lps_unit.buf = 0; -lps_power = LPS_ON; /* power is on */ +if (sim_switches & SWMASK ('P')) { /* PON reset? */ + lps_power = LPS_ON; /* power is on */ + lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */ + } + +lpsio (lps_dib.devno, ioPOPIO, 0); /* send POPIO signal */ + +lps_sta = 0; /* clear status */ sim_cancel (&lps_unit); /* deactivate unit */ -lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */ + return SCPE_OK; } @@ -456,7 +511,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)) +if (lps_control && !sim_is_active (uptr)) sim_activate (uptr, 0); /* reschedule I/O */ return SCPE_OK; } diff --git a/HP2100/hp2100_lpt.c b/HP2100/hp2100_lpt.c index 41f43cf2..b2f67439 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,10 +23,12 @@ 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 + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + Changed CTIME register width to match documentation 22-Jan-07 RMS Added UNIT_TEXT flag - 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified) + 28-Dec-06 JDB Added ioCRS state to I/O decoders 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 @@ -37,6 +39,10 @@ 25-Apr-03 RMS Revised for extended file support 24-Oct-02 RMS Cloned from 12653A + Reference: + - 12845A Line Printer Operating and Service Manual (12845-90001, Aug-1972) + + The 2607 provides three status bits via the interface: bit 15 -- printer ready (online) @@ -62,9 +68,6 @@ SET LPT ONLINE --> print button down ATT LPT --> paper loaded DET LPT --> paper out - - Reference: - - 12845A Line Printer Operating and Service Manual (12845-90001, Aug-1972) */ #include "hp2100_defs.h" @@ -86,8 +89,9 @@ #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]; +FLIP_FLOP lpt_control = CLEAR; +FLIP_FLOP lpt_flag = CLEAR; +FLIP_FLOP lpt_flagbuf = CLEAR; int32 lpt_ctime = 4; /* char time */ int32 lpt_ptime = 10000; /* print time */ @@ -98,7 +102,7 @@ static int32 lpt_cct[8] = { }; DEVICE lpt_dev; -int32 lptio (int32 inst, int32 IR, int32 dat); +uint32 lptio (uint32 select_code, IOSIG signal, uint32 data); t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); t_stat lpt_restart (UNIT *uptr, int32 value, char *cptr, void *desc); @@ -111,7 +115,7 @@ t_stat lpt_attach (UNIT *uptr, char *cptr); lpt_reg LPT register list */ -DIB lpt_dib = { LPT, 0, 0, 0, 0, 0, &lptio }; +DIB lpt_dib = { LPT, &lptio }; UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE+UNIT_TEXT, 0) @@ -119,14 +123,12 @@ UNIT lpt_unit = { 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) }, + { FLDATA (CTL, lpt_control, 0) }, + { FLDATA (FLG, lpt_flag, 0) }, + { FLDATA (FBF, lpt_flagbuf, 0) }, { DRDATA (LCNT, lpt_lcnt, 7) }, { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lpt_ctime, 31), PV_LEFT }, + { DRDATA (CTIME, lpt_ctime, 24), PV_LEFT }, { DRDATA (PTIME, lpt_ptime, 24), PV_LEFT }, { FLDATA (STOP_IOE, lpt_stopioe, 0) }, { ORDATA (DEVNO, lpt_dib.devno, 6), REG_HRO }, @@ -151,84 +153,122 @@ DEVICE lpt_dev = { &lpt_dib, DEV_DISABLE }; -/* IO instructions */ -int32 lptio (int32 inst, int32 IR, int32 dat) +/* I/O signal handler */ + +uint32 lptio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + lpt_flag = lpt_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + lpt_flag = lpt_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (lpt); break; - case ioOTX: /* output */ - lpt_unit.buf = dat & (LPT_CTL | 0177); + + case ioSFS: /* skip if flag is set */ + setstdSKF (lpt); break; - case ioLIX: /* load */ - dat = 0; /* default sta = 0 */ - case ioMIX: /* merge */ + + case ioIOI: /* I/O data input */ if (lpt_unit.flags & UNIT_POWEROFF) /* power off? */ - dat = dat | LPT_PWROFF; + data = LPT_PWROFF; + else if (!(lpt_unit.flags & UNIT_OFFLINE)) { /* online? */ if (lpt_unit.flags & UNIT_ATT) { /* paper loaded? */ - dat = dat | LPT_RDY; + data = LPT_RDY; if (!sim_is_active (&lpt_unit)) /* printer busy? */ - dat = dat | LPT_NBSY; + data = data | LPT_NBSY; } + else if (lpt_lcnt == LPT_PAGELNT - 1) /* paper out, at BOF? */ - dat = dat | LPT_PAPO; + data = LPT_PAPO; } + + else + data = 0; break; - case ioCRS: /* control reset (action unverif) */ - 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); - } + + case ioIOO: /* I/O data output */ + lpt_unit.buf = data & (LPT_CTL | 0177); break; - default: - break; - } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -return dat; + case ioPOPIO: /* power-on preset to I/O */ + lpt_flag = lpt_flagbuf = SET; /* set flag and flag buffer */ + lpt_unit.buf = 0; /* clear output buffer */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + lpt_control = CLEAR; + break; + + + case ioSTC: /* set control flip-flop */ + lpt_control = SET; + sim_activate (&lpt_unit, /* schedule op */ + (lpt_unit.buf & LPT_CTL)? lpt_ptime: lpt_ctime); + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, lpt); /* set standard PRL signal */ + setstdIRQ (select_code, lpt); /* set standard IRQ signal */ + setstdSRQ (select_code, lpt); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + lpt_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + lptio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + lptio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service */ t_stat lpt_svc (UNIT *uptr) { -int32 i, skip, chan, dev; +int32 i, skip, chan; -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 */ + +lptio (lpt_dib.devno, ioENF, 0); /* set flag */ + if (uptr->buf & LPT_CTL) { /* control word? */ if (uptr->buf & LPT_CHAN) { chan = uptr->buf & LPT_CHANM; @@ -257,17 +297,18 @@ lpt_unit.pos = ftell (uptr->fileref); /* update pos */ return SCPE_OK; } -/* Reset routine - called from SCP, flags in DIB */ + +/* Reset routine */ 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_unit.buf = 0; +lptio (lpt_dib.devno, ioPOPIO, 0); /* send POPIO signal */ + sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } + /* Restart I/O routine If I/O is started via STC, and the printer is powered off, offline, @@ -284,11 +325,12 @@ 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)) +if (lpt_control && !sim_is_active (uptr)) sim_activate (uptr, 0); /* reschedule I/O */ return SCPE_OK; } + /* Attach routine */ t_stat lpt_attach (UNIT *uptr, char *cptr) diff --git a/HP2100/hp2100_mpx.c b/HP2100/hp2100_mpx.c new file mode 100644 index 00000000..46ecf043 --- /dev/null +++ b/HP2100/hp2100_mpx.c @@ -0,0 +1,2693 @@ +/* hp2100_mpx.c: HP 12792C eight-channel asynchronous multiplexer simulator + + Copyright (c) 2008, J. David Bryan + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of the author shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from the author. + + MPX 12792C 8-channel multiplexer card + + 25-Nov-08 JDB Revised for new multiplexer library SHOW routines + 14-Nov-08 JDB Cleaned up VC++ size mismatch warnings for zero assignments + 03-Oct-08 JDB Fixed logic for ENQ/XOFF transmit wait + 07-Sep-08 JDB Changed Telnet poll to connect immediately after reset or attach + 10-Aug-08 JDB Added REG_FIT to register variables < 32-bit size + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 26-May-08 JDB Created MPX device + + References: + - HP 12792B 8-Channel Asynchronous Multiplexer Subsystem Installation and + Reference Manual (12792-90020, Jul-1984) + - HP 12792B/C 8-Channel Asynchronous Multiplexer Subsystem User's Manual + (5955-8867, Jun-1993) + - HP 12792B/C 8-Channel Asynchronous Multiplexer Subsystem Configuration Guide + (5955-8868, Jun-1993) + - HP 1000 series 8-channel Multiplexer Firmware External Reference Specification + (October 19, 1982) + - HP 12792/12040 Multiplexer Firmware Source (24999-18312, revision C) + - Zilog Components Data Book (00-2034-04, 1985) + + + The 12792A/B/C/D was an eight-line asynchronous serial multiplexer that + connected terminals, modems, serial line printers, and "black box" devices + that used the RS-232 standard to the CPU. It used an on-board microprocessor + and provided input and output buffering to support block-mode reads from HP + 264x and 262x terminals at speeds up to 19.2K baud. The card handled + character editing, echoing, ENQ/ACK handshaking, and read terminator + detection, substantially reducing the load on the CPU over the earlier 12920 + multiplexer. It was supported by HP under RTE-MIII, RTE-IVB, and RTE-6/VM. + Under simulation, it connects with HP terminal emulators via Telnet to a + user-specified port. + + The single interface card contained a Z80 CPU, DMA controller, CTC, four + two-channel SIO UARTs, 16K of RAM, 8K of ROM, and I/O backplane latches and + control circuitry. The card executed a high-level command set, and data + transfer to and from the CPU was via the on-board DMA controller and the DCPC + in the CPU. + + The 12792 for the M/E/F series and the 12040 multiplexer for the A/L series + differed only in backplane design. Early ROMs were card-specific, but later + ones were interchangeable; the code would determine whether it was executing + on an MEF card or an AL card. + + Four major firmware revisions were made. These were labelled "A", "B", "C", + and "D". The A, B, and C revisions were interchangeable from the perspective + of the OS driver; the D was different and required an updated driver. + Specifically: + + Op. Sys. Driver Part Number Rev + -------- ------ -------------------- --- + RTE-MIII DVM00 12792-16002 Rev.2032 A + RTE-IVB DVM00 12792-16002 Rev.5000 ABC + + RTE-6/VM DVM00 12792-16002 Rev.5000 ABC + RTE-6/VM DV800 92084-15068 Rev.6000 D + + RTE-A IDM00 92077-16754 Rev.5020 ABC + RTE-A ID800 92077-16887 Rev.6200 D + + Revisions A-C have an upward-compatible command set that partitions each OS + request into several sub-commands. Each command is initiated by setting the + control flip-flop on the card, which causes a non-maskable interrupt (NMI) on + the card's Z80 processor. + + The D-revision firmware uses a completely different command set. The + commands are slightly modified versions of the original EXEC calls (read, + write, and control) and are generally passed to the card directly for action. + + This simulation supports the C revision. D-revision support may be added + later. + + Twelve programmable baud rates are supported by the multiplexer. These + "realistic" rates are simulated by scheduling I/O service based on the + appropriate number of 1000 E-Series instructions for the rate selected. + + The simulation provides both the "realistic timing" described above, as well + as an optimized "fast timing" option. Optimization makes three improvements: + + 1. Buffered characters are transferred via Telnet in blocks. + + 2. ENQ/ACK handshaking is done locally without involving the Telnet client. + + 3. BS and DEL respond visually more like prior RTE terminal drivers. + + HP did not offer a functional diagnostic for the 12792. Instead, a Z80 + program that tested the operation of the hardware was downloaded to the card, + and a "go/no-go" status was returned to indicate the hardware condition. + Because this is a functional simulation of the multiplexer and not a Z80 + emulation, the diagnostic cannot be used to test the implementation. + + Implementation notes: + + 1. The 12792 had two baud-rate generators that were assigned to lines by the + wiring configuration in the I/O cable connector hood. Two of the four + CTC counters were used to implement the BRGs for all eight lines. Only + subsets of the configurable rates were allowed for lines connected to the + same BRG, and assigning mutually incompatible rates caused corruption of + the rates on lines assigned earlier. Under simulation, any baud rate may + be assigned to any line without interaction, and assignments of lines to + BRGs is not implemented. + + 2. Revisions B and C added support for the 37214A Systems Modem subsystem + and the RTE-A Virtual Control Panel (VCP). Under simulation, the modem + commands return status codes indicating that no modems are present, and + the VCP commands are not implemented. +*/ + + +#include + +#include "hp2100_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" + + +/* Bitfield constructor. + + Given a bitfield starting bit number and width in bits, declare two + constants: one for the starting bit number, and one for the positioned field + mask. That is, given a definition such as: + + BITFIELD(SMALLFIELD,5,2) + + ...this macro produces: + + static const uint32 SMALLFIELD_V = 5; + static const uint32 SMALLFIELD = ((1 << (2)) - 1) << (5); + + The latter reduces to 3 << 5, or 0x00000060. + + Note: C requires constant expressions in initializers for objects with static + storage duration, so initializing a static object with a BITFIELD value is + illegal (a "static const" object is not a constant!). +*/ + +#define BITFIELD(NAME,STARTBIT,BITWIDTH) \ + static const uint32 NAME ## _V = STARTBIT; \ + static const uint32 NAME = ((1 << (BITWIDTH)) - 1) << (STARTBIT); + + +/* Program constants */ + +#define MPX_DATE_CODE 2416 /* date code for C firmware */ + +#define RD_BUF_SIZE 514 /* read buffer size */ +#define WR_BUF_SIZE 514 /* write buffer size */ + +#define RD_BUF_LIMIT 254 /* read buffer limit */ +#define WR_BUF_LIMIT 254 /* write buffer limit */ + +#define KEY_DEFAULT 255 /* default port key */ + + +/* Service times: + + DATA_DELAY = 1.25 us (Z80 DMA data word transfer time) + PARAM_DELAY = 25 us (STC to STF for first word of two-word command) + CMD_DELAY = 400 us (STC to STF for one or two-word command execution) +*/ + +#define DATA_DELAY 2 /* data transfer time */ +#define PARAM_DELAY 40 /* parameter request time */ +#define CMD_DELAY 630 /* command completion time */ + + +/* Unit references */ + +#define MPX_PORTS 8 /* number of visible units */ +#define MPX_CNTLS 2 /* number of control units */ + +#define mpx_cntl (mpx_unit [MPX_PORTS + 0]) /* controller unit */ +#define mpx_poll (mpx_unit [MPX_PORTS + 1]) /* Telnet polling unit */ + + +/* Character constants */ + +#define EOT '\004' +#define ENQ '\005' +#define ACK '\006' +#define BS '\010' +#define LF '\012' +#define CR '\015' +#define DC1 '\021' +#define DC2 '\022' +#define DC3 '\023' +#define ESC '\033' +#define RS '\036' +#define DEL '\177' + +#define XON DC1 +#define XOFF DC3 + + +/* Device flags */ + +#define DEV_V_REV_D (DEV_V_UF + 0) /* firmware revision D (not implemented) */ + +#define DEV_REV_D (1 << DEV_V_REV_D) + + +/* Unit flags */ + +#define UNIT_V_FASTTIME (UNIT_V_UF + 0) /* fast timing mode */ +#define UNIT_V_CAPSLOCK (UNIT_V_UF + 1) /* caps lock mode */ + +#define UNIT_FASTTIME (1 << UNIT_V_FASTTIME) +#define UNIT_CAPSLOCK (1 << UNIT_V_CAPSLOCK) + + +/* Debug flags */ + +#define DEB_CMDS (1 << 0) /* commands and status */ +#define DEB_CPU (1 << 1) /* CPU I/O */ +#define DEB_BUF (1 << 2) /* buffer gets and puts */ +#define DEB_XFER (1 << 3) /* character reads and writes */ + + +/* Multiplexer commands for revisions A/B/C. + + Commands are either one or two words in length. The one-word format is: + + +-------------------------------+-------------------------------+ + | 0 . 1 | command opcode | command parameter | + +-------------------------------+-------------------------------+ + 15 - 8 7 - 0 + + The two-word format is: + + +-------------------------------+-------------------------------+ + | 1 . 1 | command opcode | command value | + +-------------------------------+-------------------------------+ + | command parameter | + +---------------------------------------------------------------+ + 15 - 8 7 - 0 + + Commands implemented by firmware revision: + + Rev Cmd Value Operation Status Value(s) Returned + --- --- ----- ------------------------------- ------------------------------- + ABC 100 - No operation 000000 + ABC 101 - Reset to power-on defaults 100000 + ABC 102 - Enable unsolicited input None, unless UI pending + ABC 103 1 Disable unsolicited interrupts 000000 + ABC 103 2 Abort DMA transfer 000000 + ABC 104 - Acknowledge Second word of UI status + ABC 105 key Cancel first receive buffer 000000 + ABC 106 key Cancel all received buffers 000000 + ABC 107 - Fast binary read (none) + + -BC 140 chr VCP put byte 000000 + -BC 141 - VCP put buffer 000000 + -BC 142 - VCP get byte Character from port 0 + -BC 143 - VCP get buffer 000120 + -BC 144 - Exit VCP mode 000000 + -BC 157 - Enter VCP mode 000000 + + ABC 300 - No operation 000000 + ABC 301 key Request write buffer 000000 or 000376 + ABC 302 key Write data to buffer (none) + ABC 303 key Set port key 000000 or date code of firmware + ABC 304 key Set receive type 000000 + ABC 305 key Set character count 000000 + ABC 306 key Set flow control 000000 + ABC 307 key Read data from buffer (none) + ABC 310 - Download executable (none) + + -BC 311 key Connect line 000000 or 140000 if no modem + -BC 312 key Disconnect line 000000 or 140000 if no modem + -BC 315 key Get modem/port status modem status or 000200 if no modem + -BC 316 key Enable/disable modem loopback 000000 or 140000 if no modem + -BC 320 key Terminate active receive buffer 000000 +*/ + + +/* One-word command codes */ + +#define CMD_NOP 0100 /* No operation */ +#define CMD_RESET 0101 /* Reset firmware to power-on defaults */ +#define CMD_ENABLE_UI 0102 /* Enable unsolicited input */ +#define CMD_DISABLE 0103 /* Disable interrupts / Abort DMA Transfer */ +#define CMD_ACK 0104 /* Acknowledge */ +#define CMD_CANCEL 0105 /* Cancel first receive buffer */ +#define CMD_CANCEL_ALL 0106 /* Cancel all received buffers */ +#define CMD_BINARY_READ 0107 /* Fast binary read */ + +#define CMD_VCP_PUT 0140 /* VCP put byte */ +#define CMD_VCP_PUT_BUF 0141 /* VCP put buffer */ +#define CMD_VCP_GET 0142 /* VCP get byte */ +#define CMD_VCP_GET_BUF 0143 /* VCP get buffer */ +#define CMD_VCP_EXIT 0144 /* Exit VCP mode */ +#define CMD_VCP_ENTER 0157 /* Enter VCP mode */ + + +/* Two-word command codes */ + +#define CMD_REQ_WRITE 0301 /* Request write buffer */ +#define CMD_WRITE 0302 /* Write data to buffer */ +#define CMD_SET_KEY 0303 /* Set port key */ +#define CMD_SET_RCV 0304 /* Set receive type */ +#define CMD_SET_COUNT 0305 /* Set character count */ +#define CMD_SET_FLOW 0306 /* Set flow control */ +#define CMD_READ 0307 /* Read data from buffer */ +#define CMD_DL_EXEC 0310 /* Download executable */ + +#define CMD_CN_LINE 0311 /* Connect line */ +#define CMD_DC_LINE 0312 /* Disconnect line */ +#define CMD_GET_STATUS 0315 /* Get modem/port status */ +#define CMD_LOOPBACK 0316 /* Enable/disable modem loopback */ +#define CMD_TERM_BUF 0320 /* Terminate active receive buffer */ + + +/* Sub-command codes */ + +#define SUBCMD_UI 1 /* Disable unsolicited interrupts */ +#define SUBCMD_DMA 2 /* Abort DMA transfer */ + +#define CMD_TWO_WORDS 0200 /* two-word command flag */ + + +/* Unsolicited interrupt reasons */ + +#define UI_REASON_V 8 /* interrupt reason */ +#define UI_REASON (((1 << 8) - 1) << (UI_REASON_V)) /* (UI_REASON_V must be a constant!) */ + +BITFIELD (UI_PORT, 0, 3) /* interrupt port number */ + +#define UI_WRBUF_AVAIL (1 << UI_REASON_V) /* Write buffer available */ +#define UI_LINE_CONN (2 << UI_REASON_V) /* Modem line connected */ +#define UI_LINE_DISC (3 << UI_REASON_V) /* Modem line disconnected */ +#define UI_BRK_RECD (4 << UI_REASON_V) /* Break received */ +#define UI_RDBUF_AVAIL (5 << UI_REASON_V) /* Read buffer available */ + + +/* Return status to CPU */ + +#define ST_OK 0000000 /* Command OK */ +#define ST_DIAG_OK 0000015 /* Diagnostic passes */ +#define ST_VCP_SIZE 0000120 /* VCP buffer size = 80 chars */ +#define ST_NO_SYSMDM 0000200 /* No systems modem card */ +#define ST_TEST_OK 0100000 /* Self test OK */ +#define ST_NO_MODEM 0140000 /* No modem card on port */ +#define ST_BAD_KEY 0135320 /* Bad port key = 0xBAD0 */ + + +/* Bit flags */ + +#define RS_OVERFLOW 0040000 /* Receive status: buffer overflow occurred */ +#define RS_PARTIAL 0020000 /* Receive status: buffer is partial */ +#define RS_ETC_RS 0014000 /* Receive status: terminated by RS */ +#define RS_ETC_DC2 0010000 /* Receive status: terminated by DC2 */ +#define RS_ETC_CR 0004000 /* Receive status: terminated by CR */ +#define RS_ETC_EOT 0000000 /* Receive status: terminated by EOT */ +#define RS_CHAR_COUNT 0003777 /* Receive status: character count */ + +#define WR_NO_ENQACK 0020000 /* Write: no ENQ/ACK this xfer */ +#define WR_ADD_CRLF 0010000 /* Write: add CR/LF if not '_' */ +#define WR_PARTIAL 0004000 /* Write: write is partial */ +#define WR_LENGTH 0003777 /* Write: write length in bytes */ + +#define RT_END_ON_CR 0000200 /* Receive type: end xfer on CR */ +#define RT_END_ON_RS 0000100 /* Receive type: end xfer on RS */ +#define RT_END_ON_EOT 0000040 /* Receive type: end xfer on EOT */ +#define RT_END_ON_DC2 0000020 /* Receive type: end xfer on DC2 */ +#define RT_END_ON_CNT 0000010 /* Receive type: end xfer on count */ +#define RT_END_ON_CHAR 0000004 /* Receive type: end xfer on character */ +#define RT_ENAB_EDIT 0000002 /* Receive type: enable input editing */ +#define RT_ENAB_ECHO 0000001 /* Receive type: enable input echoing */ + +#define FC_FORCE_XON 0000002 /* Flow control: force XON */ +#define FC_XONXOFF 0000001 /* Flow control: enable XON/XOFF */ + +#define CL_GUARD 0000040 /* Connect line: guard tone off or on */ +#define CL_STANDARD 0000020 /* Connect line: standard 212 or V.22 */ +#define CL_BITS 0000010 /* Connect line: bits 10 or 9 */ +#define CL_MODE 0000004 /* Connect line: mode originate or answer */ +#define CL_DIAL 0000002 /* Connect line: dial manual or automatic */ +#define CL_SPEED 0000001 /* Connect line: speed low or high */ + +#define DL_AUTO_ANSWER 0000001 /* Disconnect line: auto-answer enable or disable */ + +#define LB_SPEED 0000004 /* Loopback test: speed low or high */ +#define LB_MODE 0000002 /* Loopback test: mode analog or digital */ +#define LB_TEST 0000001 /* Loopback test: test disable or enable */ + +#define GS_NO_SYSMDM 0000200 /* Get status: systems modem present or absent */ +#define GS_SYSMDM_TO 0000100 /* Get status: systems modem OK or timed out */ +#define GS_NO_MODEM 0000040 /* Get status: modem present or absent */ +#define GS_SPEED 0000020 /* Get status: speed low or high */ +#define GS_LINE 0000001 /* Get status: line disconnected or connected */ + + +/* Bit fields (name, starting bit, bit width) */ + +BITFIELD (CMD_OPCODE, 8, 8) /* Command: opcode */ +BITFIELD (CMD_KEY, 0, 8) /* Command: key */ + +BITFIELD (SK_BPC, 14, 2) /* Set key: bits per character */ +BITFIELD (SK_MODEM, 13, 1) /* Set key: hardwired or modem */ +BITFIELD (SK_BRG, 12, 1) /* Set key: baud rate generator 0/1 */ +BITFIELD (SK_STOPBITS, 10, 2) /* Set key: stop bits */ +BITFIELD (SK_PARITY, 8, 2) /* Set key: parity select */ +BITFIELD (SK_ENQACK, 7, 1) /* Set key: disable or enable ENQ/ACK */ +BITFIELD (SK_BAUDRATE, 3, 4) /* Set key: port baud rate */ +BITFIELD (SK_PORT, 0, 3) /* Set key: port number */ + +BITFIELD (FL_ALERT, 11, 1) /* Port flags: alert for terminate recv buffer */ +BITFIELD (FL_XOFF, 10, 1) /* Port flags: XOFF stopped transmission */ +BITFIELD (FL_BREAK, 9, 1) /* Port flags: UI / break detected */ +BITFIELD (FL_HAVEBUF, 8, 1) /* Port flags: UI / read buffer available */ +BITFIELD (FL_WANTBUF, 7, 1) /* Port flags: UI / write buffer available */ +BITFIELD (FL_RDOVFLOW, 6, 1) /* Port flags: read buffers overflowed */ +BITFIELD (FL_RDFILL, 5, 1) /* Port flags: read buffer is filling */ +BITFIELD (FL_RDEMPT, 4, 1) /* Port flags: read buffer is emptying */ +BITFIELD (FL_WRFILL, 3, 1) /* Port flags: write buffer is filling */ +BITFIELD (FL_WREMPT, 2, 1) /* Port flags: write buffer is emptying */ +BITFIELD (FL_WAITACK, 1, 1) /* Port flags: ENQ sent, waiting for ACK */ +BITFIELD (FL_DO_ENQACK, 0, 1) /* Port flags: do ENQ/ACK handshake */ + +#define SK_BRG_1 SK_BRG +#define SK_BRG_0 0 + +#define FL_RDFLAGS (FL_RDEMPT | FL_RDFILL | FL_RDOVFLOW) +#define FL_WRFLAGS (FL_WREMPT | FL_WRFILL) +#define FL_UI_PENDING (FL_WANTBUF | FL_HAVEBUF | FL_BREAK) + +#define ACK_LIMIT 1000 /* poll timeout for ACK response */ +#define ENQ_LIMIT 80 /* output chars before ENQ */ + + +/* Packed field values */ + +#define SK_BPC_5 (0 << SK_BPC_V) +#define SK_BPC_6 (1 << SK_BPC_V) +#define SK_BPC_7 (2 << SK_BPC_V) +#define SK_BPC_8 (3 << SK_BPC_V) + +#define SK_STOP_1 (1 << SK_STOPBITS_V) +#define SK_STOP_15 (2 << SK_STOPBITS_V) +#define SK_STOP_2 (3 << SK_STOPBITS_V) + +#define SK_BAUD_NOCHG (0 << SK_BAUDRATE_V) +#define SK_BAUD_50 (1 << SK_BAUDRATE_V) +#define SK_BAUD_75 (2 << SK_BAUDRATE_V) +#define SK_BAUD_110 (3 << SK_BAUDRATE_V) +#define SK_BAUD_1345 (4 << SK_BAUDRATE_V) +#define SK_BAUD_150 (5 << SK_BAUDRATE_V) +#define SK_BAUD_300 (6 << SK_BAUDRATE_V) +#define SK_BAUD_1200 (7 << SK_BAUDRATE_V) +#define SK_BAUD_1800 (8 << SK_BAUDRATE_V) +#define SK_BAUD_2400 (9 << SK_BAUDRATE_V) +#define SK_BAUD_4800 (10 << SK_BAUDRATE_V) +#define SK_BAUD_9600 (11 << SK_BAUDRATE_V) +#define SK_BAUD_19200 (12 << SK_BAUDRATE_V) + + +/* Default values */ + +#define SK_PWRUP_0 (SK_BPC_8 | SK_BRG_0 | SK_STOP_1 | SK_BAUD_9600) +#define SK_PWRUP_1 (SK_BPC_8 | SK_BRG_1 | SK_STOP_1 | SK_BAUD_9600) + +#define RT_PWRUP (RT_END_ON_CR | RT_END_ON_CHAR | RT_ENAB_EDIT | RT_ENAB_ECHO) + + +/* Command helpers */ + +#define GET_OPCODE(w) (((w) & CMD_OPCODE) >> CMD_OPCODE_V) +#define GET_KEY(w) (((w) & CMD_KEY) >> CMD_KEY_V) +#define GET_BPC(w) (((w) & SK_BPC) >> SK_BPC_V) +#define GET_BAUDRATE(w) (((w) & SK_BAUDRATE) >> SK_BAUDRATE_V) +#define GET_PORT(w) (((w) & SK_PORT) >> SK_PORT_V) +#define GET_UIREASON(w) (((w) & UI_REASON) >> UI_REASON_V) +#define GET_UIPORT(w) (((w) & UI_PORT) >> UI_PORT_V) + + +/* Multiplexer controller state variables */ + +typedef enum { idle, cmd, param, exec } STATE; + +STATE mpx_state = idle; /* controller state */ + +uint16 mpx_ibuf = 0; /* status/data in */ +uint16 mpx_obuf = 0; /* command/data out */ + +uint32 mpx_cmd = 0; /* current command */ +uint32 mpx_param = 0; /* current parameter */ +uint32 mpx_port = 0; /* current port number for R/W */ +uint32 mpx_portkey = 0; /* current port's key */ + int32 mpx_iolen = 0; /* length of current I/O xfer */ + +t_bool mpx_uien = FALSE; /* unsolicited interrupts enabled */ +uint32 mpx_uicode = 0; /* unsolicited interrupt reason and port */ + +FLIP_FLOP mpx_control = CLEAR; /* control flip-flop */ +FLIP_FLOP mpx_flag = CLEAR; /* flag flip-flop */ +FLIP_FLOP mpx_flagbuf = CLEAR; /* flag buffer flip-flop */ + + +/* Multiplexer per-line state variables */ + +uint8 mpx_key [MPX_PORTS]; /* port keys */ +uint16 mpx_config [MPX_PORTS]; /* port configuration */ +uint16 mpx_rcvtype [MPX_PORTS]; /* receive type */ +uint16 mpx_charcnt [MPX_PORTS]; /* character count */ +uint16 mpx_flowcntl [MPX_PORTS]; /* flow control */ +uint8 mpx_enq_cntr [MPX_PORTS]; /* ENQ character counter */ +uint16 mpx_ack_wait [MPX_PORTS]; /* ACK wait timer */ +uint16 mpx_flags [MPX_PORTS]; /* line state flags */ + +/* Multiplexer buffer selectors */ + +typedef enum { ioread, iowrite } IO_OPER; /* I/O operation */ +typedef enum { get, put } BUF_SELECT; /* buffer selector */ + +static const char *const io_op [] = { "read", /* operation names */ + "write" }; + +static const uint32 buf_size [] = { RD_BUF_SIZE, /* buffer sizes */ + WR_BUF_SIZE }; + +static uint32 emptying_flags [2]; /* buffer emptying flags [IO_OPER] */ +static uint32 filling_flags [2]; /* buffer filling flags [IO_OPER] */ + + +/* Multiplexer per-line buffer variables */ + +typedef uint16 BUF_INDEX [MPX_PORTS] [2]; /* buffer index (read and write) */ + +BUF_INDEX mpx_put; /* read/write buffer add index */ +BUF_INDEX mpx_sep; /* read/write buffer separator index */ +BUF_INDEX mpx_get; /* read/write buffer remove index */ + +uint8 mpx_rbuf [MPX_PORTS] [RD_BUF_SIZE]; /* read buffer */ +uint8 mpx_wbuf [MPX_PORTS] [WR_BUF_SIZE]; /* write buffer */ + + +/* Multiplexer local routines */ + +static t_bool exec_command (void); +static void poll_connection (void); +static void controller_reset (void); +static uint32 service_time (uint16 control_word); +static int32 key_to_port (uint32 key); + +static void buf_init (IO_OPER rw, uint32 port); +static uint8 buf_get (IO_OPER rw, uint32 port); +static void buf_put (IO_OPER rw, uint32 port, uint8 ch); +static void buf_remove (IO_OPER rw, uint32 port); +static void buf_term (IO_OPER rw, uint32 port, uint8 header); +static void buf_free (IO_OPER rw, uint32 port); +static void buf_cancel (IO_OPER rw, uint32 port, BUF_SELECT which); +static uint32 buf_len (IO_OPER rw, uint32 port, BUF_SELECT which); +static uint32 buf_avail (IO_OPER rw, uint32 port); + + +/* Multiplexer global routines */ + +uint32 mpx_io (uint32 select_code, IOSIG signal, uint32 data); + +t_stat mpx_line_svc (UNIT *uptr); +t_stat mpx_cntl_svc (UNIT *uptr); +t_stat mpx_poll_svc (UNIT *uptr); +t_stat mpx_reset (DEVICE *dptr); +t_stat mpx_attach (UNIT *uptr, char *cptr); +t_stat mpx_detach (UNIT *uptr); +t_stat mpx_status (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat mpx_set_frev (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat mpx_show_frev (FILE *st, UNIT *uptr, int32 val, void *desc); + + +/* MPX data structures. + + mpx_order MPX line connection order table + mpx_ldsc MPX line descriptors + mpx_desc MPX multiplexer descriptor + mpx_dib MPX device information block + mpx_unit MPX unit list + mpx_reg MPX register list + mpx_mod MPX modifier list + mpx_deb MPX debug list + mpx_dev MPX device descriptor + + The first eight units correspond to the eight multiplexer line ports. These + handle character I/O via the Telnet library. A ninth unit acts as the card + controller, executing commands and transferring data to and from the I/O + buffers. A tenth unit is responsible for polling for connections and socket + I/O. It also holds the master socket. + + The character I/O service routines run only when there are characters to read + or write. They operate at the approximate baud rates of the terminals (in + CPU instructions per second) in order to be compatible with the OS drivers. + The controller service routine runs only when a command is executing or a + data transfer to or from the CPU is in progress. The Telnet poll must run + continuously, but it may operate much more slowly, as the only requirement is + that it must not present a perceptible lag to human input. To be compatible + with CPU idling, it is co-scheduled with the master poll timer, which uses a + ten millisecond period. + + The controller and poll units are hidden by disabling them, so as to present + a logical picture of the multiplexer to the user. However, we cannot attach + to a disabled unit, so the poll unit is enabled prior to attaching and + disabled thereafter. +*/ + +int32 mpx_order [MPX_PORTS] = { -1 }; /* connection order */ +TMLN mpx_ldsc [MPX_PORTS] = { { 0 } }; /* line descriptors */ +TMXR mpx_desc = { MPX_PORTS, 0, 0, mpx_ldsc, mpx_order }; /* device descriptor */ + +DIB mpx_dib = { MPX, &mpx_io }; + +DEVICE mpx_dev; + +UNIT mpx_unit [] = { + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 0 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 1 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 2 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 3 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 4 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 5 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 6 */ + { UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 7 */ + { UDATA (&mpx_cntl_svc, UNIT_DIS, 0) }, /* controller unit */ + { UDATA (&mpx_poll_svc, UNIT_ATTABLE | UNIT_DIS, POLL_FIRST) } /* Telnet poll unit */ + }; + +REG mpx_reg [] = { + { DRDATA (STATE, mpx_state, 3) }, + { ORDATA (IBUF, mpx_ibuf, 16), REG_FIT }, + { ORDATA (OBUF, mpx_obuf, 16), REG_FIT }, + + { ORDATA (CMD, mpx_cmd, 8) }, + { ORDATA (PARAM, mpx_param, 16) }, + + { DRDATA (PORT, mpx_port, 8), PV_LEFT }, + { DRDATA (PORTKEY, mpx_portkey, 8), PV_LEFT }, + { DRDATA (IOLEN, mpx_iolen, 16), PV_LEFT }, + + { FLDATA (UIEN, mpx_uien, 0) }, + { GRDATA (UIPORT, mpx_uicode, 10, 3, 0) }, + { GRDATA (UICODE, mpx_uicode, 10, 3, UI_REASON_V) }, + + { BRDATA (KEYS, mpx_key, 10, 8, MPX_PORTS) }, + { BRDATA (PCONFIG, mpx_config, 8, 16, MPX_PORTS) }, + { BRDATA (RCVTYPE, mpx_rcvtype, 8, 16, MPX_PORTS) }, + { BRDATA (CHARCNT, mpx_charcnt, 8, 16, MPX_PORTS) }, + { BRDATA (FLOWCNTL, mpx_flowcntl, 8, 16, MPX_PORTS) }, + + { BRDATA (ENQCNTR, mpx_enq_cntr, 10, 7, MPX_PORTS) }, + { BRDATA (ACKWAIT, mpx_ack_wait, 10, 10, MPX_PORTS) }, + { BRDATA (PFLAGS, mpx_flags, 2, 12, MPX_PORTS) }, + + { BRDATA (RBUF, mpx_rbuf, 8, 8, MPX_PORTS * RD_BUF_SIZE) }, + { BRDATA (WBUF, mpx_wbuf, 8, 8, MPX_PORTS * WR_BUF_SIZE) }, + + { BRDATA (GET, mpx_get, 10, 10, MPX_PORTS * 2) }, + { BRDATA (SEP, mpx_sep, 10, 10, MPX_PORTS * 2) }, + { BRDATA (PUT, mpx_put, 10, 10, MPX_PORTS * 2) }, + + { FLDATA (CTL, mpx_control, 0) }, + { FLDATA (FLG, mpx_flag, 0) }, + { FLDATA (FBF, mpx_flagbuf, 0) }, + { ORDATA (DEVNO, mpx_dib.devno, 6), REG_HRO }, + + { BRDATA (CONNORD, mpx_order, 10, 32, MPX_PORTS), REG_HRO }, + { NULL } + }; + +MTAB mpx_mod [] = { + { UNIT_FASTTIME, UNIT_FASTTIME, "fast timing", "FASTTIME", NULL, NULL, NULL }, + { UNIT_FASTTIME, 0, "realistic timing", "REALTIME", NULL, NULL, NULL }, + + { UNIT_CAPSLOCK, UNIT_CAPSLOCK, "CAPS LOCK down", "CAPSLOCK", NULL, NULL, NULL }, + { UNIT_CAPSLOCK, 0, "CAPS LOCK up", "NOCAPSLOCK", NULL, NULL, NULL }, + + { MTAB_XTD | MTAB_VDV, 0, "REV", NULL, &mpx_set_frev, &mpx_show_frev, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "LINEORDER", "LINEORDER", &tmxr_set_lnorder, &tmxr_show_lnorder, &mpx_desc }, + + { MTAB_XTD | MTAB_VUN | MTAB_NC, 0, "LOG", "LOG", &tmxr_set_log, &tmxr_show_log, &mpx_desc }, + { MTAB_XTD | MTAB_VUN | MTAB_NC, 0, NULL, "NOLOG", &tmxr_set_nolog, NULL, &mpx_desc }, + + { MTAB_XTD | MTAB_VDV, 0, "", NULL, NULL, &mpx_status, &mpx_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, NULL, &tmxr_show_cstat, &mpx_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &mpx_desc }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &mpx_desc }, + { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &mpx_dev }, + + { 0 } + }; + +DEBTAB mpx_deb [] = { + { "CMDS", DEB_CMDS }, + { "CPU", DEB_CPU }, + { "BUF", DEB_BUF }, + { "XFER", DEB_XFER }, + { NULL, 0 } + }; + +DEVICE mpx_dev = { + "MPX", /* device name */ + mpx_unit, /* unit array */ + mpx_reg, /* register array */ + mpx_mod, /* modifier array */ + MPX_PORTS + MPX_CNTLS, /* number of units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 8, /* data width */ + &tmxr_ex, /* examine routine */ + &tmxr_dep, /* deposit routine */ + &mpx_reset, /* reset routine */ + NULL, /* boot routine */ + &mpx_attach, /* attach routine */ + &mpx_detach, /* detach routine */ + &mpx_dib, /* device information block */ + DEV_NET | DEV_DEBUG | DEV_DISABLE, /* device flags */ + 0, /* debug control flags */ + mpx_deb, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ + + + +/* I/O signal handler. + + Commands are sent to the card via an OTA/B. Issuing an STC SC,C causes the + mux to accept the word (STC causes a NMI on the card). If the command uses + one word, command execution will commence, and the flag will set on + completion. If the command uses two words, the flag will be set, indicating + that the second word should be output via an OTA/B. Command execution will + commence upon receipt, and the flag will set on completion. + + When the flag sets for command completion, status or data may be read from + the card via an LIA/B. If additional status or data words are expected, the + flag will set when they are available. + + A command consists of an opcode in the high byte, and a port key or command + parameter in the low byte. Undefined commands are treated as NOPs. + + The card firmware executes commands as part of a twelve-event round-robin + scheduling poll. The card NMI service routine simply sets a flag that is + interrogated during polling. The poll sequence is advanced after each + command. This implies that successive commands incur a delay of at least one + poll-loop's execution time. On an otherwise quiescent card, this delay is + approximately 460 Z80 instructions, or about 950 usec. The average command + initiation time is half of that, or roughly 425 usec. + + If a detected command requires a second word, the card sits in a tight loop, + waiting for the OTx that indicates that the parameter is available. Command + initiation from parameter receipt is about 25 usec. + + For reads and writes to card buffers, the on-board DMA controller is used. + The CPU uses DCPC to handle the transfer, but the data transfer time is + limited by the Z80 DMA, which can process a word in about 1.25 usec. + + For most cards, the hardware POPIO signal sets the flag buffer and flag + flip-flops, while CRS clears the control flip-flop. For this card, the + control and flags are cleared together by CRS, and POPIO is not used. + + Implementation notes: + + 1. "Enable unsolicited input" is the only command that does not set the + device flag upon completion. Therefore, the CPU has no way of knowing + when the command has completed. Because the command in the input latch + is recorded in the NMI handler, but actual execution only begins when the + scheduler polls for the command indication, it is possible for another + command to be sent to the card before the "Enable unsolicited input" + command is recognized. In this case, the second command overwrites the + first and is executed by the scheduler poll. Under simulation, this + condition occurs when the OTx and STC processors are entered with + mpx_state = cmd. + + 2. The "Fast binary read" command inhibits all other commands until the card + is reset. + + 3. The card does not respond to POPIO. However, as PRESET asserts POPIO and + CRS together, we fall into the latter from the former. +*/ + +uint32 mpx_io (uint32 select_code, IOSIG signal, uint32 data) +{ +static const char *output_state [] = { "Command", "Command override", "Parameter", "Data" }; +static const char *input_state [] = { "Status", "Invalid status", "Parameter", "Data" }; +const char *hold_or_clear = (signal > ioCLF ? ",C" : ""); +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 delay; + +switch (base_signal) { /* dispatch base I/O signal */ + + case ioCLF: /* clear flag flip-flop */ + mpx_flag = mpx_flagbuf = CLEAR; /* clear flag and flag buffer */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fputs (">>MPX cmds: [CLF] Flag cleared\n", sim_deb); + break; + + + case ioSTF: /* set flag flip-flop */ + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fputs (">>MPX cmds: [STF] Flag set\n", sim_deb); + /* fall into ENF */ + + case ioENF: /* enable flag */ + mpx_flag = mpx_flagbuf = SET; /* set flag and flag buffer */ + break; + + + case ioSFC: /* skip if flag is clear */ + setstdSKF (mpx); + break; + + + case ioSFS: /* skip if flag is set */ + setstdSKF (mpx); + break; + + + case ioIOI: /* I/O data input */ + data = mpx_ibuf; /* return info */ + + if (DEBUG_PRI (mpx_dev, DEB_CPU)) + fprintf (sim_deb, ">>MPX cpu: [LIx%s] %s = %06o\n", + hold_or_clear, input_state [mpx_state], data); + + if (mpx_state == exec) /* if this is input data word */ + sim_activate (&mpx_cntl, DATA_DELAY); /* continue transmission */ + break; + + + case ioIOO: /* I/O data output */ + if (DEBUG_PRI (mpx_dev, DEB_CPU)) + fprintf (sim_deb, ">>MPX cpu: [OTx%s] %s = %06o\n", + hold_or_clear, output_state [mpx_state], data); + + mpx_obuf = data; /* save word */ + + if (mpx_state == param) { /* if this is parameter word */ + sim_activate (&mpx_cntl, CMD_DELAY); /* do command now */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: [OTx%s] Command %03o parameter %06o scheduled, " + "time = %d\n", hold_or_clear, mpx_cmd, mpx_obuf, CMD_DELAY); + } + + else if (mpx_state == exec) /* else if this is output data word */ + sim_activate (&mpx_cntl, DATA_DELAY); /* then do transmission */ + break; + + + case ioPOPIO: /* power-on preset to I/O */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + controller_reset (); /* reset firmware to power-on defaults */ + mpx_obuf = 0; /* clear output buffer */ + + mpx_control = CLEAR; /* clear control */ + mpx_flagbuf = CLEAR; /* clear flag buffer */ + mpx_flag = CLEAR; /* clear flag */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fputs (">>MPX cmds: [CRS] Controller reset\n", sim_deb); + break; + + + case ioCLC: /* clear control flip-flop */ + mpx_control = CLEAR; /* clear control */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: [CLC%s] Control cleared\n", hold_or_clear); + break; + + + case ioSTC: /* set control flip-flop */ + mpx_control = SET; /* set control */ + + if (mpx_cmd == CMD_BINARY_READ) /* executing fast binary read? */ + break; /* further command execution inhibited */ + + mpx_cmd = GET_OPCODE (mpx_obuf); /* get command opcode */ + mpx_portkey = GET_KEY (mpx_obuf); /* get port key */ + + if (mpx_state == cmd) /* already scheduled? */ + sim_cancel (&mpx_cntl); /* cancel to get full delay */ + + mpx_state = cmd; /* set command state */ + + if (mpx_cmd & CMD_TWO_WORDS) /* two-word command? */ + delay = PARAM_DELAY; /* specify parameter wait */ + else /* one-word command */ + delay = CMD_DELAY; /* specify command wait */ + + sim_activate (&mpx_cntl, delay); /* schedule command */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: [STC%s] Command %03o key %d scheduled, " + "time = %d\n", hold_or_clear, mpx_cmd, mpx_portkey, delay); + break; + + + case ioEDT: /* end data transfer */ + if (DEBUG_PRI (mpx_dev, DEB_CPU)) + fputs (">>MPX cpu: [EDT] DCPC transfer ended\n", sim_deb); + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, mpx); /* set standard PRL signal */ + setstdIRQ (select_code, mpx); /* set standard IRQ signal */ + setstdSRQ (select_code, mpx); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + mpx_flagbuf = CLEAR; /* clear flag buffer */ + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + mpx_io (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + mpx_io (select_code, ioSIR, 0); /* set interrupt request */ + +return data; +} + + +/* Command executor. + + We are called by the controller service routine to process one- and two-word + commands. For two-word commands, the parameter word is present in mpx_param. + The return value indicates whether the card flag should be set upon + completion. + + Most commands execute and complete directly. The read and write commands, + however, transition to the execution state to simulate the DMA transfer, and + the "Download executable" command does the same to receive the download from + the CPU. + + Several commands were added for the B firmware revision, and the various + revisions of the RTE drivers sent some commands that were never implemented + in the mux firmware. The command protocol treated unknown commands as NOPs, + meaning that the command (and parameter, if it was a two-word command) was + absorbed and the card flag was set as though the command completed normally. + This allowed interoperability between firmware and driver revisions. + + Commands that refer to ports do so indirectly by passing a port key, rather + than a port number. The key-to-port translation is established by the "Set + port key" command. If a key is not found in the table, the command is not + executed, and the status return is ST_BAD_KEY, which in hex is "BAD0". + + Implementation notes: + + 1. The "Reset to power-on defaults" command causes the firmware to disable + interrupts and jump to the power-on initialization routine, exactly as + though the Z80 had received a hardware reset. + + 2. The "Abort DMA transfer" command works because STC causes NMI, so the + command is executed even in the middle of a DMA transfer. The OTx of the + command will be sent to the buffer if a "Write data to buffer" command is + in progress, but the STC will cause this routine to be called, which will + cancel the buffer and return the controller to the idle state. Note that + this command might be sent with no transfer in progress, in which case + nothing is done. + + 3. In response to an "Enable unsolicited interrupts" command, the controller + service is scheduled to check for a pending UI. If one is found, the + first UI status word is placed in the input buffer, and an interrupt is + generated by setting the flag. This causes entry to the driver, which + issues an "Acknowledge" command to obtain the second status word. + + It is possible, however, for the interrupt to be ignored. For example, + the driver may be waiting for a "write buffer available" UI when it is + called to begin a write to a different port. If the flag is set by + the UI after RTE has been entered, the interrupt will be held off, and + the STC sc,C instruction that begins the command sequence will clear the + flag, removing the interrupt entirely. In this case, the controller will + reissue the UI when the next "Enable unsolicited interrupts" command is + sent. + + Note that the firmware reissues the same UI, rather than recomputing UIs + and potentially selecting a different one of higher priority. + + 4. The "Fast binary read" command apparently was intended to facilitate + booting from a 264x tape drive, although no boot loader ROM for the + multiplexer was ever released. It sends the fast binary read escape + sequence (ESC e) to the terminal and then packs each pair of characters + received into a word and sends it to the CPU, accompanied by the device + flag. + + The multiplexer firmware disables interrupts and then manipulates the SIO + for port 0 directly. Significantly, it does no interpretation of the + incoming data and sits in an endless I/O loop, so the only way to exit + the command is to reset the card with a CRS (front panel PRESET or CLC 0 + instruction execution). Sending a command will not work; although the + NMI will interrupt the fast binary read, the NMI handler simply sets a + flag that is tested by the scheduler poll. Because the processor is in + an endless loop, control never returns to the scheduler, so the command + is never seen. + + 5. The "Terminate active receive buffer" behavior is a bit tricky. If the + read buffer has characters, the buffer is terminated as though a + "terminate on count" condition occurred. If the buffer is empty, + however, a "terminate on count = 1" condition is established. When a + character is received, the buffer is terminated, and the buffer + termination count is reset to 254. +*/ + +static t_bool exec_command (void) +{ +int32 port; +uint32 svc_time; +t_bool set_flag = TRUE; /* flag is normally set on completion */ +STATE next_state = idle; /* command normally executes to completion */ + +mpx_ibuf = ST_OK; /* return status is normally OK */ + +switch (mpx_cmd) { + + case CMD_NOP: /* no operation */ + break; /* just ignore */ + + + case CMD_RESET: /* reset firmware */ + controller_reset (); /* reset program variables */ + mpx_ibuf = ST_TEST_OK; /* return self-test OK code */ + break; + + + case CMD_ENABLE_UI: + mpx_uien = TRUE; /* enable unsolicited interrupts */ + sim_activate (&mpx_cntl, CMD_DELAY); /* and schedule controller for UI check */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Controller status check scheduled, " + "time = %d\n", CMD_DELAY); + + set_flag = FALSE; /* do not set the flag at completion */ + break; + + + case CMD_DISABLE: + switch (mpx_portkey) { + case SUBCMD_UI: + mpx_uien = FALSE; /* disable unsolicited interrupts */ + break; + + case SUBCMD_DMA: + if (mpx_flags [mpx_port] & FL_WRFILL) /* write buffer xfer in progress? */ + buf_cancel (iowrite, mpx_port, put); /* cancel it */ + else if (mpx_flags [mpx_port] & FL_RDEMPT) /* read buffer xfer in progress? */ + buf_cancel (ioread, mpx_port, get); /* cancel it */ + break; + } + break; + + + case CMD_ACK: /* acknowledge unsolicited interrupt */ + switch (mpx_uicode & UI_REASON) { + + case UI_WRBUF_AVAIL: /* write buffer notification */ + mpx_flags [mpx_port] &= ~FL_WANTBUF; /* clear flag */ + mpx_ibuf = WR_BUF_LIMIT; /* report write buffer available */ + break; + + case UI_RDBUF_AVAIL: /* read buffer notification */ + mpx_flags [mpx_port] &= ~FL_HAVEBUF; /* clear flag */ + + mpx_ibuf = buf_get (ioread, mpx_port) << 8 | /* get header value and position */ + buf_len (ioread, mpx_port, get); /* and include buffer length */ + + if (mpx_flags [mpx_port] & FL_RDOVFLOW) { /* did a buffer overflow? */ + mpx_ibuf = mpx_ibuf | RS_OVERFLOW; /* report it */ + mpx_flags [mpx_port] &= ~FL_RDOVFLOW; /* clear overflow flag */ + } + break; + + case UI_BRK_RECD: /* break received */ + mpx_flags [mpx_port] &= ~FL_BREAK; /* clear flag */ + mpx_ibuf = 0; /* 2nd word is zero */ + break; + } + + mpx_uicode = 0; /* clear notification code */ + break; + + + case CMD_CANCEL: /* cancel first read buffer */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + buf_cancel (ioread, port, get); /* cancel get buffer */ + + if ((buf_avail (ioread, port) == 1) && /* one buffer remaining? */ + !(mpx_flags [port] & FL_RDFILL)) /* and not filling it? */ + mpx_flags [port] |= FL_HAVEBUF; /* indicate buffer availability */ + break; + + + case CMD_CANCEL_ALL: /* cancel all read buffers */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + buf_init (ioread, port); /* reinitialize read buffers */ + break; + + + case CMD_BINARY_READ: /* fast binary read */ + for (port = 0; port < MPX_PORTS; port++) + sim_cancel (&mpx_unit [port]); /* cancel I/O on all lines */ + + mpx_flags [0] = 0; /* clear port 0 state flags */ + mpx_enq_cntr [0] = 0; /* clear port 0 ENQ counter */ + mpx_ack_wait [0] = 0; /* clear port 0 ACK wait timer */ + + tmxr_putc_ln (&mpx_ldsc [0], ESC); /* send fast binary read */ + tmxr_putc_ln (&mpx_ldsc [0], 'e'); /* escape sequence to port 0 */ + tmxr_poll_tx (&mpx_desc); /* flush output */ + + next_state = exec; /* set execution state */ + break; + + + case CMD_REQ_WRITE: /* request write buffer */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + if (buf_avail (iowrite, port) > 0) /* is a buffer available? */ + mpx_ibuf = WR_BUF_LIMIT; /* report write buffer limit */ + + else { + mpx_ibuf = 0; /* report none available */ + mpx_flags [port] |= FL_WANTBUF; /* set buffer request */ + } + break; + + + case CMD_WRITE: /* write to buffer */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) { /* port defined? */ + mpx_port = port; /* save port number */ + mpx_iolen = mpx_param & WR_LENGTH; /* save request length */ + next_state = exec; /* set execution state */ + } + break; + + + case CMD_SET_KEY: /* set port key and configuration */ + port = GET_PORT (mpx_param); /* get target port number */ + mpx_key [port] = (uint8) mpx_portkey; /* set port key */ + mpx_config [port] = mpx_param; /* set port configuration word */ + + svc_time = service_time (mpx_param); /* get service time for baud rate */ + + if (svc_time) /* want to change? */ + mpx_unit [port].wait = svc_time; /* set service time */ + + mpx_ibuf = MPX_DATE_CODE; /* return firmware date code */ + break; + + + case CMD_SET_RCV: /* set receive type */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + mpx_rcvtype [port] = mpx_param; /* save port receive type */ + break; + + + case CMD_SET_COUNT: /* set character count */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + mpx_charcnt [port] = mpx_param; /* save port character count */ + break; + + + case CMD_SET_FLOW: /* set flow control */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + mpx_flowcntl [port] = mpx_param & FC_XONXOFF; /* save port flow control */ + + if (mpx_param & FC_FORCE_XON) /* force XON? */ + mpx_flags [port] &= ~FL_XOFF; /* resume transmission if suspended */ + break; + + + case CMD_READ: /* read from buffer */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) { /* port defined? */ + mpx_port = port; /* save port number */ + mpx_iolen = mpx_param; /* save request length */ + + sim_activate (&mpx_cntl, DATA_DELAY); /* schedule the transfer */ + next_state = exec; /* set execution state */ + set_flag = FALSE; /* no flag until word ready */ + } + break; + + + case CMD_DL_EXEC: /* Download executable */ + mpx_iolen = mpx_param; /* save request length */ + next_state = exec; /* set execution state */ + break; + + + case CMD_CN_LINE: /* connect modem line */ + case CMD_DC_LINE: /* disconnect modem line */ + case CMD_LOOPBACK: /* enable/disable modem loopback */ + mpx_ibuf = ST_NO_MODEM; /* report "no modem installed" */ + break; + + + case CMD_GET_STATUS: /* get modem status */ + mpx_ibuf = ST_NO_SYSMDM; /* report "no systems modem card" */ + break; + + + case CMD_TERM_BUF: /* terminate active receive buffer */ + port = key_to_port (mpx_portkey); /* get port */ + + if (port >= 0) /* port defined? */ + if (buf_len (ioread, port, put) > 0) { /* any chars in buffer? */ + buf_term (ioread, port, 0); /* terminate buffer and set header */ + + if (buf_avail (ioread, port) == 1) /* first read buffer? */ + mpx_flags [port] |= FL_HAVEBUF; /* indicate availability */ + } + + else { /* buffer is empty */ + mpx_charcnt [port] = 1; /* set to terminate on one char */ + mpx_flags [port] |= FL_ALERT; /* set alert flag */ + } + break; + + + case CMD_VCP_PUT: /* VCP put byte */ + case CMD_VCP_PUT_BUF: /* VCP put buffer */ + case CMD_VCP_GET: /* VCP get byte */ + case CMD_VCP_GET_BUF: /* VCP get buffer */ + case CMD_VCP_EXIT: /* Exit VCP mode */ + case CMD_VCP_ENTER: /* Enter VCP mode */ + + default: /* unknown command */ + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Unknown command %03o ignored\n", mpx_cmd); + } + +mpx_state = next_state; +return set_flag; +} + + +/* Multiplexer controller service. + + The controller service handles commands and data transfers to and from the + CPU. The delay in scheduling the controller service represents the firmware + command or data execution time. The controller may be in one of four states + upon entry: idle, first word of command received (cmd), command parameter + received (param), or data transfer (exec). + + Entry in the command state causes execution of one-word commands and + solicitation of command parameters for two-word commands, which are executed + when entering in the parameter state. + + Entry in the data transfer state moves one word between the CPU and a read or + write buffer. For writes, the write buffer is filled with words from the + CPU. Once the indicated number of words have been transferred, the + appropriate line service is scheduled to send the characters. For reads, + characters are unloaded from the read buffer to the CPU; an odd-length + transfer is padded with a blank. A read of fewer characters than are present + in the buffer will return the remaining characters when the next read is + performed. + + Each read or write is terminated by the CPU sending one additional word (the + RTE drivers send -1). The command completes when this word is acknowledged + by the card setting the device flag. For zero-length writes, this additional + word will be the only word sent. + + Data transfer is also used by the "Download executable" command to absorb the + downloaded program. The firmware jumps to location 5100 hex in the + downloaded program upon completion of reception. It is the responsibility of + the program to return to the multiplexer firmware and to return to the CPU + whatever status is appropriate when it is done. Under simulation, we simply + "sink" the program and return status compatible with the multiplexer + diagnostic program to simulate a passing test. + + Entry in the idle state checks for unsolicited interrupts. UIs are sent to + the host when the controller is idle, UIs have been enabled, and a UI + condition exists. If a UI is not acknowledged, it will remain pending and + will be reissued the next time the controller is idle and UIs have been + enabled. + + UI conditions are kept in the per-port flags. The UI conditions are write + buffer available, read buffer available, break received, modem line + connected, and modem line disconnected. The latter two conditions are not + implemented in this simulation. If a break condition occurs at the same time + as a read buffer completion, the break has priority; the buffer UI will occur + after the break UI is acknowledged. + + The firmware checks for UI condition flags as part of the scheduler polling + loop. Under simulation, though, UIs can occur only in two places: the point + of origin (e.g., termination of a read buffer), or the "Enable unsolicited + input" command executor. UIs will be generated at the point of origin only + if the simulator is idle. If the simulator is not idle, it is assumed that + UIs have been disabled to execute the current command and will be reenabled + when the command sequence is complete. + + When the multiplexer is reset, and before the port keys are set, all ports + enter "echoplex" mode. In this mode, characters received are echoed back as + a functional test. Each port terminates buffers on CR reception. We detect + this condition, cancel the buffer, and discard the buffer termination UI. + + Implementation notes: + + 1. The firmware transfers the full amount requested by the CPU, even if the + transfer is longer than the buffer. Also, zero-length transfers program + the card DMA chip to transfer 0 bytes; this results in a transfer of 217 + bytes, per the Zilog databook. Under simulation, writes beyond the + buffer are accepted from the CPU but discarded, and reads beyond the + buffer return blanks. + + 2. We should never return from this routine in the "cmd" state, so debugging + will report "internal error!" if we do. +*/ + +t_stat mpx_cntl_svc (UNIT *uptr) +{ +uint8 ch; +uint32 i; +t_bool add_crlf; +t_bool set_flag = TRUE; +STATE last_state = mpx_state; + +static const char *cmd_state [] = { "complete", "internal error!", "waiting for parameter", "executing" }; + + +switch (mpx_state) { /* dispatch on current state */ + + case idle: /* controller idle */ + set_flag = FALSE; /* assume no UI */ + + if (mpx_uicode) { /* unacknowledged UI? */ + if (mpx_uien == TRUE) { /* interrupts enabled? */ + mpx_port = GET_UIPORT (mpx_uicode); /* get port number */ + mpx_portkey = mpx_key [mpx_port]; /* get port key */ + mpx_ibuf = mpx_uicode & UI_REASON | mpx_portkey; /* report UI reason and port key */ + set_flag = TRUE; /* reissue host interrupt */ + mpx_uien = FALSE; /* disable UI */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Port %d key %d unsolicited interrupt reissued, " + "reason = %d\n", mpx_port, mpx_portkey, GET_UIREASON (mpx_uicode)); + } + } + + else { /* no unacknowledged UI */ + for (i = 0; i < MPX_PORTS; i++) { /* check all ports for UIs */ + if (mpx_flags [i] & FL_UI_PENDING) { /* pending UI? */ + mpx_portkey = mpx_key [i]; /* get port key */ + + if (mpx_portkey == KEY_DEFAULT) { /* key defined? */ + if (mpx_flags [i] & FL_HAVEBUF) /* no, is this read buffer avail? */ + buf_cancel (ioread, i, get); /* cancel buffer */ + + mpx_flags [i] &= ~FL_UI_PENDING; /* cancel pending UI */ + } + + else if (mpx_uien == TRUE) { /* interrupts enabled? */ + if ((mpx_flags [i] & FL_WANTBUF) && /* port wants a write buffer? */ + (buf_avail (iowrite, i) > 0)) /* and one is available? */ + mpx_uicode = UI_WRBUF_AVAIL; /* set UI reason */ + + else if (mpx_flags [i] & FL_BREAK) /* received a line BREAK? */ + mpx_uicode = UI_BRK_RECD; /* set UI reason */ + + else if (mpx_flags [i] & FL_HAVEBUF) /* have a read buffer ready? */ + mpx_uicode = UI_RDBUF_AVAIL; /* set UI reason */ + + if (mpx_uicode) { /* UI to send? */ + mpx_port = i; /* set port number for Acknowledge */ + mpx_ibuf = mpx_uicode | mpx_portkey; /* merge UI reason and port key */ + mpx_uicode = mpx_uicode | mpx_port; /* save UI reason and port */ + set_flag = TRUE; /* interrupt host */ + mpx_uien = FALSE; /* disable UI */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Port %d key %d unsolicited interrupt generated, " + "reason = %d\n", i, mpx_portkey, GET_UIREASON (mpx_uicode)); + + break; /* quit after first UI */ + } + } + } + } + } + break; + + + case cmd: /* command state */ + if (mpx_cmd & CMD_TWO_WORDS) /* two-word command? */ + mpx_state = param; /* look for parameter before executing */ + else + set_flag = exec_command (); /* execute one-word command */ + break; + + + case param: /* parameter get state */ + mpx_param = mpx_obuf; /* save parameter */ + set_flag = exec_command (); /* execute two-word command */ + break; + + + case exec: /* execution state */ + switch (mpx_cmd) { + + case CMD_BINARY_READ: /* fast binary read */ + mpx_flags [0] &= ~FL_HAVEBUF; /* data word was picked up by CPU */ + set_flag = FALSE; /* suppress device flag */ + break; + + + case CMD_WRITE: /* transfer data to buffer */ + if (mpx_iolen <= 0) { /* last (or only) entry? */ + mpx_state = idle; /* idle controller */ + + if (mpx_iolen < 0) /* tie-off for buffer complete? */ + break; /* we're done */ + } + + add_crlf = ((mpx_param & /* CRLF should be added */ + (WR_ADD_CRLF | WR_PARTIAL)) == WR_ADD_CRLF); + + for (i = 0; i < 2; i++) /* output one or two chars */ + if (mpx_iolen > 0) { /* more to do? */ + if (i) /* high or low byte? */ + ch = (uint8) (mpx_obuf & 0377); /* low byte */ + else + ch = mpx_obuf >> 8; /* high byte */ + + if ((mpx_iolen == 1) && /* final char? */ + (ch == '_') && add_crlf) { /* underscore and asking for CRLF? */ + + add_crlf = FALSE; /* suppress CRLF */ + + if (DEBUG_PRI (mpx_dev, DEB_BUF)) + fprintf (sim_deb, ">>MPX buf: Port %d character '_' " + "suppressed CR/LF\n", mpx_port); + } + + else if (buf_len (iowrite, mpx_port, put) < WR_BUF_LIMIT) + buf_put (iowrite, mpx_port, ch); /* add char to buffer if space avail */ + + mpx_iolen = mpx_iolen - 1; /* drop remaining count */ + } + + if (mpx_iolen == 0) { /* buffer done? */ + if (add_crlf) { /* want CRLF? */ + buf_put (iowrite, mpx_port, CR); /* add CR to buffer */ + buf_put (iowrite, mpx_port, LF); /* add LF to buffer */ + } + + buf_term (iowrite, mpx_port, mpx_param >> 8); /* terminate buffer */ + mpx_iolen = -1; /* mark as done */ + } + + if (DEBUG_PRI (mpx_dev, DEB_CMDS) && + (sim_is_active (&mpx_unit [mpx_port]) == 0)) + fprintf (sim_deb, ">>MPX cmds: Port %d service scheduled, " + "time = %d\n", mpx_port, mpx_unit [mpx_port].wait); + + sim_activate (&mpx_unit [mpx_port], /* start line service */ + mpx_unit [mpx_port].wait); + break; + + + case CMD_READ: /* transfer data from buffer */ + if (mpx_iolen < 0) { /* input complete? */ + if (mpx_obuf == 0177777) { /* "tie-off" word received? */ + if (buf_len (ioread, mpx_port, get) == 0) { /* buffer now empty? */ + buf_free (ioread, mpx_port); /* free buffer */ + + if (buf_avail (ioread, mpx_port) == 1) /* another buffer available? */ + mpx_flags [mpx_port] |= FL_HAVEBUF; /* indicate availability */ + } + + mpx_state = idle; /* idle controller */ + } + + else + set_flag = FALSE; /* ignore word */ + + break; + } + + for (i = 0; i < 2; i++) /* input one or two chars */ + if (mpx_iolen > 0) { /* more to transfer? */ + if (buf_len (ioread, mpx_port, get) > 0) /* more chars available? */ + ch = buf_get (ioread, mpx_port); /* get char from buffer */ + else /* buffer exhausted */ + ch = ' '; /* pad with blank */ + + if (i) /* high or low byte? */ + mpx_ibuf = mpx_ibuf | ch; /* low byte */ + else + mpx_ibuf = ch << 8; /* high byte */ + + mpx_iolen = mpx_iolen - 1; /* drop count */ + } + + else /* odd number of chars */ + mpx_ibuf = mpx_ibuf | ' '; /* pad last with blank */ + + if (mpx_iolen == 0) /* end of host xfer? */ + mpx_iolen = -1; /* mark as done */ + + break; + + + case CMD_DL_EXEC: /* sink data from host */ + if (mpx_iolen <= 0) { /* final entry? */ + mpx_state = idle; /* idle controller */ + mpx_ibuf = ST_DIAG_OK; /* return diag passed status */ + } + + else { + if (mpx_iolen > 0) /* more from host? */ + mpx_iolen = mpx_iolen - 2; /* sink two bytes */ + + if (mpx_iolen <= 0) /* finished download? */ + sim_activate (&mpx_cntl, CMD_DELAY); /* schedule completion */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Download completion scheduled, " + "time = %d\n", CMD_DELAY); + } + + break; + + + default: /* no other entries allowed */ + return SCPE_IERR; /* simulator error! */ + } + break; + } + + +if (DEBUG_PRI (mpx_dev, DEB_CMDS) && /* debug print? */ + (last_state != mpx_state)) { /* and state change? */ + fprintf (sim_deb, ">>MPX cmds: Command %03o ", mpx_cmd); + + if ((mpx_cmd & CMD_TWO_WORDS) && (mpx_state != param)) + fprintf (sim_deb, "parameter %06o ", mpx_param); + + fputs (cmd_state [mpx_state], sim_deb); + fputc ('\n', sim_deb); + } + +if (set_flag) { + mpx_io (mpx_dib.devno, ioENF, 0); /* set device flag */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fputs (">>MPX cmds: Flag set\n", sim_deb); + } + +return SCPE_OK; +} + + +/* Multiplexer line service. + + The line service routine is used to transmit and receive characters. It is + started when a buffer is ready for output or when the Telnet poll routine + determines that there are characters ready for input, and it is stopped when + there are no more characters to output or input. When a line is quiescent, + this routine does not run. Service times are selected to approximate the + baud rate setting of the multiplexer port. + + "Fast timing" mode enables three optimizations. First, buffered characters + are transferred via Telnet in blocks, rather than a character at a time; this + reduces network traffic and decreases simulator overhead (there is only one + service routine entry per block, rather than one per character). Second, + ENQ/ACK handshaking is done locally, without involving the Telnet client. + Third, when editing and echo is enabled, entering BS echoes a backspace, a + space, and a backspace, and entering DEL echoes a backslash, a carriage + return, and a line feed, providing better compatibility with prior RTE + terminal drivers. + + Each read and write buffer begins with a reserved header byte that stores + per-buffer information, such as whether handshaking should be suppressed + during output, or the specific cause of termination for input. Buffer + termination sets the header byte with the appropriate flags. + + For output, a character counter is maintained and is incremented if ENQ/ACK + handshaking is enabled for the current port and request. If the counter + limit is reached, an ENQ is sent, and a flag is set to suspend transmission + until an ACK is received. If the last character of the buffer is sent, the + write buffer is freed, and a UI check is made if the controller is idle, in + case a write buffer request is pending. + + For input, the character is retrieved from the Telnet buffer. If a BREAK was + received, break status is set, and the character is discarded (the current + multiplexer library implementation always returns a NUL with a BREAK + indication). If the character is an XOFF, and XON/XOFF pacing is enabled, a + flag is set, and transmission is suspended until a corresponding XON is + received. If the character is an ACK and is in response to a previously sent + ENQ, it is discarded, and transmission is reenabled. + + If editing is enabled, a BS will delete the last character in the read + buffer, and a DEL will delete the entire buffer. Otherwise, buffer + termination conditions are checked (end on character, end on count, or + buffer full), and if observed, the read buffer is terminated, and a read + buffer available UI condition is signalled. + + Implementation notes: + + 1. The firmware echoes an entered BS before checking the buffer count to see + if there are any characters to delete. Under simulation, we only echo if + the buffer is not empty. + + 2. The "Fast binary read" command inhibits the normal transmit and receive + processing. Instead, a pair of characters are sought on line 0 to fill + the input buffer. When they are received, the device flag is set. The + CPU will do a LIx sc,C to retrieve the data and reset the flag. +*/ + +t_stat mpx_line_svc (UNIT *uptr) +{ +const uint32 port = uptr - mpx_unit; /* port number */ +const uint16 rt = mpx_rcvtype [port]; /* receive type for port */ +const uint32 data_bits = 5 + GET_BPC (mpx_config [port]); /* number of data bits */ +const uint32 data_mask = (1 << data_bits) - 1; /* mask for data bits */ +const t_bool fast_timing = (uptr->flags & UNIT_FASTTIME) != 0; /* port is set for fast timing */ +const t_bool fast_binary_read = (mpx_cmd == CMD_BINARY_READ); /* fast binary read in progress */ + +uint8 ch; +int32 chx; +uint16 read_length; +t_stat status = SCPE_OK; +t_bool recv_loop = !fast_binary_read; /* bypass if fast binary read */ +t_bool xmit_loop = !(fast_binary_read || /* bypass if fast read or output suspended */ + (mpx_flags [port] & (FL_WAITACK | FL_XOFF))); + + +/* Transmission service */ + +while (xmit_loop && (buf_len (iowrite, port, get) > 0)) { /* character available to output? */ + if ((mpx_flags [port] & FL_WREMPT) == 0) { /* has buffer started emptying? */ + chx = buf_get (iowrite, port) << 8; /* get header value and position */ + + if (fast_timing || (chx & WR_NO_ENQACK) || /* do we want handshake? */ + !(mpx_config [port] & SK_ENQACK)) /* and configured for handshake? */ + mpx_flags [port] &= ~FL_DO_ENQACK; /* no, so clear flag */ + else + mpx_flags [port] |= FL_DO_ENQACK; /* yes, so set flag */ + + continue; /* "continue" for zero-length write */ + } + + if (mpx_flags [port] & FL_DO_ENQACK) /* do handshake for this buffer? */ + mpx_enq_cntr [port] = mpx_enq_cntr [port] + 1; /* bump character counter */ + + if (mpx_enq_cntr [port] > ENQ_LIMIT) { /* ready for ENQ? */ + mpx_enq_cntr [port] = 0; /* clear ENQ counter */ + mpx_ack_wait [port] = 0; /* clear ACK wait timer */ + + mpx_flags [port] |= FL_WAITACK; /* set wait for ACK */ + ch = ENQ; + status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit ENQ */ + xmit_loop = FALSE; /* stop further transmission */ + } + + else { /* not ready for ENQ */ + ch = buf_get (iowrite, port) & data_mask; /* get char and mask to bit width */ + status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit the character */ + xmit_loop = (status == SCPE_OK) && fast_timing; /* continue transmission? */ + } + + if ((status == SCPE_OK) && /* transmitted OK? */ + DEBUG_PRI (mpx_dev, DEB_XFER)) + fprintf (sim_deb, ">>MPX xfer: Port %d character %s transmitted\n", + port, fmt_char (ch)); + + else + xmit_loop = FALSE; + + if (buf_len (iowrite, port, get) == 0) { /* buffer complete? */ + buf_free (iowrite, port); /* free buffer */ + + if (mpx_state == idle) /* controller idle? */ + mpx_cntl_svc (&mpx_cntl); /* check for UI */ + } + } + + +/* Reception service */ + +while (recv_loop && /* OK to process? */ + (chx = tmxr_getc_ln (&mpx_ldsc [port]))) { /* and new char available? */ + + if (chx & SCPE_BREAK) { /* break detected? */ + mpx_flags [port] |= FL_BREAK; /* set break status */ + + if (DEBUG_PRI (mpx_dev, DEB_XFER)) + fputs (">>MPX xfer: Break detected\n", sim_deb); + + if (mpx_state == idle) /* controller idle? */ + mpx_cntl_svc (&mpx_cntl); /* check for UI */ + + continue; /* discard NUL that accompanied BREAK */ + } + + ch = chx & data_mask; /* mask to bits per char */ + + if ((ch == XOFF) && /* XOFF? */ + (mpx_flowcntl [port] & FC_XONXOFF)) { /* and handshaking enabled? */ + mpx_flags [port] |= FL_XOFF; /* suspend transmission */ + + if (DEBUG_PRI (mpx_dev, DEB_XFER)) + fprintf (sim_deb, ">>MPX xfer: Port %d character XOFF " + "suspends transmission\n", port); + + recv_loop = fast_timing; /* set to loop if fast mode */ + continue; + } + + else if ((ch == XON) && /* XON? */ + (mpx_flags [port] & FL_XOFF)) { /* and currently suspended? */ + mpx_flags [port] &= ~FL_XOFF; /* resume transmission */ + + if (DEBUG_PRI (mpx_dev, DEB_XFER)) + fprintf (sim_deb, ">>MPX xfer: Port %d character XON " + "resumes transmission\n", port); + + recv_loop = fast_timing; /* set to loop if fast mode */ + continue; + } + + if (DEBUG_PRI (mpx_dev, DEB_XFER)) + fprintf (sim_deb, ">>MPX xfer: Port %d character %s received\n", + port, fmt_char (ch)); + + if ((ch == ACK) && (mpx_flags [port] & FL_WAITACK)) { /* ACK and waiting for it? */ + mpx_flags [port] = mpx_flags [port] & ~FL_WAITACK; /* clear wait flag */ + recv_loop = FALSE; /* absorb character */ + } + + else if ((buf_avail (ioread, port) == 0) && /* no free buffer available for char? */ + !(mpx_flags [port] & FL_RDFILL)) { /* and not filling last buffer? */ + mpx_flags [port] |= FL_RDOVFLOW; /* set buffer overflow flag */ + recv_loop = fast_timing; /* continue loop if fast mode */ + } + + else { /* buffer is available */ + if (rt & RT_ENAB_EDIT) /* editing enabled? */ + if (ch == BS) { /* backspace? */ + if (buf_len (ioread, port, put) > 0) /* at least one character in buffer? */ + buf_remove (ioread, port); /* remove last char */ + + if (rt & RT_ENAB_ECHO) { /* echo enabled? */ + tmxr_putc_ln (&mpx_ldsc [port], BS); /* echo BS */ + + if (fast_timing) { /* fast timing mode? */ + tmxr_putc_ln (&mpx_ldsc [port], ' '); /* echo space */ + tmxr_putc_ln (&mpx_ldsc [port], BS); /* echo BS */ + } + } + + continue; + } + + else if (ch == DEL) { /* delete line? */ + buf_cancel (ioread, port, put); /* cancel put buffer */ + + if (rt & RT_ENAB_ECHO) { /* echo enabled? */ + if (fast_timing) /* fast timing mode? */ + tmxr_putc_ln (&mpx_ldsc [port], '\\'); /* echo backslash */ + + tmxr_putc_ln (&mpx_ldsc [port], CR); /* echo CR */ + tmxr_putc_ln (&mpx_ldsc [port], LF); /* and LF */ + } + + continue; + } + + if (uptr->flags & UNIT_CAPSLOCK) /* caps lock mode? */ + ch = toupper (ch); /* convert to upper case if lower */ + + if (rt & RT_ENAB_ECHO) /* echo enabled? */ + tmxr_putc_ln (&mpx_ldsc [port], ch); /* echo the char */ + + if (rt & RT_END_ON_CHAR) { /* end on character? */ + recv_loop = FALSE; /* assume termination */ + + if ((ch == CR) && (rt & RT_END_ON_CR)) { + if (rt & RT_ENAB_ECHO) /* echo enabled? */ + tmxr_putc_ln (&mpx_ldsc [port], LF); /* send LF */ + mpx_param = RS_ETC_CR; /* set termination condition */ + } + + else if ((ch == RS) && (rt & RT_END_ON_RS)) + mpx_param = RS_ETC_RS; /* set termination condition */ + + else if ((ch == EOT) && (rt & RT_END_ON_EOT)) + mpx_param = RS_ETC_EOT; /* set termination condition */ + + else if ((ch == DC2) && (rt & RT_END_ON_DC2)) + mpx_param = RS_ETC_DC2; /* set termination condition */ + + else + recv_loop = TRUE; /* no termination */ + } + + if (recv_loop) /* no termination condition? */ + buf_put (ioread, port, ch); /* put character in buffer */ + + read_length = buf_len (ioread, port, put); /* get current buffer length */ + + if ((rt & RT_END_ON_CNT) && /* end on count */ + (read_length == mpx_charcnt [port])) { /* and count reached? */ + recv_loop = FALSE; /* set termination */ + mpx_param = 0; /* no extra termination info */ + + if (mpx_flags [port] & FL_ALERT) { /* was this alert for term rcv buffer? */ + mpx_flags [port] &= ~FL_ALERT; /* clear alert flag */ + mpx_charcnt [port] = RD_BUF_LIMIT; /* reset character count */ + } + } + + else if (read_length == RD_BUF_LIMIT) { /* buffer now full? */ + recv_loop = FALSE; /* set termination */ + mpx_param = mpx_param | RS_PARTIAL; /* and partial buffer flag */ + } + + if (recv_loop) /* no termination condition? */ + recv_loop = fast_timing; /* set to loop if fast mode */ + + else { /* termination occurred */ + if (DEBUG_PRI (mpx_dev, DEB_XFER)) { + fprintf (sim_deb, ">>MPX xfer: Port %d read terminated on ", port); + + if (mpx_param & RS_PARTIAL) + fputs ("buffer full\n", sim_deb); + else if (rt & RT_END_ON_CHAR) + fprintf (sim_deb, "character %s\n", fmt_char (ch)); + else + fprintf (sim_deb, "count = %d\n", mpx_charcnt [port]); + } + + if (buf_len (ioread, port, put) == 0) { /* zero-length read? */ + buf_put (ioread, port, 0); /* dummy put to reserve header */ + buf_remove (ioread, port); /* back out dummy char leaving header */ + } + + buf_term (ioread, port, mpx_param >> 8); /* terminate buffer and set header */ + + if (buf_avail (ioread, port) == 1) /* first read buffer? */ + mpx_flags [port] |= FL_HAVEBUF; /* indicate availability */ + + if (mpx_state == idle) /* controller idle? */ + mpx_cntl_svc (&mpx_cntl); /* check for UI */ + } + } + } + + +/* Housekeeping */ + +if (fast_binary_read) { /* fast binary read in progress? */ + if (port == 0) { /* on port 0? */ + chx = tmxr_getc_ln (&mpx_ldsc [0]); /* see if a character is ready */ + + if (chx && !(mpx_flags [0] & FL_HAVEBUF)) { /* character ready and buffer empty? */ + if (mpx_flags [0] & FL_WANTBUF) { /* second character? */ + mpx_ibuf = mpx_ibuf | (chx & DMASK8); /* merge it into word */ + mpx_flags [0] |= FL_HAVEBUF; /* mark buffer as ready */ + + mpx_io (mpx_dib.devno, ioENF, 0); /* set device flag */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fputs (">>MPX cmds: Flag and SRQ set\n", sim_deb); + } + + else /* first character */ + mpx_ibuf = (chx & DMASK8) << 8; /* put in top half of word */ + + mpx_flags [0] ^= FL_WANTBUF; /* toggle byte flag */ + } + + sim_activate (uptr, uptr->wait); /* reschedule service for fast response */ + } + } + +else { /* normal service */ + tmxr_poll_tx (&mpx_desc); /* output any accumulated characters */ + + if ((buf_avail (iowrite, port) < 2) && /* more to transmit? */ + !(mpx_flags [port] & (FL_WAITACK | FL_XOFF)) || /* and transmission not suspended */ + tmxr_rqln (&mpx_ldsc [port])) /* or more to receive? */ + sim_activate (uptr, uptr->wait); /* reschedule service */ + else + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Port %d service stopped\n", port); + } + +return SCPE_OK; +} + + +/* Telnet poll service. + + This service routine is used to poll for Telnet connections and incoming + characters. It starts when the socket is attached and stops when the socket + is detached. + + Each line is then checked for a pending ENQ/ACK handshake. If one is + pending, the ACK counter is incremented, and if it times out, another ENQ is + sent to avoid stalls. Lines are also checked for available characters, and + the corresponding line I/O service routine is scheduled if needed. +*/ + +t_stat mpx_poll_svc (UNIT *uptr) +{ +uint32 i; +t_stat status = SCPE_OK; + +poll_connection (); /* check for new connection */ + +tmxr_poll_rx (&mpx_desc); /* poll for input */ + +for (i = 0; i < MPX_PORTS; i++) { /* check lines */ + if (mpx_flags [i] & FL_WAITACK) { /* waiting for ACK? */ + mpx_ack_wait [i] = mpx_ack_wait [i] + 1; /* increment ACK wait timer */ + + if (mpx_ack_wait [i] > ACK_LIMIT) { /* has wait timed out? */ + mpx_ack_wait [i] = 0; /* reset counter */ + status = tmxr_putc_ln (&mpx_ldsc [i], ENQ); /* send ENQ again */ + tmxr_poll_tx (&mpx_desc); /* transmit it */ + + if ((status == SCPE_OK) && /* transmitted OK? */ + DEBUG_PRI (mpx_dev, DEB_XFER)) + fprintf (sim_deb, ">>MPX xfer: Port %d character ENQ retransmitted\n", i); + } + } + + if (tmxr_rqln (&mpx_ldsc [i])) /* chars available? */ + sim_activate (&mpx_unit [i], mpx_unit [i].wait); /* activate I/O service */ + } + +if (uptr->wait == POLL_FIRST) /* first poll? */ + uptr->wait = sync_poll (INITIAL); /* initial synchronization */ +else /* not first */ + uptr->wait = sync_poll (SERVICE); /* continue synchronization */ + +sim_activate (uptr, uptr->wait); /* continue polling */ + +return SCPE_OK; +} + + +/* Simulator reset routine. + + The hardware CRS signal generates a reset signal to the Z80 and its + peripherals. This causes execution of the power up initialization code. + + The CRS signal also has these hardware effects: + - clears control + - clears flag + - clears flag buffer + - clears backplane ready + - clears the output buffer register + + Implementation notes: + + 1. Under simulation, we also clear the input buffer register, even though + the hardware doesn't. + + 2. We set up the first poll for Telnet connections to occur "immediately" + upon execution, so that clients will be connected before execution + begins. Otherwise, a fast program may access the multiplexer before the + poll service routine activates. + + 3. We must set the "emptying_flags" and "filling_flags" values here, because + they cannot be initialized statically, even though the values are + constant. +*/ + +t_stat mpx_reset (DEVICE *dptr) +{ +if (sim_switches & SWMASK ('P')) { /* PON reset? */ + emptying_flags [ioread] = FL_RDEMPT; /* initialize buffer flags constants */ + emptying_flags [iowrite] = FL_WREMPT; + filling_flags [ioread] = FL_RDFILL; + filling_flags [iowrite] = FL_WRFILL; + } + +mpx_io (mpx_dib.devno, ioPOPIO, 0); /* send POPIO signal */ + +mpx_ibuf = 0; /* clear input buffer */ + +if (mpx_poll.flags & UNIT_ATT) { /* network attached? */ + mpx_poll.wait = POLL_FIRST; /* set up poll */ + sim_activate (&mpx_poll, mpx_poll.wait); /* start Telnet poll immediately */ + } +else + sim_cancel (&mpx_poll); /* else stop Telnet poll */ + +return SCPE_OK; +} + + +/* Attach the multiplexer to a Telnet port. + + We are called by the ATTACH MPX command to attach the multiplexer to + the listening port indicated by . Logically, it is the multiplexer + device that is attached; however, SIMH only allows units to be attached. + This makes sense for devices such as tape drives, where the attached media is + a property of a specific drive. In our case, though, the listening port is a + property of the multiplexer card, not of any given serial line. As ATTACH + MPX is equivalent to ATTACH MPX0, the port would, by default, be attached to + the first serial line and be reported there in a SHOW MPX command. + + To preserve the logical picture, we attach the port to the Telnet poll unit, + which is normally disabled, inhibiting its display. Attaching to a disabled + unit is not allowed, so we first enable the unit, then attach it, then + disable it again. Attachment is reported by the "mpx_status" routine below. + + The Telnet poll service routine is synchronized with the other input polling + devices in the simulator to facilitate idling. +*/ + +t_stat mpx_attach (UNIT *uptr, char *cptr) +{ +t_stat status = SCPE_OK; + +if (uptr != mpx_unit) /* not unit 0? */ + return SCPE_NOATT; /* can't attach */ + +mpx_poll.flags = mpx_poll.flags & ~UNIT_DIS; /* enable unit */ +status = tmxr_attach (&mpx_desc, &mpx_poll, cptr); /* attach to socket */ +mpx_poll.flags = mpx_poll.flags | UNIT_DIS; /* disable unit */ + +if (status == SCPE_OK) { + mpx_poll.wait = POLL_FIRST; /* set up poll */ + sim_activate (&mpx_poll, mpx_poll.wait); /* start Telnet poll immediately */ + } +return status; +} + + +/* Detach the multiplexer. + + Normally, we are called by the DETACH MPX command, which is equivalent to + DETACH MPX0. However, we may be called with other units in two cases. + + A DETACH ALL command will call us for unit 9 (the poll unit) if it is + attached. Also, during simulator shutdown, we will be called for units 0-8 + (detach_all in scp.c calls the detach routines of all units that do NOT have + UNIT_ATTABLE), as well as for unit 9 if it is attached. In both cases, it is + imperative that we return SCPE_OK, otherwise any remaining device detaches + will not be performed. +*/ + +t_stat mpx_detach (UNIT *uptr) +{ +t_stat status = SCPE_OK; +int32 i; + +if ((uptr == mpx_unit) || (uptr == &mpx_poll)) { /* base unit or poll unit? */ + status = tmxr_detach (&mpx_desc, &mpx_poll); /* detach socket */ + + for (i = 0; i < MPX_PORTS; i++) { + mpx_ldsc [i].rcve = 0; /* disable line reception */ + sim_cancel (&mpx_unit [i]); /* cancel any scheduled I/O */ + } + + sim_cancel (&mpx_poll); /* stop Telnet poll */ + } + +return status; +} + + +/* Show multiplexer status */ + +t_stat mpx_status (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +if (mpx_poll.flags & UNIT_ATT) /* attached to socket? */ + fprintf (st, "attached to port %s, ", mpx_poll.filename); +else + fprintf (st, "not attached, "); + +tmxr_show_summ (st, uptr, val, desc); /* report connection count */ +return SCPE_OK; +} + + +/* Set firmware revision. + + Currently, we support only revision C, so the MTAB entry does not have an + "mstring" entry. When we add revision D support, an "mstring" entry of "REV" + will enable changing the firmware revision. +*/ + +t_stat mpx_set_frev (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if ((cptr == NULL) || /* no parameter? */ + (*cptr < 'C') || (*cptr > 'D') || /* or not C or D? */ + (*(cptr + 1) != '\0')) /* or not just one character? */ + return SCPE_ARG; /* bad argument */ + +else { + if (*cptr == 'C') /* setting revision C? */ + mpx_dev.flags = mpx_dev.flags & ~DEV_REV_D; /* clear 'D' flag */ + else if (*cptr == 'D') /* setting revision D? */ + mpx_dev.flags = mpx_dev.flags | DEV_REV_D; /* set 'D' flag */ + + return SCPE_OK; + } +} + + +/* Show firmware revision */ + +t_stat mpx_show_frev (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +if (mpx_dev.flags & DEV_REV_D) + fputs ("12792D", st); +else + fputs ("12792C", st); +return SCPE_OK; +} + + +/* Local routines */ + + +/* Poll for new Telnet connections */ + +static void poll_connection (void) +{ +int32 new_line; + +new_line = tmxr_poll_conn (&mpx_desc); /* check for new connection */ + +if (new_line >= 0) /* new connection established? */ + mpx_ldsc [new_line].rcve = 1; /* enable line to receive */ + +return; +} + + +/* Controller reset. + + This is the card microprocessor reset, not the simulator reset routine. It + simulates a power-on restart of the Z80 firmware. When it is called from the + simulator reset routine, that routine will take care of setting the card + flip-flops appropriately. +*/ + +static void controller_reset (void) +{ +uint32 i; + +mpx_state = idle; /* idle state */ + +mpx_cmd = 0; /* clear command */ +mpx_param = 0; /* clear parameter */ +mpx_uien = FALSE; /* disable interrupts */ + +for (i = 0; i < MPX_PORTS; i++) { /* clear per-line variables */ + buf_init (iowrite, i); /* initialize write buffers */ + buf_init (ioread, i); /* initialize read buffers */ + + mpx_key [i] = KEY_DEFAULT; /* clear port key to default */ + + if (i == 0) /* default port configurations */ + mpx_config [0] = SK_PWRUP_0; /* port 0 is separate from 1-7 */ + else + mpx_config [i] = SK_PWRUP_1 | i; + + mpx_rcvtype [i] = RT_PWRUP; /* power on config for echoplex */ + mpx_charcnt [i] = 0; /* default character count */ + mpx_flowcntl [i] = 0; /* default flow control */ + mpx_flags [i] = 0; /* clear state flags */ + mpx_enq_cntr [i] = 0; /* clear ENQ counter */ + mpx_ack_wait [i] = 0; /* clear ACK wait timer */ + mpx_unit [i].wait = service_time (mpx_config [i]); /* set terminal I/O time */ + + sim_cancel (&mpx_unit [i]); /* cancel line I/O */ + } + +sim_cancel (&mpx_cntl); /* cancel controller */ + +return; +} + + +/* Calculate service time from baud rate. + + Service times are based on 1580 instructions per second, which is the 1000 + E-Series execution speed. Baud rate 0 means "don't change" and is handled by + the "Set port key" command executor. + + Baud rate settings of 13-15 are marked as "reserved" in the user manual, but + the firmware defines these as 38400, 9600, and 9600 baud, respectively. +*/ + +static uint32 service_time (uint16 control_word) +{ +/* Baud Rates 0- 7 : --, 50, 75, 110, 134.5, 150, 300, 1200, + Baud Rates 8-15 : 1800, 2400, 4800, 9600, 19200, 38400, 9600, 9600 +*/ +static const int32 ticks [] = { 0, 316000, 210667, 143636, 117472, 105333, 52667, 13167, + 8778, 6583, 3292, 1646, 823, 411, 1646, 1646 }; + +return ticks [GET_BAUDRATE (control_word)]; /* return service time for indicated rate */ +} + + +/* Translate port key to port number. + + Port keys are scanned in reverse port order, so if more than one port has the + same port key, commands specifying that key will affect the highest numbered + port. + + If a port key is the reserved value 255, then the port key has not been set. + In this case, set the input buffer to 0xBAD0 and return -1 to indicate + failure. +*/ + +static int32 key_to_port (uint32 key) +{ +int32 i; + +for (i = MPX_PORTS - 1; i >= 0; i--) /* scan in reverse order */ + if (mpx_key [i] == key) /* key found? */ + return i; /* return port number */ + +mpx_ibuf = ST_BAD_KEY; /* key not found: set status */ +return -1; /* return failure code */ +} + + +/* Buffer manipulation routines. + + The 12792 hardware provides 16K bytes of RAM to the microprocessor. From + this pool, the firmware allocates per-port read/write buffers and state + variables, global variables, and the system stack. Allocations are static + and differ between firmware revisions. + + The A/B/C revisions allocate two 254-byte read buffers and two 254-byte write + buffers per port. Assuming an idle condition, the first write to a port + transfers characters to the first write buffer. When the transfer completes, + the SIO begins transmitting. During transmission, a second write can be + initiated, which transfers characters to the second write buffer. If a third + write is attempted before the first buffer has been released, it will be + denied until the SIO completes transmission; then, if enabled, an unsolicited + interrupt will occur to announce buffer availability. The "active" (filling) + buffer alternates between the two. + + At idle, characters received will fill the first read buffer. When the read + completes according to the previously set termination criteria, an + unsolicited interrupt will occur (if enabled) to announce buffer + availability. If more characters are received before the first buffer has + been transferred to the CPU, they will fill the second buffer. If that read + also completes, additional characters will be discarded until the first + buffer has been emptied. The "active" (emptying) buffer alternates between + the two. + + With this configuration, two one-character writes or reads will allocate both + available buffers, even though each was essentially empty. + + The D revision allocates one 1024-byte FIFO read buffer and one 892-byte + write buffer per port. As with the A/B/C revisions, the first write to a + port transfers characters to the write buffer, and serial transmission begins + when the write completes. However, the write buffer is not a FIFO, so the + host is not permitted another write request until the entire buffer has been + transmitted. + + The read buffer is a FIFO. Characters received are placed into the FIFO as a + stream. Unlike the A/B/C revisions, character editing and termination + conditions are not evaluated until the buffer is read. Therefore, a full + 1024 characters may be received before additional characters would be + discarded. + + When the first character is received, an unsolicited interrupt occurs (if + enabled) to announce data reception. A host read may then be initiated. The + write buffer is used temporarily to process characters from the read buffer. + Characters are copied from the read to the write buffer while editing as + directed by the configuration accompanying the read request (e.g., deleting + the character preceding a BS, stripping CR/LF, etc.). When the termination + condition is found, the read command completes. Incoming characters may be + added to the FIFO while this is occurring. + + In summary, the revision differences in buffer handling are: + + Revisions A/B/C: + - two 254-byte receive buffers + - a buffer is "full" when the terminator character or count is received + - termination type must be established before the corresponding read + - data is echoed as it is received + + Revision D: + - one 1024-byte receive buffer + - buffer is "full" only when 1024 characters are received + - the concept of a buffer terminator does not apply, as the data is not + examined until a read is requested and characters are retrieved from the + FIFO. + - data is not echoed until it is read + + To implement the C revision behavior, while preserving the option of reusing + the buffer handlers for future D revision support, the dual 254-byte buffers + are implemented as a single 514-byte circular FIFO with capacity limited to + 254 bytes per buffer. This reserves space for a CR and LF and for a header + byte in each buffer. The header byte preserves per-buffer state information. + + In this implementation, the buffer "put" index points at the next free + location, and the buffer "get" index points at the next character to + retrieve. In addition to "put" and "get" indexes, a third "separator" index + is maintained to divide the FIFO into two areas corresponding to the two + buffers, and a "buffer filling" flag is maintained for each FIFO that is set + by the fill (put) routine and cleared by the terminate buffer routine. + + Graphically, the implementation is as follows for buffer "B[]", get "G", put + "P", and separator "S" indexes: + + 1. Initialize: 2. Fill first buffer: + G = S = P = 0 B[P] = char; Incr (P) + + |------------------------------| |---------|--------------------| + G G P --> + S S + P + + 3. Terminate first buffer: 4. Fill second buffer: + if S == G then S = P else nop B[P] = char; Incr (P) + + |------------|-----------------| |------------|------|----------| + G /---> S G S P --> + * ----/ P + + 5. Terminate second buffer: 6. Empty first buffer: + if S == G then S = P else nop char = B[G]; Incr (G) + + |------------|------------|----| |----|-------|------------|----| + G S P G --> S P + + 7. First buffer is empty: 8. Free first buffer: + G == S if !filling then S = P else nop + + |------------|------------|----| |------------|------------|----| + G P G /---> S + S * ----/ P + + 9. Empty second buffer: 10. Second buffer empty: + char = B[G]; Incr (G) G == S + + |----------------|--------|----| |-------------------------|----| + G --> S G + P S + P + 11. Free second buffer: + if !filling then S = P else nop + + |-------------------------|----| + G + S + P + + We also provide the following utility routines: + + - Remove Character: Decr (P) + + - Cancel Buffer: if S == G then P = G else G = S + + - Buffer Length: if S < G then return S + BUFSIZE - G else return S - G + + - Buffers Available: if G == P then return 2 else if G != S != P then return + 0 else return 1 + + The "buffer filling" flag is necessary for the "free" routine to decide + whether to advance the separator index. If the first buffer is to be freed, + then G == S and S != P. If the second buffer is already filled, then S = P. + However, if the buffer is still filling, then S must remain at G. This + cannot be determined from G, S, and P alone. + + A "buffer emptying" flag is also employed to record whether the per-buffer + header has been obtained. This allows the buffer length to exclude the + header and reflect only the characters present. +*/ + + +/* Increment a buffer index with wraparound */ + +static uint16 buf_incr (BUF_INDEX index, uint32 port, IO_OPER rw, int increment) +{ +index [port] [rw] = + (index [port] [rw] + buf_size [rw] + increment) % buf_size [rw]; + +return index [port] [rw]; +} + + +/* Initialize the buffer. + + Initialization sets the three indexes to zero and clears the buffer state + flags. +*/ + +static void buf_init (IO_OPER rw, uint32 port) +{ +mpx_get [port] [rw] = 0; /* clear indexes */ +mpx_sep [port] [rw] = 0; +mpx_put [port] [rw] = 0; + +if (rw == ioread) + mpx_flags [mpx_port] &= ~(FL_RDFLAGS); /* clear read buffer flags */ +else + mpx_flags [mpx_port] &= ~(FL_WRFLAGS); /* clear write buffer flags */ +return; +} + + +/* Get a character from the buffer. + + The character indicated by the "get" index is retrieved from the buffer, and + the index is incremented with wraparound. If the buffer is now empty, the + "buffer emptying" flag is cleared. Otherwise, it is set to indicate that + characters have been removed from the buffer. +*/ + +static uint8 buf_get (IO_OPER rw, uint32 port) +{ +uint8 ch; +uint32 index = mpx_get [port] [rw]; /* current get index */ + +if (rw == ioread) + ch = mpx_rbuf [port] [index]; /* get char from read buffer */ +else + ch = mpx_wbuf [port] [index]; /* get char from write buffer */ + +buf_incr (mpx_get, port, rw, +1); /* increment circular get index */ + +if (DEBUG_PRI (mpx_dev, DEB_BUF)) + if (mpx_flags [port] & emptying_flags [rw]) + fprintf (sim_deb, ">>MPX buf: Port %d character %s get from %s buffer " + "[%d]\n", port, fmt_char (ch), io_op [rw], index); + else + fprintf (sim_deb, ">>MPX buf: Port %d header %03o get from %s buffer " + "[%d]\n", port, ch, io_op [rw], index); + +if (mpx_get [port] [rw] == mpx_sep [port] [rw]) /* buffer now empty? */ + mpx_flags [port] &= ~emptying_flags [rw]; /* clear "buffer emptying" flag */ +else + mpx_flags [port] |= emptying_flags [rw]; /* set "buffer emptying" flag */ + +return ch; +} + + +/* Put a character to the buffer. + + The character is written to the buffer in the slot indicated by the "put" + index, and the index is incremented with wraparound. The first character put + to a new buffer reserves space for the header and sets the "buffer filling" + flag. +*/ + +static void buf_put (IO_OPER rw, uint32 port, uint8 ch) +{ +uint32 index; + +if ((mpx_flags [port] & filling_flags [rw]) == 0) { /* first put to this buffer? */ + mpx_flags [port] |= filling_flags [rw]; /* set buffer filling flag */ + index = mpx_put [port] [rw]; /* get current put index */ + buf_incr (mpx_put, port, rw, +1); /* reserve space for header */ + + if (DEBUG_PRI (mpx_dev, DEB_BUF)) + fprintf (sim_deb, ">>MPX buf: Port %d reserved header " + "for %s buffer [%d]\n", port, io_op [rw], index); + } + +index = mpx_put [port] [rw]; /* get current put index */ + +if (rw == ioread) + mpx_rbuf [port] [index] = ch; /* put char in read buffer */ +else + mpx_wbuf [port] [index] = ch; /* put char in write buffer */ + +buf_incr (mpx_put, port, rw, +1); /* increment circular put index */ + +if (DEBUG_PRI (mpx_dev, DEB_BUF)) + fprintf (sim_deb, ">>MPX buf: Port %d character %s put to %s buffer " + "[%d]\n", port, fmt_char (ch), io_op [rw], index); +return; +} + + +/* Remove the last character put to the buffer. + + The most-recent character put to the buffer is removed by decrementing the + "put" index with wraparound. +*/ + +static void buf_remove (IO_OPER rw, uint32 port) +{ +uint8 ch; +uint32 index; + +index = buf_incr (mpx_put, port, rw, -1); /* decrement circular put index */ + +if (DEBUG_PRI (mpx_dev, DEB_BUF)) { + if (rw == ioread) + ch = mpx_rbuf [port] [index]; /* pick up char from read buffer */ + else + ch = mpx_wbuf [port] [index]; /* pick up char from write buffer */ + + fprintf (sim_deb, ">>MPX buf: Port %d character %s removed from %s buffer " + "[%d]\n", port, fmt_char (ch), io_op [rw], index); + } +return; +} + + +/* Terminate the buffer. + + The buffer is marked to indicate that filling is complete and that the next + "put" operation should begin a new buffer. The header value is stored in + first byte of buffer, which is reserved, and the "buffer filling" flag is + cleared. +*/ + +static void buf_term (IO_OPER rw, uint32 port, uint8 header) +{ +uint32 index = mpx_sep [port] [rw]; /* separator index */ + +if (rw == ioread) + mpx_rbuf [port] [index] = header; /* put header in read buffer */ +else + mpx_wbuf [port] [index] = header; /* put header in write buffer */ + +mpx_flags [port] = mpx_flags [port] & ~filling_flags [rw]; /* clear filling flag */ + +if (mpx_get [port] [rw] == index) /* reached separator? */ + mpx_sep [port] [rw] = mpx_put [port] [rw]; /* move sep to end of next buffer */ + +if (DEBUG_PRI (mpx_dev, DEB_BUF)) + fprintf (sim_deb, ">>MPX buf: Port %d header %03o terminated %s buffer\n", + port, header, io_op [rw]); +return; +} + + +/* Free the buffer. + + The buffer is marked to indicate that it is available for reuse, and the + "buffer emptying" flag is reset. +*/ + +static void buf_free (IO_OPER rw, uint32 port) +{ +if ((mpx_flags [port] & filling_flags [rw]) == 0) /* not filling next buffer? */ + mpx_sep [port] [rw] = mpx_put [port] [rw]; /* move separator to end of next buffer */ + /* else it will be moved when terminated */ +mpx_flags [port] = mpx_flags [port] & ~emptying_flags [rw]; /* clear emptying flag */ + +if (DEBUG_PRI (mpx_dev, DEB_BUF)) + fprintf (sim_deb, ">>MPX buf: Port %d released %s buffer\n", port, io_op [rw]); +return; +} + + +/* Cancel the selected buffer. + + The selected buffer is marked to indicate that it is empty. Either the "put" + buffer or the "get" buffer may be selected. +*/ + +static void buf_cancel (IO_OPER rw, uint32 port, BUF_SELECT which) +{ +if (which == put) { /* cancel put buffer? */ + mpx_put [port] [rw] = mpx_sep [port] [rw]; /* move put back to separator */ + mpx_flags [port] &= ~filling_flags [rw]; /* clear filling flag */ + } + +else { /* cancel get buffer */ + if (mpx_sep [port] [rw] == mpx_get [port] [rw]) { /* filling first buffer? */ + mpx_put [port] [rw] = mpx_get [port] [rw]; /* cancel first buffer */ + mpx_flags [port] &= ~filling_flags [rw]; /* clear filling flag */ + } + + else { /* not filling first buffer */ + mpx_get [port] [rw] = mpx_sep [port] [rw]; /* cancel first buffer */ + + if ((mpx_flags [port] & filling_flags [rw]) == 0) /* not filling second buffer? */ + mpx_sep [port] [rw] = mpx_put [port] [rw]; /* move separator to end of next buffer */ + } + + mpx_flags [port] &= ~emptying_flags [rw]; /* clear emptying flag */ + } + +if (DEBUG_PRI (mpx_dev, DEB_BUF)) + fprintf (sim_deb, ">>MPX buf: Port %d cancelled %s buffer\n", port, io_op [rw]); +return; +} + + +/* Get the buffer length. + + The current length of the selected buffer (put or get) is returned. For ease + of use, the returned length does NOT include the header byte, i.e., it + reflects only the characters contained in the buffer. + + If the put buffer is selected, and the buffer is filling, or the get buffer + is selected, and the buffer is not emptying, then subtract one from the + length for the allocated header. +*/ + +static uint32 buf_len (IO_OPER rw, uint32 port, BUF_SELECT which) +{ +int32 length; + +if (which == put) + length = mpx_put [port] [rw] - mpx_sep [port] [rw] - /* calculate length */ + ((mpx_flags [port] & filling_flags [rw]) != 0); /* account for allocated header */ + +else { + length = mpx_sep [port] [rw] - mpx_get [port] [rw]; /* calculate length */ + + if (length && !(mpx_flags [port] & emptying_flags [rw])) /* not empty and not yet emptying? */ + length = length - 1; /* account for allocated header */ + } + +if (length < 0) /* is length negative? */ + return length + buf_size [rw]; /* account for wraparound */ +else + return length; +} + + +/* Return the number of free buffers available. + + Either 0, 1, or 2 free buffers will be available. A buffer is available if + it contains no characters (including the header byte). +*/ + +static uint32 buf_avail (IO_OPER rw, uint32 port) +{ +if (mpx_get [port] [rw] == mpx_put [port] [rw]) /* get and put indexes equal? */ + return 2; /* all buffers are free */ + +else if ((mpx_get [port] [rw] != mpx_sep [port] [rw]) && /* get, separator, and put */ + (mpx_sep [port] [rw] != mpx_put [port] [rw])) /* all different? */ + return 0; /* no buffers are free */ + +else + return 1; /* one buffer free */ +} diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index f94d9be2..4d2e64fc 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-2006, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,10 +23,12 @@ 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 + MS 13181A 7970B 800bpi nine track magnetic tape 13183A 7970E 1600bpi nine track magnetic tape - 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified) + 11-Aug-08 JDB Revised to use AR instead of saved_AR in boot + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 28-Dec-06 JDB Added ioCRS state to I/O decoders 18-Sep-06 JDB Fixed 2nd CLR after WC causing another write Improve debug reporting, add debug flags 14-Sep-06 JDB Removed local BOT flag, now uses sim_tape_bot @@ -61,28 +63,17 @@ 30-May-02 RMS Widened POS to 32b 22-Apr-02 RMS Added maximum record length test - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. - References: - 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual (13181-90901, Nov-1982) - 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual (13183-90901, Nov-1983) + - SIMH Magtape Representation and Handling (Bob Supnik, 30-Aug-2006) */ + #include "hp2100_defs.h" +#include "hp2100_cpu.h" #include "sim_tape.h" #define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */ @@ -158,18 +149,23 @@ #define STA_DYN (STA_PE | STA_SEL | STA_TBSY | STA_BOT | \ STA_EOT | 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 FILE *sim_deb; - -int32 ms_ctype = 0; /* ctrl type */ +enum { A13181, A13183 } ms_ctype = A13181; /* ctrl type */ int32 ms_timing = 1; /* timing type */ + +FLIP_FLOP msc_control = CLEAR; +FLIP_FLOP msc_flag = CLEAR; +FLIP_FLOP msc_flagbuf = CLEAR; + int32 msc_sta = 0; /* status */ int32 msc_buf = 0; /* buffer */ int32 msc_usl = 0; /* unit select */ int32 msc_1st = 0; /* first service */ int32 msc_stopioe = 1; /* stop on error */ + +FLIP_FLOP msd_control = CLEAR; +FLIP_FLOP msd_flag = CLEAR; +FLIP_FLOP msd_flagbuf = CLEAR; + int32 msd_buf = 0; /* data buffer */ uint8 msxb[DBSIZE] = { 0 }; /* data buffer */ t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */ @@ -210,8 +206,8 @@ const TIMESET msc_times[3] = { }; DEVICE msd_dev, msc_dev; -int32 msdio (int32 inst, int32 IR, int32 dat); -int32 mscio (int32 inst, int32 IR, int32 dat); +uint32 msdio (uint32 select_code, IOSIG signal, uint32 data); +uint32 mscio (uint32 select_code, IOSIG signal, uint32 data); t_stat msc_svc (UNIT *uptr); t_stat msc_reset (DEVICE *dptr); t_stat msc_attach (UNIT *uptr, char *cptr); @@ -228,6 +224,8 @@ 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); char *ms_cmd_name (uint32 cmd); +t_stat ms_clear (void); + /* MSD data structures @@ -237,8 +235,8 @@ char *ms_cmd_name (uint32 cmd); */ DIB ms_dib[] = { - { MSD, 0, 0, 0, 0, 0, &msdio }, - { MSC, 0, 0, 0, 0, 0, &mscio } + { MSD, &msdio }, + { MSC, &mscio } }; #define msd_dib ms_dib[0] @@ -248,11 +246,9 @@ 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) }, + { FLDATA (CTL, msd_control, 0) }, + { FLDATA (FLG, msd_flag, 0) }, + { FLDATA (FBF, msd_flagbuf, 0) }, { BRDATA (DBUF, msxb, 8, 8, DBSIZE) }, { DRDATA (BPTR, ms_ptr, DB_N_SIZE + 1) }, { DRDATA (BMAX, ms_max, DB_N_SIZE + 1) }, @@ -299,11 +295,9 @@ REG msc_reg[] = { { 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) }, + { FLDATA (CTL, msc_control, 0) }, + { FLDATA (FLG, msc_flag, 0) }, + { FLDATA (FBF, msc_flagbuf, 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) }, @@ -365,178 +359,248 @@ DEVICE msc_dev = { 0, msc_deb, NULL, NULL }; -/* IO instructions */ -int32 msdio (int32 inst, int32 IR, int32 dat) +/* Data channel I/O signal handler */ + +uint32 msdio (uint32 select_code, IOSIG signal, uint32 data) { -int32 devd; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + msd_flag = msd_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + msd_flag = msd_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + case ioSFC: /* skip if flag is clear */ + setstdSKF (msd); break; - case ioOTX: /* output */ - msd_buf = dat; /* store data */ + case ioSFS: /* skip if flag is set */ + setstdSKF (msd); break; - case ioMIX: /* merge */ - dat = dat | msd_buf; + case ioIOI: /* I/O data input */ + data = msd_buf; break; - case ioLIX: /* load */ - dat = msd_buf; + case ioIOO: /* I/O data output */ + msd_buf = data; /* store data */ break; - case ioCRS: /* control reset (action unverif) */ - 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); - } + case ioPOPIO: /* power-on preset to I/O */ + ms_clear (); /* issue CLR to controller */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ + msd_flag = msd_flagbuf = SET; /* set flag and flag buffer */ + /* fall into CLC handler */ + case ioCLC: /* clear control flip-flop */ + msd_control = CLEAR; break; - case ioEDT: /* DMA end */ - clrFSR (devd); /* same as CLF */ + case ioSTC: /* set control flip-flop */ + msd_control = SET; break; - default: + case ioEDT: /* end data transfer */ + msd_flag = msd_flagbuf = CLEAR; /* same as CLF */ break; - } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ -return dat; + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, msd); /* set standard PRL signal */ + setstdIRQ (select_code, msd); /* set standard IRQ signal */ + setstdSRQ (select_code, msd); /* set standard SRQ signal */ + break; + + case ioIAK: /* interrupt acknowledge */ + msd_flagbuf = CLEAR; + break; + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + msdio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + msdio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } -int32 mscio (int32 inst, int32 IR, int32 dat) + +/* Command channel I/O signal handler. + + Implementation notes: + + 1. Commands are usually initiated with an STC cc,C instruction. The CLR + command completes immediately and sets the flag. This requires that we + ignore the CLF part (but still process the SIR). + + 2. The command channel card clears its flag and flag buffer on EDT, but as + it never asserts SRQ, it will never get EDT. Under simulation, we omit + the EDT handler. + + 3. In hardware, the command channel card passes PRH to PRL. The data card + actually drives PRL with both channels' control and flag states. That + is, the priority chain is broken at the data card, even when the command + card is interrupting. This works in hardware, but we must break PRL at + the command card under simulation to allow the command card to interrupt. +*/ + +uint32 mscio (uint32 select_code, IOSIG signal, uint32 data) { -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 }; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 sched_time; +UNIT *uptr = msc_dev.units + msc_usl; -devc = IR & I_DEVMASK; /* get device no */ -devd = devc - 1; -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + msc_flag = msc_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + msc_flag = msc_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (msc); break; - case ioOTX: /* output */ + + case ioSFS: /* skip if flag is set */ + setstdSKF (msc); + break; + + + case ioIOI: /* I/O data input */ + data = msc_sta & ~STA_DYN; /* get card status */ + + if ((uptr->flags & UNIT_OFFLINE) == 0) { /* online? */ + data = data | uptr->UST; /* add unit status */ + + if (sim_tape_bot (uptr)) /* BOT? */ + data = data | STA_BOT; + + if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */ + !((uptr->FNC & FNF_RWD) && sim_tape_bot (uptr))) + data = data | STA_TBSY; + + if (sim_tape_wrp (uptr)) /* write prot? */ + data = data | STA_WLK; + + if (sim_tape_eot (uptr)) /* EOT? */ + data = data | STA_EOT; + } + + else + data = data | STA_TBSY | STA_LOCAL; + + if (ms_ctype == A13183) /* 13183A? */ + data = data | STA_PE | (msc_usl << STA_V_SEL); + if (DEBUG_PRI (msc_dev, DEB_CPU)) - fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", dat); - msc_buf = dat; + fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", data); + + break; + + + case ioIOO: /* I/O data output */ + if (DEBUG_PRI (msc_dev, DEB_CPU)) + fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", data); + + msc_buf = data; msc_sta = msc_sta & ~STA_REJ; /* clear reject */ - if ((dat & 0377) == FNC_CLR) break; /* clear always ok */ + + if ((data & 0377) == FNC_CLR) /* clear always ok */ + break; + 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 */ + + if (data & FNF_CHS) { /* select change */ + msc_usl = map_sel[FNC_GETSEL (data)]; /* is immediate */ uptr = msc_dev.units + msc_usl; if (DEBUG_PRI (msc_dev, DEB_CMDS)) fprintf (sim_deb, ">>MSC OTx: Unit %d selected\n", msc_usl); } - if (((dat & FNF_MOT) && sim_is_active (uptr)) || - ((dat & FNF_REV) && sim_tape_bot (uptr)) || - ((dat & FNF_WRT) && sim_tape_wrp (uptr))) + + if (((data & FNF_MOT) && sim_is_active (uptr)) || + ((data & FNF_REV) && sim_tape_bot (uptr)) || + ((data & 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_tape_bot (uptr)) /* BOT? */ - dat = dat | STA_BOT; - if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */ - !((uptr->FNC & FNF_RWD) && sim_tape_bot (uptr))) - dat = dat | STA_TBSY; - if (sim_tape_wrp (uptr)) /* write prot? */ - dat = dat | STA_WLK; - if (sim_tape_eot (uptr)) /* EOT? */ - 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_PRI (msc_dev, DEB_CPU)) - fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", dat); + + case ioPOPIO: /* power-on preset to I/O */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + msc_flag = msc_flagbuf = SET; /* set flag and flag buffer */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + msc_control = CLEAR; break; - case ioCRS: /* control reset (action unverif) */ - case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else if (!(msc_sta & STA_REJ)) { /* STC, last cmd rejected? */ + + case ioSTC: /* set control flip-flop */ + if (!(msc_sta & STA_REJ)) { /* last cmd rejected? */ if ((msc_buf & 0377) == FNC_CLR) { /* clear? */ - for (i = 0; i < MS_NUMDR; i++) { /* look for write in progr */ - if (sim_is_active (&msc_unit[i]) && /* unit active? */ - (msc_unit[i].FNC == FNC_WC) && /* last cmd write? */ - (ms_ptr > 0)) { /* partial buffer? */ - if (DEBUG_PRI (msc_dev, DEB_RWS)) - fprintf (sim_deb, - ">>MSC STC: Unit %d wrote %d word partial record\n", - i, ms_ptr / 2); - if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF)) - ms_map_err (uptr, st); /* discard any error */ - ms_ptr = 0; /* clear partial */ - } - 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 */ + ms_clear (); /* issue CLR to controller */ + + msc_control = SET; /* set CTL for STC */ + msc_flag = msc_flagbuf = SET; /* set FLG for completion */ + + signal = ioSTC; /* eliminate possible CLF */ + if (DEBUG_PRI (msc_dev, DEB_CMDS)) fputs (">>MSC STC: Controller cleared\n", sim_deb); - return SCPE_OK; + + break; /* command completes immediately */ } + uptr->FNC = msc_buf & 0377; /* save function */ + if (uptr->FNC & FNF_RWD) { /* rewind? */ if (!sim_tape_bot (uptr)) /* not at BOT? */ uptr->UST = STA_REW; /* set rewinding */ + sched_time = msc_rtime; /* set response time */ } + else { if (sim_tape_bot (uptr)) /* 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 (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */ sim_activate (uptr, sched_time); /* else schedule op */ + if (DEBUG_PRI (msc_dev, DEB_CMDS)) fprintf (sim_deb, ">>MSC STC: Unit %d command %03o (%s) scheduled, " @@ -544,26 +608,43 @@ switch (inst) { /* case on opcode */ msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC), uptr->pos, sched_time); } + else if (DEBUG_PRI (msc_dev, DEB_CMDS)) fputs (">>MSC STC: Unit select (NOP)\n", sim_deb); + msc_sta = STA_BUSY; /* ctrl is busy */ msc_1st = 1; - setCTL (devc); /* go */ + msc_control = SET; /* go */ } break; - case ioEDT: /* DMA end */ - clrFSR (devc); /* same as CLF */ + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, msc); /* set standard PRL signal */ + setstdIRQ (select_code, msc); /* set standard IRQ signal */ + setstdSRQ (select_code, msc); /* set standard SRQ signal */ break; - default: - break; - } -if (IR & I_HC) { clrFSR (devc); } /* H/C option */ -return dat; + case ioIAK: /* interrupt acknowledge */ + msc_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + mscio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + mscio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service If rewind done, reposition to start of tape, set status @@ -582,17 +663,15 @@ return dat; t_stat msc_svc (UNIT *uptr) { -int32 devc, devd, unum; +int32 unum; t_mtrlnt tbc; t_stat st, r = SCPE_OK; -devc = msc_dib.devno; /* get device nos */ -devd = msd_dib.devno; 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 */ + mscio (msc_dib.devno, ioENF, 0); /* set flag */ return IORETURN (msc_stopioe, SCPE_UNATT); } @@ -695,14 +774,15 @@ switch (uptr->FNC) { /* case on function */ } break; /* err, done */ } - if (ms_ctype) msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */ + if (ms_ctype == A13183) + msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */ } - if (CTL (devd) && (ms_ptr < ms_max)) { /* DCH on, more data? */ - if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR; + if (msd_control && (ms_ptr < ms_max)) { /* DCH on, more data? */ + if (msd_flag) 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 */ + msdio (msd_dib.devno, ioENF, 0); /* set flag */ sim_activate (uptr, msc_xtime); /* re-activate */ return SCPE_OK; } @@ -739,8 +819,8 @@ switch (uptr->FNC) { /* case on function */ } else msc_sta = msc_sta | STA_PAR; } - if (CTL (devd)) { /* xfer flop set? */ - setFSR (devd); /* set dch flag */ + if (msd_control) { /* xfer flop set? */ + msdio (msd_dib.devno, ioENF, 0); /* set flag */ sim_activate (uptr, msc_xtime); /* re-activate */ return SCPE_OK; } @@ -770,7 +850,7 @@ switch (uptr->FNC) { /* case on function */ break; } -setFSR (devc); /* set cch flg */ +mscio (msc_dib.devno, ioENF, 0); /* set flag */ msc_sta = msc_sta & ~STA_BUSY; /* update status */ if (DEBUG_PRI (msc_dev, DEB_CMDS)) fprintf (sim_deb, @@ -779,6 +859,7 @@ if (DEBUG_PRI (msc_dev, DEB_CMDS)) return r; } + /* Write an erase gap */ t_stat ms_write_gap (UNIT *uptr) @@ -793,6 +874,7 @@ else return SCPE_OK; } + /* Map tape error status */ t_stat ms_map_err (UNIT *uptr, t_stat st) @@ -820,8 +902,11 @@ switch (st) { 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 */ + msc_sta = msc_sta | STA_EOF; + + if (ms_ctype == A13181) + msc_sta = msc_sta | STA_ODD; /* EOF also sets ODD for 13181A */ + break; case MTSE_INVRL: /* invalid rec lnt */ msc_sta = msc_sta | STA_PAR; @@ -844,6 +929,41 @@ switch (st) { return SCPE_OK; } + +/* Controller clear */ + +t_stat ms_clear (void) +{ +int32 i; +t_stat st; +UNIT *uptr; + +for (i = 0; i < MS_NUMDR; i++) { /* look for write in progr */ + uptr = &msc_unit [i]; /* get pointer to unit */ + + if (sim_is_active (uptr) && /* unit active? */ + (uptr->FNC == FNC_WC) && /* and last cmd write? */ + (ms_ptr > 0)) { /* and partial buffer? */ + if (DEBUG_PRI (msc_dev, DEB_RWS)) + fprintf (sim_deb, + ">>MSC rws: Unit %d wrote %d word partial record\n", i, ms_ptr / 2); + + if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF)) + ms_map_err (uptr, st); /* discard any error */ + + ms_ptr = 0; /* clear partial */ + } + + if ((uptr->UST & STA_REW) == 0) + sim_cancel (uptr); /* stop if not rew */ + } + +msc_sta = msc_1st = 0; /* clr ctlr status */ + +return SCPE_OK; +} + + /* Reset routine */ t_stat msc_reset (DEVICE *dptr) @@ -852,25 +972,31 @@ int32 i; UNIT *uptr; hp_enbdis_pair (dptr, /* make pair cons */ - (dptr == &msd_dev)? &msc_dev: &msd_dev); + (dptr == &msd_dev) ? &msc_dev : &msd_dev); + +if (sim_switches & SWMASK ('P')) /* PON reset? */ + ms_config_timing (); + +if (dptr == &msc_dev) /* command channel reset? */ + mscio (msc_dib.devno, ioPOPIO, 0); /* send POPIO signal to command channel */ +else /* data channel reset */ + msdio (msd_dib.devno, ioPOPIO, 0); /* send POPIO signal to data channel */ + 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 */ + for (i = 0; i < MS_NUMDR; i++) { uptr = msc_dev.units + i; sim_tape_reset (uptr); sim_cancel (uptr); uptr->UST = 0; } -ms_config_timing (); + return SCPE_OK; } + /* Attach routine */ t_stat msc_attach (UNIT *uptr, char *cptr) @@ -906,7 +1032,7 @@ void ms_config_timing (void) { uint32 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] = msc_times[tset][i]; /* assign times */ } @@ -949,8 +1075,10 @@ return SCPE_OK; t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (ms_ctype) fprintf (st, "13183A"); -else fprintf (st, "13181A"); +if (ms_ctype == A13183) + fprintf (st, "13183A"); +else + fprintf (st, "13181A"); return SCPE_OK; } @@ -995,7 +1123,7 @@ else switch (reel) { return SCPE_ARG; } -uptr->capac = uptr->REEL? (TCAP << uptr->REEL) << ms_ctype: 0; +uptr->capac = uptr->REEL ? (TCAP << uptr->REEL) << ms_ctype : 0; return SCPE_OK; } @@ -1044,7 +1172,7 @@ switch (cmd & 0377) { /* 7970B/7970E bootstrap routine (HP 12992D ROM) */ -const uint16 ms_rom[IBL_LNT] = { +const BOOT_ROM ms_rom = { 0106501, /*ST LIB 1 ; read sw */ 0006011, /* SLB,RSS ; bit 0 set? */ 0027714, /* JMP RD ; no read */ @@ -1114,13 +1242,11 @@ const uint16 ms_rom[IBL_LNT] = { 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 ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */ return SCPE_OK; } - diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c index 61f379ee..d0360aa7 100644 --- a/HP2100/hp2100_mt.c +++ b/HP2100/hp2100_mt.c @@ -1,6 +1,6 @@ /* hp2100_mt.c: HP 2100 12559A magnetic tape simulator - Copyright (c) 1993-2006, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,9 +23,12 @@ 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 - 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified) + 04-Sep-08 JDB Fixed missing flag after CLR command + 02-Sep-08 JDB Moved write enable and format commands from MTD to MTC + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 28-Dec-06 JDB Added ioCRS state to I/O decoders 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) @@ -45,24 +48,33 @@ 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: + References: + - 12559A 9-Track Magnetic Tape Unit Interface Kit Operating and Service Manual + (12559-9001, Jul-1970) + - SIMH Magtape Representation and Handling (Bob Supnik, 30-Aug-2006) - 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. + The 3030 was one of HP's earliest tape drives. The 12559A controller + supported a single 800 bpi, 9-track drive, operating at 75 inches per second. + It had two unusual characteristics: - Unusually among HP peripherals, the 12559 does not have a command flop, - and its flag and flag buffer power up as clear rather than set. + - The controller accepted only one byte per I/O word, rather than packing + two bytes per word. + + - The drive could not read or write fewer than 12 bytes per record. + + The first behavior meant that DMA operation required the byte-unpacking + feature of the 12578A DMA card for the 2116 computer. The second meant that + software drivers had to pad short records with blanks or nulls. + + Implementation notes: + + 1. The HP 3030 Magnetic Tape Subsystem diagnostic, part number 20433-60001, + has never been located, so this simulator has not been fully tested. It + does pass a functional test under DOS-III using driver DVR22. */ + #include "hp2100_defs.h" #include "sim_tape.h" @@ -93,8 +105,12 @@ #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]; +FLIP_FLOP mtd_flag = CLEAR; +FLIP_FLOP mtd_flagbuf = CLEAR; + +FLIP_FLOP mtc_control = CLEAR; +FLIP_FLOP mtc_flag = CLEAR; +FLIP_FLOP mtc_flagbuf = CLEAR; int32 mtc_fnc = 0; /* function */ int32 mtc_sta = 0; /* status register */ @@ -106,18 +122,18 @@ 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[] = { +static const uint32 mtc_cmd[] = { FNC_WC, FNC_RC, FNC_GAP, FNC_FSR, FNC_BSR, FNC_REW, FNC_RWS, FNC_WFM }; DEVICE mtd_dev, mtc_dev; -int32 mtdio (int32 inst, int32 IR, int32 dat); -int32 mtcio (int32 inst, int32 IR, int32 dat); +uint32 mtdio (uint32 select_code, IOSIG signal, uint32 data); +uint32 mtcio (uint32 select_code, IOSIG signal, uint32 data); t_stat mtc_svc (UNIT *uptr); -t_stat mtd_reset (DEVICE *dptr); -t_stat mtc_reset (DEVICE *dptr); +t_stat mt_reset (DEVICE *dptr); t_stat mtc_attach (UNIT *uptr, char *cptr); t_stat mtc_detach (UNIT *uptr); t_stat mt_map_err (UNIT *uptr, t_stat st); +t_stat mt_clear (void); /* MTD data structures @@ -127,8 +143,8 @@ t_stat mt_map_err (UNIT *uptr, t_stat st); */ DIB mt_dib[] = { - { MTD, 0, 0, 0, 0, 0, &mtdio }, - { MTC, 0, 0, 0, 0, 0, &mtcio } + { MTD, &mtdio }, + { MTC, &mtcio } }; #define mtd_dib mt_dib[0] @@ -137,11 +153,8 @@ 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) }, + { FLDATA (FLG, mtd_flag, 0) }, + { FLDATA (FBF, mtd_flagbuf, 0) }, { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) }, { DRDATA (BPTR, mt_ptr, DB_V_SIZE + 1) }, { DRDATA (BMAX, mt_max, DB_V_SIZE + 1) }, @@ -150,10 +163,6 @@ REG mtd_reg[] = { }; 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 } @@ -162,7 +171,7 @@ MTAB mtd_mod[] = { DEVICE mtd_dev = { "MTD", &mtd_unit, mtd_reg, mtd_mod, 1, 10, 16, 1, 8, 8, - NULL, NULL, &mtd_reset, + NULL, NULL, &mt_reset, NULL, NULL, NULL, &mtd_dib, DEV_DISABLE | DEV_DIS }; @@ -181,11 +190,9 @@ 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 (CTL, mtc_control, 0) }, + { FLDATA (FLG, mtc_flag, 0) }, + { FLDATA (FBF, mtc_flagbuf, 0) }, { FLDATA (DTF, mtc_dtf, 0) }, { FLDATA (FSVC, mtc_1st, 0) }, { DRDATA (POS, mtc_unit.pos, T_ADDR_W), PV_LEFT }, @@ -198,6 +205,10 @@ REG mtc_reg[] = { }; MTAB mtc_mod[] = { + { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD | MTAB_VDV | 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 } @@ -206,142 +217,234 @@ MTAB mtc_mod[] = { DEVICE mtc_dev = { "MTC", &mtc_unit, mtc_reg, mtc_mod, 1, 10, 31, 1, 8, 8, - NULL, NULL, &mtc_reset, + NULL, NULL, &mt_reset, NULL, &mtc_attach, &mtc_detach, &mtc_dib, DEV_DISABLE | DEV_DIS }; -/* IO instructions */ -int32 mtdio (int32 inst, int32 IR, int32 dat) +/* Data channel I/O signal handler + + The 12559A data channel interface has a number of non-standard features: + + - The card does not drive PRL or IRQ. + - The card does not respond to IAK. + - There is no control flip-flop; CLC resets the data transfer flip-flop. + - POPIO issues a CLR command and clears the flag and flag buffer flip-flops. + - CRS is not used. + + Implementation notes: + + 1. The data channel has a flag buffer flip-flop (necessary for the proper + timing of the flag flip-flop), but the data channel does not interrupt, + so the flag buffer serves no other purpose. +*/ + +uint32 mtdio (uint32 select_code, IOSIG signal, uint32 data) { -int32 devd; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + mtd_flag = mtd_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + mtd_flag = mtd_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + case ioSFC: /* skip if flag is clear */ + setstdSKF (mtd); break; - case ioOTX: /* output */ - mtc_unit.buf = dat & 0377; /* store data */ + case ioSFS: /* skip if flag is set */ + setstdSKF (mtd); break; - case ioMIX: /* merge */ - dat = dat | mtc_unit.buf; + case ioIOI: /* I/O data input */ + data = mtc_unit.buf; break; - case ioLIX: /* load */ - dat = mtc_unit.buf; + case ioIOO: /* I/O data output */ + mtc_unit.buf = data & 0377; /* store data */ break; - case ioCRS: /* control reset (action unverif) */ - case ioCTL: /* control clear/set */ - if (IR & I_CTL) mtc_dtf = 0; /* CLC: clr xfer flop */ + case ioPOPIO: /* power-on preset to I/O */ + mt_clear (); /* issue CLR to controller */ + mtd_flag = mtd_flagbuf = CLEAR; /* clear flag and flag buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ break; - default: + case ioCLC: /* clear control flip-flop */ + mtc_dtf = 0; /* clr xfer flop */ + mtd_flag = mtd_flagbuf = CLEAR; /* clear flag and flag buffer */ break; - } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ -return dat; + case ioSIR: /* set interrupt request */ + setstdSRQ (select_code, mtd); /* set standard SRQ signal */ + break; + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + mtdio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + mtdio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } -int32 mtcio (int32 inst, int32 IR, int32 dat) + +/* Command channel I/O signal handler. + + The 12559A command interface is reasonably standard, although POPIO clears, + rather than sets, the flag and flag buffer flip-flops. One unusual feature + is that commands are initiated when they are output to the interface with + OTA/B, rather than waiting until control is set with STC. STC simply enables + command-channel interrupts. + + Implementation notes: + + 1. In hardware, the command channel card passes PRH to PRL. The data card + actually drives PRL with the command channel's control and flag states. + That is, the priority chain is broken at the data card, although the + command card is interrupting. This works in hardware, but we must break + PRL at the command card under simulation to allow the command card to + interrupt. + + 2. In hardware, the CLR command takes 5 milliseconds to complete. During + this time, the BUSY bit is set in the status word. Under simulation, we + complete immediately, and the BUSY bit never sets.. +*/ + +uint32 mtcio (uint32 select_code, IOSIG signal, uint32 data) { +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ uint32 i; -int32 devc, devd, valid; -t_stat st; +int32 valid; -devc = IR & I_DEVMASK; /* get device no */ -devd = devc - 1; -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + mtc_flag = mtc_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + mtc_flag = mtc_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (mtc); 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; + + case ioSFS: /* skip if flag is set */ + setstdSKF (mtc); + break; + + + case ioIOI: /* I/O data input */ + data = mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY); + + if (mtc_unit.flags & UNIT_ATT) { /* construct status */ + if (sim_is_active (&mtc_unit)) + data = data | STA_BUSY; + + if (sim_tape_wrp (&mtc_unit)) + data = data | STA_WLK; } + else + data = data | STA_BUSY | STA_LOCAL; + break; + + + case ioIOO: /* I/O data output */ + data = data & 0377; + mtc_sta = mtc_sta & ~STA_REJ; /* clear reject */ + + if (data == FNC_CLR) { /* clear? */ + mt_clear (); /* send CLR to controller */ + + mtd_flag = mtd_flagbuf = CLEAR; /* clear data flag and flag buffer */ + mtc_flag = mtc_flagbuf = SET; /* set command flag and flag buffer */ + break; /* command completes immediately */ + } + for (i = valid = 0; i < sizeof (mtc_cmd); i++) /* is fnc valid? */ - if (dat == mtc_cmd[i]) valid = 1; + if (data == mtc_cmd[i]) + valid = 1; + if (!valid || sim_is_active (&mtc_unit) || /* is cmd valid? */ - ((mtc_sta & STA_BOT) && (dat == FNC_BSR)) || + ((mtc_sta & STA_BOT) && (data == FNC_BSR)) || (sim_tape_wrp (&mtc_unit) && - ((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM)))) + ((data == FNC_WC) || (data == FNC_GAP) || (data == FNC_WFM)))) mtc_sta = mtc_sta | STA_REJ; + else { sim_activate (&mtc_unit, mtc_ctime); /* start tape */ - mtc_fnc = dat; /* save function */ + mtc_fnc = data; /* save function */ mtc_sta = STA_BUSY; /* unit busy */ mt_ptr = 0; /* init buffer ptr */ - clrFSR (devc); /* clear flags */ - clrFSR (devd); + + mtcio (select_code, ioCLF, 0); /* clear flags */ + mtcio (mtd_dib.devno, ioCLF, 0); + 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; + + case ioPOPIO: /* power-on preset to I/O */ + mtc_flag = mtc_flagbuf = CLEAR; /* clear flag and flag buffer */ + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + mtc_control = CLEAR; break; - case ioCRS: /* control reset (action unverif) */ - case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else { setCTL (devc); } /* STC */ + + case ioSTC: /* set control flip-flop */ + mtc_control = SET; break; - default: - break; - } -if (IR & I_HC) { clrFSR (devc); } /* H/C option */ -return dat; + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, mtc); /* set standard PRL signal */ + setstdIRQ (select_code, mtc); /* set standard IRQ signal */ + setstdSRQ (select_code, mtc); /* set standard SRQ signal */ + break; + + case ioIAK: /* interrupt acknowledge */ + mtc_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + mtcio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + mtcio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service If rewind done, reposition to start of tape, set status @@ -352,15 +455,12 @@ return dat; t_stat mtc_svc (UNIT *uptr) { -int32 devc, devd; t_mtrlnt tbc; t_stat st, r = SCPE_OK; -devc = mtc_dib.devno; /* get device nos */ -devd = mtd_dib.devno; if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */ mtc_sta = STA_LOCAL | STA_REJ; /* rejected */ - setFSR (devc); /* set cch flg */ + mtcio (mtc_dib.devno, ioENF, 0); /* set cch flg */ return IORETURN (mtc_stopioe, SCPE_UNATT); } @@ -414,9 +514,9 @@ switch (mtc_fnc) { /* case on function */ } } if (mtc_dtf && (mt_ptr < mt_max)) { /* more chars? */ - if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM; + if (mtd_flag) mtc_sta = mtc_sta | STA_TIM; mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */ - setFSR (devd); /* set dch flg */ + mtdio (mtd_dib.devno, ioENF, 0); /* set dch flg */ sim_activate (uptr, mtc_xtime); /* re-activate */ return SCPE_OK; } @@ -434,7 +534,7 @@ switch (mtc_fnc) { /* case on function */ else mtc_sta = mtc_sta | STA_PAR; } if (mtc_dtf) { /* xfer flop set? */ - setFSR (devd); /* set dch flag */ + mtdio (mtd_dib.devno, ioENF, 0); /* set dch flg */ sim_activate (uptr, mtc_xtime); /* re-activate */ return SCPE_OK; } @@ -452,7 +552,7 @@ switch (mtc_fnc) { /* case on function */ break; } -setFSR (devc); /* set cch flg */ +mtcio (mtc_dib.devno, ioENF, 0); /* set cch flg */ mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */ return r; } @@ -499,33 +599,57 @@ switch (st) { 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 */ -} +/* Controller clear */ -t_stat mtc_reset (DEVICE *dptr) +t_stat mt_clear (void) { -hp_enbdis_pair (&mtc_dev, &mtd_dev); /* make pair cons */ -mtc_fnc = 0; +t_stat st; + +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_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); -else mtc_sta = STA_LOCAL | STA_BUSY; +mtc_sta = mtc_sta & STA_BOT; + return SCPE_OK; } + +/* Reset routine */ + +t_stat mt_reset (DEVICE *dptr) +{ +hp_enbdis_pair (dptr, /* make pair cons */ + (dptr == &mtd_dev) ? &mtc_dev : &mtd_dev); + +if (dptr == &mtc_dev) /* command channel reset? */ + mtcio (mtc_dib.devno, ioPOPIO, 0); /* send POPIO signal to command channel */ +else /* data channel reset */ + mtdio (mtd_dib.devno, ioPOPIO, 0); /* send POPIO signal to data channel */ + +mtc_fnc = 0; +mtc_1st = mtc_dtf = 0; + +sim_cancel (&mtc_unit); /* cancel activity */ +sim_tape_reset (&mtc_unit); + +if (mtc_unit.flags & UNIT_ATT) + mtc_sta = (sim_tape_bot (&mtc_unit)? STA_BOT: 0) | + (sim_tape_wrp (&mtc_unit)? STA_WLK: 0); +else + mtc_sta = STA_LOCAL | STA_BUSY; + +return SCPE_OK; +} + + /* Attach routine */ t_stat mtc_attach (UNIT *uptr, char *cptr) diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c index 2ec6c537..ecd89e87 100644 --- a/HP2100/hp2100_mux.c +++ b/HP2100/hp2100_mux.c @@ -23,8 +23,15 @@ 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,MUXM 12920A terminal multiplexor + 25-Nov-08 JDB Revised for new multiplexer library SHOW routines + 09-Oct-08 JDB "muxl_unit" defined one too many units (17 instead of 16) + 10-Sep-08 JDB SHOW MUX CONN/STAT with SET MUX DIAG is no longer disallowed + 07-Sep-08 JDB Changed Telnet poll to connect immediately after reset or attach + 27-Aug-08 JDB Added LINEORDER support + 12-Aug-08 JDB Added BREAK deferral to allow RTE break-mode to work + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 16-Apr-08 JDB Sync mux poll with console poll for idle compatibility 06-Mar-07 JDB Corrected "mux_sta" size from 16 to 21 elements Fixed "muxc_reset" to clear lines 16-20 @@ -51,32 +58,107 @@ 01-Nov-02 RMS Added 7B/8B support 22-Aug-02 RMS Updated for changes to sim_tmxr - The 12920A consists of three separate devices - - mux scanner (upper data card) - muxl lines (lower data card) - muxm modem control (control card) - - The lower data card has no CMD flop; the control card has no CMD flop. - The upper data card has none of the usual flops. - Reference: - - 12920A Asynchronous Multiplexer Interface Kits Operating and Service - Manual (12920-90001, Oct-1972) + - 12920A Asynchronous Multiplexer Interface Kits Operating and Service Manual + (12920-90001, Oct-1972) + + + The 12920A was a 16-channel asynchronous terminal multiplexer. It supported + direct-connected terminals as well as modems at speeds up to 2400 baud. It + was the primary terminal multiplexer for the HP 2000 series of Time-Shared + BASIC systems. + + The multiplexer was implemented as a three-card set consisting of a lower + data card, an upper data card, and a modem control card. Under simulation, + these are implemented by three devices: + + MUXL lower data card (lines) + MUX upper data card (scanner) + MUXM control card (modem control) + + The lower and upper data cards must be in adjacent I/O slots. The control + card may be placed in any slot, although in practice it was placed in the + slot above the upper data card, so that all three cards were physically + together. + + The 12920A supported one or two control cards (two cards were used with + 801-type automatic dialers). Under simulation, only one control card is + supported. + + Implementation notes: + + 1. If a BREAK is detected during an input poll, and we are not in diagnostic + mode, we defer recognition until either a character is output or a second + successive input poll occurs. This is necessary for RTE break-mode + operation. Without this deferral, a BREAK during output would be ignored + by the RTE driver, making it impossible to stop a long listing. + + The problem is due to timing differences between simulated and real time. + The RTE multiplexer driver is a privileged driver. Privileged drivers + bypass RTE to provide rapid interrupt handling. To inform RTE that an + operation is complete, e.g., that a line has been written, the interrupt + section of the driver sets a device timeout of one clock tick (10 + milliseconds). When that timeout occurs, RTE is entered normally to + complete the I/O transaction. While the completion timeout is pending, + the driver ignores any further interrupts from the multiplexer line. + + The maximum communication rate for the multiplexer is 2400 baud, or + approximately 4.2 milliseconds per character transferred. A typical line + of 20 characters would therefore take ~85 milliseconds, plus the 10 + millisecond completion timeout, or about 95 milliseconds total. BREAK + recognition would be ignored for roughly 10% of that time. At lower baud + rates, recognition would be ignored for a correspondingly smaller + percentage of the time. + + However, SIMH uses an optimized timing of 500 instructions per character + transfer, rather than the ~6600 instructions that a character transfer + should take, and so a typical 20-character line will take about 11,000 + instructions. On the other hand, the clock tick is calibrated to real + time, and 10 milliseconds of real time takes about 420,000 instructions + on a 2.0 GHz PC. To be recognized, then, the BREAK key must be pressed + in a window that is open for about 2.5% of the time. Therefore, the + BREAK key will be ignored about 97.5% of the time, and RTE break-mode + effectively will not work. + + Deferring BREAK recognition until the next character is output ensures + that the BREAK interrupt will be accepted (the simulator delivers input + interrupts before output interrupts, so the BREAK interrupt arrives + before the output character transmit interrupt). If an output operation + is not in progress, then the BREAK will be recognized at the next input + poll. */ + +#include + #include "hp2100_defs.h" #include "sim_sock.h" #include "sim_tmxr.h" -#include -#define MUX_LINES 16 /* user lines */ -#define MUX_ILINES 5 /* diag rcv only */ + +/* Unit references */ + +#define MUX_LINES 16 /* number of user lines */ +#define MUX_ILINES 5 /* number of diag rcv only lines */ + + +/* Service times */ + +#define MUXL_WAIT 500 + + +/* Unit flags */ + #define UNIT_V_MDM (TTUF_V_UF + 0) /* modem control */ #define UNIT_V_DIAG (TTUF_V_UF + 1) /* loopback diagnostic */ #define UNIT_MDM (1 << UNIT_V_MDM) #define UNIT_DIAG (1 << UNIT_V_DIAG) -#define MUXL_WAIT 500 + +/* Debug flags */ + +#define DEB_CMDS (1 << 0) /* Command initiation and completion */ +#define DEB_CPU (1 << 1) /* CPU I/O */ +#define DEB_XFER (1 << 2) /* Socket receive and transmit */ /* Channel number (OTA upper, LIA lower or upper) */ @@ -152,55 +234,13 @@ #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) + ((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \ + << LIC_V_I) -/* Debug flags */ -#define DEB_CMDS (1 << 0) /* Command initiation and completion */ -#define DEB_CPU (1 << 1) /* CPU I/O */ -#define DEB_XFER (1 << 2) /* Socket receive and transmit */ +/* Program constants */ -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -extern FILE *sim_deb; - -uint16 mux_sta[MUX_LINES + MUX_ILINES]; /* line status */ -uint16 mux_rpar[MUX_LINES + MUX_ILINES]; /* rcv param */ -uint16 mux_xpar[MUX_LINES]; /* xmt param */ -uint16 mux_rbuf[MUX_LINES + MUX_ILINES]; /* rcv buf */ -uint16 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 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 */ - -DEVICE muxl_dev, muxu_dev, muxc_dev; -int32 muxlio (int32 inst, int32 IR, int32 dat); -int32 muxuio (int32 inst, int32 IR, int32 dat); -int32 muxcio (int32 inst, int32 IR, int32 dat); -t_stat muxi_svc (UNIT *uptr); -t_stat muxo_svc (UNIT *uptr); -t_stat muxc_reset (DEVICE *dptr); -t_stat mux_attach (UNIT *uptr, char *cptr); -t_stat mux_detach (UNIT *uptr); -t_stat mux_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void mux_data_int (void); -void mux_ctrl_int (void); -void mux_diag (int32 c); - -static uint8 odd_par[256] = { +static const 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, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 020-037 */ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 040-067 */ @@ -222,76 +262,97 @@ static uint8 odd_par[256] = { #define RCV_PAR(x) (odd_par[(x) & 0377] ? 0 : LIL_PAR) #define XMT_PAR(x) (odd_par[(x) & 0377] ? 0 : OTL_PAR) -/* Debug flags table */ -DEBTAB mux_deb[] = { - { "CMDS", DEB_CMDS }, - { "CPU", DEB_CPU }, - { "XFER", DEB_XFER }, - { NULL, 0 } }; +/* Multiplexer controller state variables */ + +FLIP_FLOP muxl_control = CLEAR; +FLIP_FLOP muxl_flag = CLEAR; +FLIP_FLOP muxl_flagbuf = CLEAR; + +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 */ + +FLIP_FLOP muxc_control = CLEAR; +FLIP_FLOP muxc_flag = CLEAR; +FLIP_FLOP muxc_flagbuf = CLEAR; + +uint32 muxc_chan = 0; /* ctrl chan */ +uint32 muxc_scan = 0; /* ctrl scan */ + + +/* Multiplexer per-line state variables */ + +uint16 mux_sta [MUX_LINES + MUX_ILINES]; /* line status */ +uint16 mux_rpar [MUX_LINES + MUX_ILINES]; /* rcv param */ +uint16 mux_xpar [MUX_LINES]; /* xmt param */ +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 */ +uint8 mux_defer [MUX_LINES]; /* break deferred flags */ + + +/* Multiplexer per-line buffer variables */ + +uint16 mux_rbuf[MUX_LINES + MUX_ILINES]; /* rcv buf */ +uint16 mux_xbuf[MUX_LINES]; /* xmt buf */ + + +/* Multiplexer local routines */ + +void mux_receive (int32 ln, int32 c, t_bool diag); +void mux_data_int (void); +void mux_ctrl_int (void); +void mux_diag (int32 c); + + +/* Multiplexer global routines */ + +uint32 muxlio (uint32 select_code, IOSIG signal, uint32 data); +uint32 muxuio (uint32 select_code, IOSIG signal, uint32 data); +uint32 muxcio (uint32 select_code, IOSIG signal, uint32 data); +t_stat muxi_svc (UNIT *uptr); +t_stat muxo_svc (UNIT *uptr); +t_stat muxc_reset (DEVICE *dptr); +t_stat mux_attach (UNIT *uptr, char *cptr); +t_stat mux_detach (UNIT *uptr); +t_stat mux_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc); + + +/* MUX data structures. + + mux_order MUX line connection order table + mux_ldsc MUX line descriptors + mux_desc MUX multiplexer descriptor +*/ + +int32 mux_order [MUX_LINES] = { -1 }; /* connection order */ +TMLN mux_ldsc [MUX_LINES] = { { 0 } }; /* line descriptors */ +TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc, mux_order }; /* device descriptor */ DIB mux_dib[] = { - { MUXL, 0, 0, 0, 0, 0, &muxlio }, - { MUXU, 0, 0, 0, 0, 0, &muxuio } + { MUXL, &muxlio }, + { MUXU, &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 -*/ +/* MUXL data structures. -UNIT muxu_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), POLL_WAIT }; - -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 } - }; - -MTAB muxu_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &mux_setdiag }, - { UNIT_DIAG, 0, "terminal mode", "TERM", &mux_setdiag }, - { 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 | DEV_DEBUG, - 0, mux_deb, NULL, NULL - }; - -/* MUXL data structures - - muxl_dev MUXL device descriptor - muxl_unit MUXL unit descriptor + muxl_dib MUXL device information block + muxl_unit MUXL unit list muxl_reg MUXL register list - muxl_mod MUXL modifiers list + muxl_mod MUXL modifier list + muxl_dev MUXL device descriptor */ +DEVICE muxl_dev; + UNIT muxl_unit[] = { { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, @@ -308,34 +369,13 @@ UNIT muxl_unit[] = { { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT } }; -MTAB muxl_mod[] = { - { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, - { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, - { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, - { TT_MODE, TT_MODE_7P, "7p", "7P", 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) }, + { FLDATA (CTL, muxl_control, 0) }, + { FLDATA (FLG, muxl_flag, 0) }, + { FLDATA (FBF, muxl_flagbuf, 0) }, { BRDATA (STA, mux_sta, 8, 16, MUX_LINES + MUX_ILINES) }, { BRDATA (RPAR, mux_rpar, 8, 16, MUX_LINES + MUX_ILINES) }, { BRDATA (XPAR, mux_xpar, 8, 16, MUX_LINES) }, @@ -343,38 +383,143 @@ REG muxl_reg[] = { { BRDATA (XBUF, mux_xbuf, 8, 16, MUX_LINES) }, { BRDATA (RCHP, mux_rchp, 8, 1, MUX_LINES + MUX_ILINES) }, { BRDATA (XDON, mux_xdon, 8, 1, MUX_LINES) }, + { BRDATA (BDFR, mux_defer, 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 +MTAB muxl_mod[] = { + { TT_MODE, TT_MODE_UC, "UC", "UC", NULL, NULL, NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL, NULL, NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL, NULL, NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL, NULL, NULL }, + + { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL, NULL, NULL }, + { UNIT_MDM, 0, "no dataset", "NODATASET", NULL, NULL, 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_VUN, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &mux_desc }, + { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &muxl_dev }, + + { 0 } }; -/* MUXM data structures +DEVICE muxl_dev = { + "MUXL", /* device name */ + muxl_unit, /* unit array */ + muxl_reg, /* register array */ + muxl_mod, /* modifier array */ + MUX_LINES, /* number of units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &muxc_reset, /* reset routine */ + NULL, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + &muxl_dib, /* device information block */ + DEV_DISABLE, /* device flags */ + 0, /* debug control flags */ + NULL, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ - muxc_dev MUXM device descriptor - muxc_unit MUXM unit descriptor - muxc_reg MUXM register list - muxc_mod MUXM modifiers list + +/* MUXU data structures + + muxu_dib MUXU device information block + muxu_unit MUXU unit list + muxu_reg MUXU register list + muxu_mod MUXU modifier list + muxu_deb MUXU debug list + muxu_dev MUXU device descriptor */ -DIB muxc_dib = { MUXC, 0, 0, 0, 0, 0, &muxcio }; +DEVICE muxu_dev; + +UNIT muxu_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), POLL_FIRST }; + +REG muxu_reg[] = { + { ORDATA (IBUF, muxu_ibuf, 16) }, + { ORDATA (OBUF, muxu_obuf, 16) }, + { ORDATA (DEVNO, muxu_dib.devno, 6), REG_HRO }, + { NULL } + }; + +MTAB muxu_mod[] = { + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &mux_setdiag, NULL, NULL }, + { UNIT_DIAG, 0, "terminal mode", "TERM", &mux_setdiag, NULL, NULL }, + { UNIT_ATT, UNIT_ATT, "", NULL, NULL, &tmxr_show_summ, &mux_desc }, + + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "LINEORDER", "LINEORDER", &tmxr_set_lnorder, &tmxr_show_lnorder, &mux_desc }, + + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, NULL, &tmxr_show_cstat, &mux_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &mux_desc }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &mux_desc }, + { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &muxl_dev }, + + { 0 } + }; + +DEBTAB muxu_deb [] = { + { "CMDS", DEB_CMDS }, + { "CPU", DEB_CPU }, + { "XFER", DEB_XFER }, + { NULL, 0 } + }; + +DEVICE muxu_dev = { + "MUX", /* device name */ + &muxu_unit, /* unit array */ + muxu_reg, /* register array */ + muxu_mod, /* modifier array */ + 1, /* number of units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 8, /* data width */ + &tmxr_ex, /* examine routine */ + &tmxr_dep, /* deposit routine */ + &muxc_reset, /* reset routine */ + NULL, /* boot routine */ + &mux_attach, /* attach routine */ + &mux_detach, /* detach routine */ + &muxu_dib, /* device information block */ + DEV_NET | DEV_DISABLE | DEV_DEBUG, /* device flags */ + 0, /* debug control flags */ + muxu_deb, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ + + +/* MUXC data structures. + + muxc_dib MUXC device information block + muxc_unit MUXC unit list + muxc_reg MUXC register list + muxc_mod MUXC modifier list + muxc_dev MUXC device descriptor +*/ + +DEVICE muxc_dev; + +DIB muxc_dib = { MUXC, &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 (CTL, muxc_control, 0) }, + { FLDATA (FLG, muxc_flag, 0) }, + { FLDATA (FBF, muxc_flagbuf, 0) }, { FLDATA (SCAN, muxc_scan, 0) }, { ORDATA (CHAN, muxc_chan, 4) }, { BRDATA (DSO, muxc_ota, 8, 6, MUX_LINES) }, @@ -384,78 +529,114 @@ REG muxc_reg[] = { }; MTAB muxc_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxc_dev }, + { 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 - }; + "MUXM", /* device name */ + &muxc_unit, /* unit array */ + muxc_reg, /* register array */ + muxc_mod, /* modifier array */ + 1, /* number of units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &muxc_reset, /* reset routine */ + NULL, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + &muxc_dib, /* device information block */ + DEV_DISABLE, /* device flags */ + 0, /* debug control flags */ + NULL, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ -/* I/O instructions: data cards - Implementation note: the operating manual says that "at least 100 - milliseconds of CLC 0s must be programmed" by systems employing the - multiplexer to ensure that the multiplexer resets. In practice, such systems - issue 128K CLC 0 instructions. As we provide debug logging of multiplexer - resets, a CRS counter is used to ensure that only one debug line is printed - in response to these 128K CRS invocations. +/* Lower data card I/O signal handler. + + Implementation notes: + + 1. The operating manual says that "at least 100 milliseconds of CLC 0s must + be programmed" by systems employing the multiplexer to ensure that the + multiplexer resets. In practice, such systems issue 128K CLC 0 + instructions. As we provide debug logging of multiplexer resets, a CRS + counter is used to ensure that only one debug line is printed in response + to these 128K CRS invocations. */ -int32 muxlio (int32 inst, int32 IR, int32 dat) +uint32 muxlio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev, ln; -t_bool is_crs; -static uint32 crs_count = 0; /* cntr for crs repeat */ +int32 ln; +const char *hold_or_clear = (signal > ioCLF ? ",C" : ""); +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +static uint32 crs_count = 0; /* cntr for ioCRS repeat */ -dev = IR & I_DEVMASK; /* get device no */ -is_crs = FALSE; +switch (base_signal) { /* dispatch base I/O signal */ -switch (inst) { /* case on opcode */ + case ioCLF: /* clear flag flip-flop */ + muxl_flag = muxl_flagbuf = CLEAR; - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fputs (">>MUXl cmds: [CLF] Flag cleared\n", sim_deb); + + mux_data_int (); /* look for new int */ break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + muxl_flag = muxl_flagbuf = SET; + + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fputs (">>MUXl cmds: [STF] Flag set\n", sim_deb); break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (muxl); break; - case ioOTX: /* output */ - muxl_obuf = dat; /* store data */ + + case ioSFS: /* skip if flag is set */ + setstdSKF (muxl); + break; + + + case ioIOI: /* I/O data input */ + data = muxl_ibuf; if (DEBUG_PRI (muxu_dev, DEB_CPU)) - if (dat & OTL_P) - fprintf (sim_deb, ">>MUXl OTx: Parameter = %06o\n", dat); + fprintf (sim_deb, ">>MUXl cpu: [LIx%s] Data = %06o\n", hold_or_clear, data); + break; + + + case ioIOO: /* I/O data output */ + muxl_obuf = data; /* store data */ + + if (DEBUG_PRI (muxu_dev, DEB_CPU)) + if (data & OTL_P) + fprintf (sim_deb, ">>MUXl cpu: [OTx%s] Parameter = %06o\n", hold_or_clear, data); else - fprintf (sim_deb, ">>MUXl OTx: Data = %06o\n", dat); + fprintf (sim_deb, ">>MUXl cpu: [OTx%s] Data = %06o\n", hold_or_clear, data); break; - case ioLIX: /* load */ - dat = 0; - case ioMIX: /* merge */ - dat = dat | muxl_ibuf; - - if (DEBUG_PRI (muxu_dev, DEB_CPU)) - fprintf (sim_deb, ">>MUXl LIx: Data = %06o\n", dat); - break; + case ioPOPIO: /* power-on preset to I/O */ + muxl_flag = muxl_flagbuf = SET; /* set flag andflag buffer */ + /* fall into CRS handler */ case ioCRS: /* control reset */ - is_crs = TRUE; - if (crs_count) /* already reset? */ break; /* skip redundant clear */ + muxl_control = CLEAR; /* clear control flip-flop */ + for (ln = 0; ln < MUX_LINES; ln++) { /* clear transmit info */ mux_xbuf[ln] = mux_xpar[ln] = 0; muxc_ota[ln] = muxc_lia[ln] = mux_xdon[ln] = 0; @@ -464,171 +645,239 @@ switch (inst) { /* case on opcode */ for (ln = 0; ln < (MUX_LINES + MUX_ILINES); ln++) { mux_rbuf[ln] = mux_rpar[ln] = 0; /* clear receive info */ mux_sta[ln] = mux_rchp[ln] = 0; - } /* fall into CLC SC */ - - case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (dev); - - if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, ">>MUXl CLC: Data interrupt inhibited\n"); } - else { /* STC */ - setCTL (dev); /* set ctl */ - ln = MUX_CHAN (muxu_obuf); /* get chan # */ + break; - if (muxl_obuf & OTL_TX) { /* transmit? */ - if (ln < MUX_LINES) { /* line valid? */ - if (muxl_obuf & OTL_P) { /* parameter? */ - mux_xpar[ln] = muxl_obuf; /* store param value */ + + case ioCLC: /* clear control flip-flop */ + muxl_control = CLEAR; + + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MUXl cmds: [CLC%s] Data interrupt inhibited\n", hold_or_clear); + break; + + + case ioSTC: /* set control flip-flop */ + muxl_control = SET; /* set control */ + + ln = MUX_CHAN (muxu_obuf); /* get chan # */ + + if (muxl_obuf & OTL_TX) { /* transmit? */ + if (ln < MUX_LINES) { /* line valid? */ + if (muxl_obuf & OTL_P) { /* parameter? */ + mux_xpar[ln] = muxl_obuf; /* store param value */ + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fprintf (sim_deb, + ">>MUXl cmds: [STC%s] Transmit channel %d parameter %06o stored\n", + hold_or_clear, ln, muxl_obuf); + } + + else { /* data */ + if (mux_xpar[ln] & OTL_TPAR) /* parity requested? */ + muxl_obuf = /* add parity bit */ + muxl_obuf & ~OTL_PAR | + XMT_PAR(muxl_obuf); + mux_xbuf[ln] = muxl_obuf; /* load buffer */ + + if (sim_is_active (&muxl_unit[ln])) { /* still working? */ + mux_sta[ln] = mux_sta[ln] | LIU_LOST; /* char lost */ if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, - ">>MUXl STC: Transmit channel %d parameter %06o stored\n", - ln, muxl_obuf); + fprintf (sim_deb, ">>MUXl cmds: [STC%s] Transmit channel %d data overrun\n", + hold_or_clear, ln); } - - else { /* data */ - if (mux_xpar[ln] & OTL_TPAR) /* parity requested? */ - muxl_obuf = /* add parity bit */ - muxl_obuf & ~OTL_PAR | - XMT_PAR(muxl_obuf); - mux_xbuf[ln] = muxl_obuf; /* load buffer */ - - if (sim_is_active (&muxl_unit[ln])) { /* still working? */ - mux_sta[ln] = mux_sta[ln] | LIU_LOST; /* char lost */ - if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, - ">>MUXl STC: Transmit channel %d data overrun\n", ln); - } - else { - if (muxu_unit.flags & UNIT_DIAG) /* loopback? */ - mux_ldsc[ln].conn = 1; /* connect this line */ - sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); - if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, - ">>MUXl STC: Transmit channel %d data %06o scheduled\n", - ln, muxl_obuf); - } + else { + if (muxu_unit.flags & UNIT_DIAG) /* loopback? */ + mux_ldsc[ln].conn = 1; /* connect this line */ + sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MUXl cmds: [STC%s] Transmit channel %d data %06o scheduled\n", + hold_or_clear, ln, muxl_obuf); } } - else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* line invalid */ - fprintf (sim_deb, ">>MUXl STC: Transmit channel %d invalid\n", ln); + } + else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* line invalid */ + fprintf (sim_deb, ">>MUXl cmds: [STC%s] Transmit channel %d invalid\n", hold_or_clear, ln); + } + + else /* receive */ + if (ln < (MUX_LINES + MUX_ILINES)) { /* line valid? */ + if (muxl_obuf & OTL_P) { /* parameter? */ + mux_rpar[ln] = muxl_obuf; /* store param value */ + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fprintf (sim_deb, + ">>MUXl cmds: [STC%s] Receive channel %d parameter %06o stored\n", + hold_or_clear, ln, muxl_obuf); + } + + else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* data (invalid action) */ + fprintf (sim_deb, + ">>MUXl cmds: [STC%s] Receive channel %d parameter %06o invalid action\n", + hold_or_clear, ln, muxl_obuf); } - else /* receive */ - if (ln < (MUX_LINES + MUX_ILINES)) { /* line valid? */ - if (muxl_obuf & OTL_P) { /* parameter? */ - mux_rpar[ln] = muxl_obuf; /* store param value */ - if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, - ">>MUXl STC: Receive channel %d parameter %06o stored\n", - ln, muxl_obuf); - } - - else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* data (invalid action) */ - fprintf (sim_deb, - ">>MUXl STC: Receive channel %d parameter %06o invalid action\n", - ln, muxl_obuf); - } - - else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* line invalid */ - fprintf (sim_deb, ">>MUXl STC: Receive channel %d invalid\n", ln); - } /* end STC */ + else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* line invalid */ + fprintf (sim_deb, ">>MUXl cmds: [STC%s] Receive channel %d invalid\n", hold_or_clear, ln); break; - default: - break; - } -if (is_crs) /* control reset? */ + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, muxl); /* set standard PRL signal */ + setstdIRQ (select_code, muxl); /* set standard IRQ signal */ + setstdSRQ (select_code, muxl); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + muxl_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + muxlio (select_code, ioCLF, 0); /* issue CLF */ + +else if (signal > ioSIR) /* signal affected interrupt status? */ + muxlio (select_code, ioSIR, 0); /* set interrupt request */ + + +if (signal == ioCRS) /* control reset? */ crs_count = crs_count + 1; /* increment count */ -else if (crs_count) { /* something else */ +else if (crs_count && (signal != ioSIR)) { /* counting CRSes? */ if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* report reset count */ - fprintf (sim_deb, - ">>MUXl CRS: Multiplexer reset %d times\n", crs_count); + fprintf (sim_deb, ">>MUXl cmds: [CRS] Multiplexer reset %d times\n", + crs_count); crs_count = 0; /* clear counter */ } -if (IR & I_HC) { /* H/C option */ - clrFSR (dev); /* clear flag */ - mux_data_int (); /* look for new int */ - } -return dat; +return data; } -int32 muxuio (int32 inst, int32 IR, int32 dat) + +/* Upper data card I/O signal handler. + + The upper data card does not have a control, flag, or flag buffer flip-flop. + It does not drive the IRQ or SRQ lines, so the I/O dispatcher does not handle + the ioSIR signal. + + Implementation notes: + + 1. The upper and lower data card hardware takes a number of actions in + response to the CRS signal. Under simulation, these actions are taken by + the lower data card CRS handler. +*/ + +uint32 muxuio (uint32 select_code, IOSIG signal, uint32 data) { -switch (inst) { /* case on opcode */ +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ - case ioOTX: /* output */ - muxu_obuf = dat; /* store data */ +switch (base_signal) { /* dispatch base I/O signal */ + + case ioIOI: /* I/O data input */ + data = muxu_ibuf; if (DEBUG_PRI (muxu_dev, DEB_CPU)) - fprintf (sim_deb, ">>MUXu OTx: Data channel = %d\n", MUX_CHAN(dat)); + fprintf (sim_deb, ">>MUXu cpu: [LIx] Status = %06o, channel = %d\n", + data, MUX_CHAN(data)); break; - case ioLIX: /* load */ - dat = 0; - case ioMIX: /* merge */ - dat = dat | muxu_ibuf; + case ioIOO: /* I/O data output */ + muxu_obuf = data; /* store data */ if (DEBUG_PRI (muxu_dev, DEB_CPU)) - fprintf (sim_deb, ">>MUXu LIx: Status = %06o, channel = %d\n", dat, MUX_CHAN(dat)); + fprintf (sim_deb, ">>MUXu cpu: [OTx] Data channel = %d\n", MUX_CHAN(data)); break; - default: - break; + + default: /* all other signals */ + break; /* are ignored */ } -return dat; +return data; } -/* I/O instructions: control card + +/* Control card I/O signal handler. In diagnostic mode, the control signals C1 and C2 are looped back to status signals S1 and S2. Changing the control signals may cause an interrupt, so a - test is performed after OTx processing. + test is performed after IOO processing. */ -int32 muxcio (int32 inst, int32 IR, int32 dat) +uint32 muxcio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev, ln, t, old; +const char *hold_or_clear = (signal > ioCLF ? ",C" : ""); +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ +int32 ln, old; -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + muxc_flag = muxc_flagbuf = CLEAR; + + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fputs (">>MUXc cmds: [CLF] Flag cleared\n", sim_deb); + + mux_ctrl_int (); /* look for new int */ break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + muxc_flag = muxc_flagbuf = SET; + + if (DEBUG_PRI (muxu_dev, DEB_CMDS)) + fputs (">>MUXc cmds: [STF] Flag set\n", sim_deb); break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (muxc); break; - case ioOTX: /* output */ - ln = muxc_chan = OTC_CHAN (dat); /* set channel */ - if (dat & OTC_SCAN) muxc_scan = 1; /* set scan flag */ + case ioSFS: /* skip if flag is set */ + setstdSKF (muxc); + break; + + + case ioIOI: /* I/O data input */ + data = 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 */ + + if (DEBUG_PRI (muxu_dev, DEB_CPU)) + fprintf (sim_deb, ">>MUXc cpu: [LIx%s] Status = %06o, channel = %d\n", + hold_or_clear, data, muxc_chan); + + muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */ + break; + + + case ioIOO: /* I/O data output */ + ln = muxc_chan = OTC_CHAN (data); /* set channel */ + + if (data & OTC_SCAN) muxc_scan = 1; /* set scan flag */ else muxc_scan = 0; - if (dat & OTC_UPD) { /* update? */ + if (data & OTC_UPD) { /* update? */ old = muxc_ota[ln]; /* save prior val */ muxc_ota[ln] = /* save ESn,SSn */ - (muxc_ota[ln] & ~OTC_RW) | (dat & OTC_RW); + (muxc_ota[ln] & ~OTC_RW) | (data & OTC_RW); - if (dat & OTC_EC2) /* if EC2, upd C2 */ + if (data & OTC_EC2) /* if EC2, upd C2 */ muxc_ota[ln] = - (muxc_ota[ln] & ~OTC_C2) | (dat & OTC_C2); + (muxc_ota[ln] & ~OTC_C2) | (data & OTC_C2); - if (dat & OTC_EC1) /* if EC1, upd C1 */ + if (data & OTC_EC1) /* if EC1, upd C1 */ muxc_ota[ln] = - (muxc_ota[ln] & ~OTC_C1) | (dat & OTC_C1); + (muxc_ota[ln] & ~OTC_C1) | (data & OTC_C1); if (muxu_unit.flags & UNIT_DIAG) /* loopback? */ muxc_lia[ln ^ 1] = /* set S1, S2 to C1, C2 */ @@ -639,54 +888,63 @@ switch (inst) { /* case on opcode */ (old & DTR) && /* DTR drop? */ !(muxc_ota[ln] & DTR)) { tmxr_linemsg (&mux_ldsc[ln], "\r\nLine hangup\r\n"); - tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ - muxc_lia[ln] = 0; /* dataset off */ + tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ + muxc_lia[ln] = 0; /* dataset off */ } - } /* end update */ + } /* end update */ if (DEBUG_PRI (muxu_dev, DEB_CPU)) - fprintf (sim_deb, ">>MUXc OTx: Parameter = %06o, channel = %d\n", - dat, ln); + fprintf (sim_deb, ">>MUXc cpu: [OTx%s] Parameter = %06o, channel = %d\n", + hold_or_clear, data, ln); - if ((muxu_unit.flags & UNIT_DIAG) && /* loopback? */ - (!FLG(muxc_dib.devno))) /* flag clear? */ - mux_ctrl_int (); /* status chg may interrupt */ + if ((muxu_unit.flags & UNIT_DIAG) && (!muxc_flag)) /* loopback and flag clear? */ + mux_ctrl_int (); /* status chg may interrupt */ 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 */ - - if (DEBUG_PRI (muxu_dev, DEB_CPU)) - fprintf (sim_deb, ">>MUXc LIx: Status = %06o, channel = %d\n", - dat, muxc_chan); - - muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */ - break; + case ioPOPIO: /* power-on preset to I/O */ + muxc_flag = muxc_flagbuf = SET; /* set flag and flag buffer */ + /* fall into CRS handler */ case ioCRS: /* control reset */ - case ioCTL: /* ctrl clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { setCTL (dev); } /* STC */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + muxc_control = CLEAR; break; - default: + + case ioSTC: /* set control flip-flop */ + muxc_control = SET; break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, muxc); /* set standard PRL signal */ + setstdIRQ (select_code, muxc); /* set standard IRQ signal */ + setstdSRQ (select_code, muxc); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + muxc_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ } -if (IR & I_HC) { /* H/C option */ - clrFSR (dev); /* clear flag */ - mux_ctrl_int (); /* look for new int */ - } -return dat; + +if (signal > ioCLF) /* multiple signals? */ + muxcio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + muxcio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service - receive side Poll for new connections @@ -702,9 +960,16 @@ loopback = ((muxu_unit.flags & UNIT_DIAG) != 0); /* diagnostic mode? */ if (!loopback) { /* terminal mode? */ if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ - muxu_unit.wait = sync_poll (SERVICE); /* synchronize poll */ - sim_activate (uptr, muxu_unit.wait); /* continue poll */ + + if (uptr->wait == POLL_FIRST) /* first poll? */ + uptr->wait = sync_poll (INITIAL); /* initial synchronization */ + else /* not first */ + uptr->wait = sync_poll (SERVICE); /* continue synchronization */ + + sim_activate (uptr, uptr->wait); /* continue polling */ + 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? */ @@ -713,7 +978,7 @@ if (!loopback) { /* terminal mode? */ 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? */ @@ -724,48 +989,27 @@ for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */ mux_ldsc[ln].conn = 0; /* clear connection */ } + else if (mux_defer[ln]) /* break deferred? */ + c = SCPE_BREAK; /* supply it now */ + else c = tmxr_getc_ln (&mux_ldsc[ln]); /* get char from Telnet */ - if (c) { /* valid 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]) /* char already pending? */ - mux_sta[ln] = mux_sta[ln] | LIU_LOST; - - if (!loopback) { /* terminal mode? */ - c = sim_tt_inpcvt (c, TT_GET_MODE (muxl_unit[ln].flags)); - 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 (DEBUG_PRI (muxu_dev, DEB_XFER)) - fprintf (sim_deb, ">>MUXi svc: Line %d character %06o received\n", - ln, c); - - if (mux_rpar[ln] & OTL_DIAG) mux_diag (c); /* rcv diag? */ - } /* end if char */ - } /* end if connected */ + if (c) /* valid char? */ + mux_receive (ln, c, loopback); /* process it */ + } else /* not connected */ if (!loopback) /* terminal mode? */ muxc_lia[ln] = 0; /* line 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 (!muxl_flag) mux_data_int (); /* scan for data int */ +if (!muxc_flag) mux_ctrl_int (); /* scan modem */ return SCPE_OK; } + /* Unit service - transmit side */ t_stat muxo_svc (UNIT *uptr) @@ -786,6 +1030,9 @@ if (mux_ldsc[ln].conn) { /* connected? */ if (loopback) /* diagnostic mode? */ mux_ldsc[ln].conn = 0; /* clear connection */ + else if (mux_defer[ln]) /* break deferred? */ + mux_receive (ln, SCPE_BREAK, loopback); /* process it now */ + if ((mux_xbuf[ln] & OTL_SYNC) == 0) { /* start bit 0? */ TMLN *lp = &mux_ldsc[ln]; /* get line */ c = sim_tt_outcvt (c, TT_GET_MODE (muxl_unit[ln].flags)); @@ -808,8 +1055,8 @@ if (mux_ldsc[ln].conn) { /* connected? */ mux_xdon[ln] = 1; /* set for xmit irq */ if (DEBUG_PRI (muxu_dev, DEB_XFER) && (loopback | (c >= 0))) - fprintf (sim_deb, ">>MUXo svc: Line %d character %06o sent\n", - ln, (loopback ? fc : c)); + fprintf (sim_deb, ">>MUXl xfer: Line %d character %s sent\n", + ln, fmt_char ((uint8) (loopback ? fc : c))); } else { /* buf full */ @@ -819,10 +1066,65 @@ if (mux_ldsc[ln].conn) { /* connected? */ } } -if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for int */ +if (!muxl_flag) mux_data_int (); /* scan for int */ return SCPE_OK; } + +/* Process a character received from a multiplexer port */ + +void mux_receive (int32 ln, int32 c, t_bool diag) +{ +if (c & SCPE_BREAK) { /* break? */ + if (mux_defer[ln] || diag) { /* break deferred or diagnostic mode? */ + mux_defer[ln] = 0; /* process now */ + mux_rbuf[ln] = 0; /* break returns NUL */ + mux_sta[ln] = mux_sta[ln] | LIU_BRK; /* set break status */ + + if (DEBUG_PRI (muxu_dev, DEB_XFER)) + if (diag) + fputs (">>MUXl xfer: Break detected\n", sim_deb); + else + fputs (">>MUXl xfer: Deferred break processed\n", sim_deb); + } + + else { + mux_defer[ln] = 1; /* defer break */ + + if (DEBUG_PRI (muxu_dev, DEB_XFER)) + fputs (">>MUXl xfer: Break detected and deferred\n", sim_deb); + + return; + } + } +else { /* normal */ + if (mux_rchp[ln]) /* char already pending? */ + mux_sta[ln] = mux_sta[ln] | LIU_LOST; + + if (!diag) { /* terminal mode? */ + c = sim_tt_inpcvt (c, TT_GET_MODE (muxl_unit[ln].flags)); + 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 (DEBUG_PRI (muxu_dev, DEB_XFER)) + fprintf (sim_deb, ">>MUXl xfer: Line %d character %s received\n", + ln, fmt_char ((uint8) c)); + +if (mux_rpar[ln] & OTL_DIAG) /* diagnose this line? */ + mux_diag (c); /* do diagnosis */ + +return; +} + + /* Look for data interrupt */ void mux_data_int (void) @@ -839,9 +1141,9 @@ for (i = 0; i < MUX_LINES; i++) { /* rcv lines */ mux_sta[i] = 0; if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, ">>MUXd irq: Receive channel %d interrupt requested\n", i); + fprintf (sim_deb, ">>MUXl cmds: Receive channel %d interrupt requested\n", i); - setFSR (muxl_dib.devno); /* interrupt */ + muxlio (muxl_dib.devno, ioENF, 0); /* interrupt */ return; } } @@ -855,31 +1157,32 @@ for (i = 0; i < MUX_LINES; i++) { /* xmt lines */ mux_sta[i] = 0; if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, ">>MUXd irq: Transmit channel %d interrupt requested\n", i); + fprintf (sim_deb, ">>MUXl cmds: Transmit channel %d interrupt requested\n", i); - setFSR (muxl_dib.devno); /* interrupt */ + muxlio (muxl_dib.devno, ioENF, 0); /* 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_DCH (i) | /* lo buf = char */ +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_DCH (i) | /* lo buf = char */ mux_rbuf[i] & LIL_CHAR | RCV_PAR (mux_rbuf[i]); - muxu_ibuf = PUT_DCH (i) | mux_sta[i] | LIU_DG; /* hi buf = stat */ - mux_rchp[i] = 0; /* clr char, stat */ + muxu_ibuf = PUT_DCH (i) | mux_sta[i] | LIU_DG; /* hi buf = stat */ + mux_rchp[i] = 0; /* clr char, stat */ mux_sta[i] = 0; if (DEBUG_PRI (muxu_dev, DEB_CMDS)) - fprintf (sim_deb, ">>MUXd irq: Receive channel %d interrupt requested\n", i); + fprintf (sim_deb, ">>MUXl cmds: Receive channel %d interrupt requested\n", i); - setFSR (muxl_dib.devno); + muxlio (muxl_dib.devno, ioENF, 0); /* interrupt */ return; } } return; } + /* Look for control interrupt If either of the incoming status bits does not match the stored status, and @@ -902,16 +1205,17 @@ for (i = 0; i < line_count; i++) { if (DEBUG_PRI (muxu_dev, DEB_CMDS)) fprintf (sim_deb, - ">>MUXc irq: Control channel %d interrupt requested (poll = %d)\n", + ">>MUXc cmds: Control channel %d interrupt requested (poll = %d)\n", muxc_chan, i + 1); - setFSR (muxc_dib.devno); /* set flag */ + muxcio (muxc_dib.devno, ioENF, 0); /* set flag */ break; } } return; } + /* Set diagnostic lines for given character */ void mux_diag (int32 c) @@ -932,6 +1236,7 @@ for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { return; } + /* Reset an individual line */ void mux_reset_ln (int32 i) @@ -939,7 +1244,7 @@ void mux_reset_ln (int32 i) mux_rbuf[i] = mux_xbuf[i] = 0; /* clear state */ mux_rpar[i] = mux_xpar[i] = 0; mux_rchp[i] = mux_xdon[i] = 0; -mux_sta[i] = 0; +mux_sta[i] = mux_defer[i] = 0; muxc_ota[i] = muxc_lia[i] = 0; /* clear modem */ if (mux_ldsc[i].conn && /* connected? */ ((muxu_unit.flags & UNIT_DIAG) == 0)) /* term mode? */ @@ -949,7 +1254,8 @@ sim_cancel (&muxl_unit[i]); return; } -/* Reset routine */ + +/* Reset routine for lower data, upper data, and control cards */ t_stat muxc_reset (DEVICE *dptr) { @@ -967,42 +1273,53 @@ 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 */ -muxc_dib.flg = muxc_dib.fbf = muxc_dib.srq = 1; + +if (dptr == &muxl_dev) /* lower data reset? */ + muxlio (muxl_dib.devno, ioPOPIO, 0); /* send POPIO signal to lower data card */ +else if (dptr == &muxu_dev) /* upper data reset? */ + muxuio (muxu_dib.devno, ioPOPIO, 0); /* send POPIO signal to upper data card */ +else /* control card reset */ + muxcio (muxc_dib.devno, ioPOPIO, 0); /* send POPIO signal to control card */ + muxc_chan = muxc_scan = 0; /* init modem scan */ + if (muxu_unit.flags & UNIT_ATT) { /* master att? */ - if (!sim_is_active (&muxu_unit)) { - muxu_unit.wait = sync_poll (INITIAL); /* synchronize poll */ - sim_activate (&muxu_unit, muxu_unit.wait); /* activate */ - } + muxu_unit.wait = POLL_FIRST; /* set up poll */ + sim_activate (&muxu_unit, muxu_unit.wait); /* start Telnet poll immediately */ } -else sim_cancel (&muxu_unit); /* else stop */ -for (i = 0; i < MUX_LINES; i++) mux_reset_ln (i); /* reset lines 0-15 */ +else + sim_cancel (&muxu_unit); /* else stop */ + +for (i = 0; i < MUX_LINES; i++) + mux_reset_ln (i); /* reset lines 0-15 */ + for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) /* reset lines 16-20 */ mux_rbuf[i] = mux_rpar[i] = mux_sta[i] = mux_rchp[i] = 0; + return SCPE_OK; } + /* Attach master unit */ t_stat mux_attach (UNIT *uptr, char *cptr) { -t_stat r; +t_stat status = SCPE_OK; if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */ return SCPE_NOFNC; /* command not allowed */ -r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -muxu_unit.wait = sync_poll (INITIAL); /* synchronize poll */ -sim_activate (uptr, muxu_unit.wait); /* start poll */ +status = tmxr_attach (&mux_desc, uptr, cptr); /* attach */ + +if (status == SCPE_OK) { + muxu_unit.wait = POLL_FIRST; /* set up poll */ + sim_activate (&muxu_unit, muxu_unit.wait); /* start Telnet poll immediately */ + } + return SCPE_OK; } + /* Detach master unit */ t_stat mux_detach (UNIT *uptr) @@ -1016,7 +1333,8 @@ sim_cancel (uptr); /* stop poll */ return r; } -/* Diagnostic/normal mode routine + +/* Diagnostic/normal mode routine, Diagnostic testing wants to exercise as much of the regular simulation code as possible to ensure good test coverage. Normally, input polling and output @@ -1050,40 +1368,3 @@ else { /* set term */ } return SCPE_OK; } - -/* Show summary processor */ - -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */ - return SCPE_NOFNC; /* command not allowed */ - -for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */ - return SCPE_NOFNC; /* command not allowed */ - -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_pif.c b/HP2100/hp2100_pif.c new file mode 100644 index 00000000..6ce98a00 --- /dev/null +++ b/HP2100/hp2100_pif.c @@ -0,0 +1,367 @@ +/* hp2100_pif.c: HP 12620A/12936A privileged interrupt fence simulator + + Copyright (c) 2008, J. David Bryan + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of the author shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from the author. + + PIF 12620A/12936A privileged interrupt fence + + 26-Jun-08 JDB Rewrote device I/O to model backplane signals + 18-Jun-08 JDB Created PIF device + + References: + - 12620A Breadboard Interface Kit Operating and Service Manual + (12620-90001, May-1978) + - 12936A Privileged Interrupt Fence Accessory Installation and Service Manual + (12936-90001, Mar-1974) + + + The Privileged Interupt Fence (PIF) was used in DOS and RTE systems to + provide privileged interrupt capability. In non-privileged systems, DOS and + RTE vectored all interrupts though the Central Interrupt Control (CIC) + routine. Within CIC, the interrupt system was turned off, the interrupt was + categorized, the associated driver was identified and mapped into logical + memory (if necessary), and the driver entered to handle the device service. + When the driver exited, the interrupt system was turned on before returning + to the point of interruption in the user's program. In addition, the DOS and + RTE operating systems themselves executed with the interrupt system off, as + they were not reentrant. + + This process proved too lengthy for certain devices, which would lose + interrupts or be forced to limit I/O speeds as a result. To allow faster + service, a driver could be written as a "privileged" driver and generated + into a privileged system. A privileged system operated with the interrupt + system on when handling unprivileged device interrupts or executing within + the operating system. The PIF card was installed in the I/O backplane to + separate privileged from unprivileged devices by controlling the interrupt + priority chain signal (PRL) to lower-priority devices. The privileged cards + located below the fence were allowed to interrupt the service routines of the + unprivileged cards that were located above the fence. + + When an unprivileged device interrupted, CIC would be entered as usual, and + the interrupt system would be turned off. However, after the system state + was saved, the PIF would be configured to break the priority chain (deny + PRL), so that subsequent interrupts from all unprivileged devices would be + deferred. Then the interrupt system would be turned on before normal CIC + processing continued. Interrupts from additional unprivileged devices would + be held off by the PIF until the driver completed and CIC returned, just as + in a non-privileged system. + + However, if a privileged device interrupted, the interrupt would be allowed, + because the interrupt system was on, and the priority chain was intact for + the devices below the fence. A privileged device bypassed CIC and entered + the associated device driver directly, and this would occur even if an + unprivileged device driver or the operating system itself were executing. + This provided very fast interrupt service time. + + HP produced two PIF cards: the 12936A Privileged Interrupt Fence Accessory + for DOS, and the 12620A Breadboard Interface for RTE. They behaved quite + differently and were not interchangeable. + + The 12620A had the standard control and flag circuitry. It behaved as most + cards did; setting control and flag together lowered PRL and generated an + interrupt. The control and flag flip-flops were set and cleared with STC/CLC + and STF/CLF instructions. The SFS/SFC instructions could be used to test the + flag state. + + The 12936A had a unique behavior. Setting either control or flag lowered + PRL. An interrupt occurred when flag was set and control was clear. The + control flip-flop was controlled with STC/CLC. The flag flip-flop was set + with OTA/B and cleared with CLF. SFC and SFS were not implemented and never + skipped. +*/ + + +#include "hp2100_defs.h" + + +/* Device flags */ + +#define DEV_V_12936 (DEV_V_UF + 0) /* 12936A card */ + +#define DEV_12936 (1 << DEV_V_12936) + + +/* PIF state variables */ + +FLIP_FLOP pif_control = CLEAR; /* control flip-flop */ +FLIP_FLOP pif_flag = CLEAR; /* flag flip-flop */ +FLIP_FLOP pif_flagbuf = CLEAR; /* flag buffer flip-flop */ + + +/* PIF global routines */ + +uint32 pif_io (uint32 select_code, IOSIG signal, uint32 data); + +t_stat pif_reset (DEVICE *dptr); +t_stat pif_set_card (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat pif_show_card (FILE *st, UNIT *uptr, int32 val, void *desc); + + +/* PIF data structures. + + pif_dib PIF device information block + pif_unit PIF unit list + pif_reg PIF register list + pif_mod PIF modifier list + pif_deb PIF debug list + pif_dev PIF device descriptor + + Implementation note: + + 1. The SIMH developer's manual says that a device's unit list may be NULL. + However, if this is done, the register state cannot be examined or + altered via SCP. To work around this problem, we define a dummy unit + that is not used otherwise. +*/ + +DEVICE pif_dev; + +DIB pif_dib = { PIF, &pif_io }; + +UNIT pif_unit = { + UDATA (NULL, 0, 0) /* dummy unit */ + }; + +REG pif_reg [] = { + { FLDATA (CTL, pif_control, 0) }, + { FLDATA (FLG, pif_flag, 0) }, + { FLDATA (FBF, pif_flagbuf, 0) }, + { ORDATA (DEVNO, pif_dib.devno, 6), REG_HRO }, + { NULL } + }; + +MTAB pif_mod [] = { + { MTAB_XTD | MTAB_VDV, 0, NULL, "12620A", &pif_set_card, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "12936A", &pif_set_card, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, NULL, &pif_show_card, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &pif_dev }, + + { 0 } + }; + +DEVICE pif_dev = { + "PIF", /* device name */ + &pif_unit, /* unit array */ + pif_reg, /* register array */ + pif_mod, /* modifier array */ + 1, /* number of units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* address increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &pif_reset, /* reset routine */ + NULL, /* boot routine */ + NULL, /* attach routine */ + NULL, /* detach routine */ + &pif_dib, /* device information block */ + DEV_DEBUG | DEV_DISABLE, /* device flags */ + 0, /* debug control flags */ + NULL, /* debug flag name table */ + NULL, /* memory size change routine */ + NULL }; /* logical device name */ + + + +/* I/O signal handler. + + Operation of the 12620A and the 12936A is different. The I/O responses of + the two cards are summarized below: + + Signal 12620A Action 12936A Action + ------ -------------------- -------------------- + POPIO Set FBF, FLG Clear FBF, FLG + CRS Clear CTL Clear CTL + CLC Clear CTL Clear CTL + STC Set CTL Set CTL + CLF Clear FBF, FLG Clear FBF, FLG + STF Set FBF, FLG none + SFC Skip if FLG clear none + SFS Skip if FLG set none + IOI none none + IOO none Set FBF, FLG + PRL ~(CTL * FLG) ~(CTL + FLG) + IRQ CTL * FLG * FBF ~CTL * FLG * FBF + IAK Clear FBF Clear FBF + SRQ Follows FLG Not driven + + Note that PRL and IRQ are non-standard for the 12936A. +*/ + +uint32 pif_io (uint32 select_code, IOSIG signal, uint32 data) +{ +const char *hold_or_clear = (signal > ioCLF ? ",C" : ""); +const t_bool is_rte_pif = (pif_dev.flags & DEV_12936) == 0; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ + +switch (base_signal) { /* dispatch base I/O signal */ + + case ioCLF: /* clear flag flip-flop */ + pif_flag = pif_flagbuf = CLEAR; /* clear flag buffer and flag */ + + if (DEBUG_PRS (pif_dev)) + fputs (">>PIF: [CLF] Flag cleared\n", sim_deb); + break; + + + case ioSTF: /* set flag flip-flop */ + if (is_rte_pif) { /* RTE PIF? */ + pif_flag = pif_flagbuf = SET; /* set flag buffer and flag */ + + if (DEBUG_PRS (pif_dev)) + fputs (">>PIF: [STF] Flag set\n", sim_deb); + } + break; + + + case ioSFC: /* skip if flag is clear */ + if (is_rte_pif) /* RTE PIF? */ + setstdSKF (pif); /* card responds to SFC */ + break; + + + case ioSFS: /* skip if flag is set */ + if (is_rte_pif) /* RTE PIF? */ + setstdSKF (pif); /* card responds to SFS */ + break; + + + case ioIOO: /* I/O data output */ + if (!is_rte_pif) { /* DOS PIF? */ + pif_flag = pif_flagbuf = SET; /* set flag buffer and flag */ + pif_io (select_code, ioSIR, 0); /* set IRQ (not normally done for IOO) */ + + if (DEBUG_PRS (pif_dev)) + fprintf (sim_deb, ">>PIF: [OTx%s] Flag set\n", hold_or_clear); + } + break; + + + case ioPOPIO: /* power-on preset to I/O */ + pif_flag = pif_flagbuf = /* set or clear flag and flag buffer */ + (is_rte_pif ? SET : CLEAR); + + if (DEBUG_PRS (pif_dev)) + fprintf (sim_deb, ">>PIF: [POPIO] Flag %s\n", + (is_rte_pif ? "set" : "cleared")); + /* fall into CRS handler */ + + case ioCRS: /* control reset */ + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + pif_control = CLEAR; /* clear control */ + + if (DEBUG_PRS (pif_dev)) + fprintf (sim_deb, ">>PIF: [%s%s] Control cleared\n", + (signal == ioCRS ? "CRS" : "CLC"), hold_or_clear); + break; + + + case ioSTC: /* set control flip-flop */ + pif_control = SET; /* set control */ + + if (DEBUG_PRS (pif_dev)) + fprintf (sim_deb, ">>PIF: [STC%s] Control set\n", hold_or_clear); + break; + + + case ioSIR: /* set interrupt request */ + if (is_rte_pif) { /* RTE PIF? */ + setstdPRL (select_code, pif); /* set standard PRL signal */ + setstdIRQ (select_code, pif); /* set standard IRQ signal */ + setstdSRQ (select_code, pif); /* set standard SRQ signal */ + } + + else { /* DOS PIF */ + setPRL (select_code, !(pif_control | pif_flag)); + setIRQ (select_code, !pif_control & pif_flag & pif_flagbuf); + } + + if (DEBUG_PRS (pif_dev)) + fprintf (sim_deb, ">>PIF: [SIR] PRL = %d, IRQ = %d\n", + PRL (select_code), IRQ (select_code)); + break; + + + case ioIAK: /* interrupt acknowledge */ + pif_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + pif_io (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + pif_io (select_code, ioSIR, 0); /* set interrupt request */ + +return data; +} + + +/* Simulator reset routine */ + +t_stat pif_reset (DEVICE *dptr) +{ +pif_io (pif_dib.devno, ioPOPIO, 0); /* send POPIO signal */ +return SCPE_OK; +} + + +/* Set card type. + + val == 0 --> set to 12936A (DOS PIF) + val == 1 --> set to 12620A (RTE PIF) +*/ + +t_stat pif_set_card (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if ((val < 0) || (val > 1) || (cptr != NULL)) /* sanity check */ + return SCPE_ARG; /* bad argument */ + +if (val) /* DOS PIF selected? */ + pif_dev.flags = pif_dev.flags | DEV_12936; /* set to 12936A */ +else /* RTE PIF selected */ + pif_dev.flags = pif_dev.flags & ~DEV_12936; /* set to 12620A */ + +return SCPE_OK; +} + + +/* Show card type */ + +t_stat pif_show_card (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +if (pif_dev.flags & DEV_12936) + fputs ("12936A", st); +else + fputs ("12620A", st); + +return SCPE_OK; +} diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c index 8923943c..5389bdf2 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -23,11 +23,12 @@ 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 + 26-Jun-08 JDB Rewrote device I/O to model backplane signals 25-Apr-08 JDB Changed TTY output wait from 100 to 200 for MSU BASIC 18-Apr-08 JDB Removed redundant control char handling definitions 14-Apr-08 JDB Changed TTY console poll to 10 msec. real time @@ -67,6 +68,16 @@ Added status input for ptp, tty 15-Oct-00 RMS Added dynamic device number support + References: + - 2748B Tape Reader Operating and Service Manual (02748-90041, Oct-1977) + - 12597A 8-Bit Duplex Register Interface Kit Operating and Service Manual + (12597-9002, Sep-1974) + - 12531C Buffered Teleprinter Interface Kit Operating and Service Manual + (12531-90033, Nov-1972) + - 12539C Time Base Generator Interface Kit Operating and Service Manual + (12539-90008, Jan-1975) + + The reader and punch, like most HP devices, have a command flop. The teleprinter and clock do not. @@ -93,15 +104,6 @@ This turns off autocalibration and divides the longest time intervals down by 10**3. The clk_time values were chosen to allow the diagnostic to pass its clock calibration test. - - References: - - 2748B Tape Reader Operating and Service Manual (02748-90041, Oct-1977) - - 12597A 8-Bit Duplex Register Interface Kit Operating and Service Manual - (12597-9002, Sep-1974) - - 12531C Buffered Teleprinter Interface Kit Operating and Service Manual - (12531-90033, Nov-1972) - - 12539C Time Base Generator Interface Kit Operating and Service Manual - (12539-90008, Jan-1975) */ #include "hp2100_defs.h" @@ -123,18 +125,34 @@ #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]; +FLIP_FLOP ptr_control = CLEAR; +FLIP_FLOP ptr_flag = CLEAR; +FLIP_FLOP ptr_flagbuf = CLEAR; int32 ptr_stopioe = 0; /* stop on error */ int32 ptr_trlcnt = 0; /* trailer counter */ int32 ptr_trllim = 40; /* trailer to add */ + +FLIP_FLOP ptp_control = CLEAR; +FLIP_FLOP ptp_flag = CLEAR; +FLIP_FLOP ptp_flagbuf = CLEAR; + int32 ptp_stopioe = 0; + +FLIP_FLOP tty_control = CLEAR; +FLIP_FLOP tty_flag = CLEAR; +FLIP_FLOP tty_flagbuf = CLEAR; + 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 */ + +FLIP_FLOP clk_control = CLEAR; +FLIP_FLOP clk_flag = CLEAR; +FLIP_FLOP clk_flagbuf = CLEAR; + int32 clk_select = 0; /* clock time select */ int32 clk_error = 0; /* clock error */ int32 clk_ctr = 0; /* clock counter */ @@ -150,26 +168,30 @@ int32 clk_rpt[8] = { /* number of repeats */ uint32 clk_tick = 0; /* instructions per tick */ DEVICE ptr_dev, ptp_dev, tty_dev, clk_dev; -int32 ptrio (int32 inst, int32 IR, int32 dat); + +uint32 ptrio (uint32 select_code, IOSIG signal, uint32 data); t_stat ptr_svc (UNIT *uptr); t_stat ptr_attach (UNIT *uptr, char *cptr); t_stat ptr_reset (DEVICE *dptr); t_stat ptr_boot (int32 unitno, DEVICE *dptr); -int32 ptpio (int32 inst, int32 IR, int32 dat); + +uint32 ptpio (uint32 select_code, IOSIG signal, uint32 data); t_stat ptp_svc (UNIT *uptr); t_stat ptp_reset (DEVICE *dptr); -int32 ttyio (int32 inst, int32 IR, int32 dat); + +uint32 ttyio (uint32 select_code, IOSIG signal, uint32 data); t_stat tti_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr); t_stat tty_reset (DEVICE *dptr); t_stat tty_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat tty_set_alf (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 clkio (int32 inst, int32 IR, int32 dat); +t_stat tto_out (int32 c); +t_stat ttp_out (int32 c); + +uint32 clkio (uint32 select_code, IOSIG signal, uint32 data); t_stat clk_svc (UNIT *uptr); 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 @@ -179,7 +201,7 @@ t_stat ttp_out (int32 c); ptr_reg PTR register list */ -DIB ptr_dib = { PTR, 0, 0, 0, 0, 0, &ptrio }; +DIB ptr_dib = { PTR, &ptrio }; UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), @@ -188,11 +210,9 @@ UNIT ptr_unit = { 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) }, + { FLDATA (CTL, ptr_control, 0) }, + { FLDATA (FLG, ptr_flag, 0) }, + { FLDATA (FBF, ptr_flagbuf, 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 }, @@ -226,7 +246,7 @@ DEVICE ptr_dev = { ptp_reg PTP register list */ -DIB ptp_dib = { PTP, 0, 0, 0, 0, 0, &ptpio }; +DIB ptp_dib = { PTP, &ptpio }; UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT @@ -234,11 +254,9 @@ UNIT ptp_unit = { 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) }, + { FLDATA (CTL, ptp_control, 0) }, + { FLDATA (FLG, ptp_flag, 0) }, + { FLDATA (FBF, ptp_flagbuf, 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) }, @@ -272,7 +290,7 @@ DEVICE ptp_dev = { #define TTO 1 #define TTP 2 -DIB tty_dib = { TTY, 0, 0, 0, 0, 0, &ttyio }; +DIB tty_dib = { TTY, &ttyio }; UNIT tty_unit[] = { { UDATA (&tti_svc, UNIT_IDLE | TT_MODE_UC, 0), POLL_WAIT }, @@ -284,11 +302,9 @@ 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 (CTL, tty_control, 0) }, + { FLDATA (FLG, tty_flag, 0) }, + { FLDATA (FBF, tty_flagbuf, 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 }, @@ -328,18 +344,16 @@ DEVICE tty_dev = { clk_reg CLK register list */ -DIB clk_dib = { CLK, 0, 0, 0, 0, 0, &clkio }; +DIB clk_dib = { CLK, &clkio }; UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 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 (CTL, clk_control, 0) }, + { FLDATA (FLG, clk_flag, 0) }, + { FLDATA (FBF, clk_flagbuf, 0) }, { FLDATA (ERR, clk_error, CLK_V_ERROR) }, { BRDATA (TIME, clk_time, 10, 24, 8) }, { DRDATA (IPTICK, clk_tick, 24), PV_RSPC | REG_RO }, @@ -363,65 +377,102 @@ DEVICE clk_dev = { &clk_dib, DEV_DISABLE }; -/* Paper tape reader IO instructions */ -int32 ptrio (int32 inst, int32 IR, int32 dat) +/* Paper tape reader I/O signal handler. + + Implementation notes: + + 1. The 12597A duplex register card is used to interface the paper tape + reader to the computer. This card has a device command flip-flop, which + supplies the READ signal to the tape reader. Under simulation, this + state is implied by the activation of the PTR unit. + + 2. The POPIO signal clears the output buffer of the duplex card. However, + the buffer outputs are not used by the paper tape reader. Under + simulation, we omit the buffer clear. +*/ + +uint32 ptrio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + ptr_flag = ptr_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + ptr_flag = ptr_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (ptr); break; - case ioMIX: /* merge */ - dat = dat | ptr_unit.buf; + + case ioSFS: /* skip if flag is set */ + setstdSKF (ptr); break; - case ioLIX: /* load */ - dat = ptr_unit.buf; + + case ioIOI: /* I/O data input */ + data = ptr_unit.buf; break; + + case ioPOPIO: /* power-on preset to I/O */ + ptr_flag = ptr_flagbuf = SET; /* set flag and flag buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - /* action same as CLC */ - 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); - } + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + ptr_control = CLEAR; break; - default: - break; - } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -return dat; + case ioSTC: /* set control flip-flop */ + ptr_control = SET; + sim_activate (&ptr_unit, ptr_unit.wait); + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, ptr); /* set standard PRL signal */ + setstdIRQ (select_code, ptr); /* set standard IRQ signal */ + setstdSRQ (select_code, ptr); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + ptr_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + ptrio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + ptrio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service */ t_stat ptr_svc (UNIT *uptr) { -int32 dev, temp; +int32 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? */ @@ -449,7 +500,9 @@ while ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte, error? */ return SCPE_IOERR; } } -setFSR (dev); /* set flag */ + +ptrio (ptr_dib.devno, ioENF, 0); /* set flag */ + ptr_unit.buf = temp & 0377; /* put byte in buf */ ptr_unit.pos = ftell (ptr_unit.fileref); @@ -459,6 +512,7 @@ if (temp) /* character non-null? * return SCPE_OK; } + /* Attach routine - clear the trailer counter */ t_stat ptr_attach (UNIT *uptr, char *cptr) @@ -467,20 +521,20 @@ ptr_trlcnt = 0; return attach_unit (uptr, cptr); } -/* Reset routine - called from SCP, flags in DIB's */ + +/* Reset routine - called from SCP */ 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_unit.buf = 0; +ptrio (ptr_dib.devno, ioPOPIO, 0); /* send POPIO signal */ sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } + /* Paper tape reader bootstrap routine (HP 12992K ROM) */ -const uint16 ptr_rom[IBL_LNT] = { +const BOOT_ROM ptr_rom = { 0107700, /*ST CLC 0,C ; intr off */ 0002401, /* CLA,RSS ; skip in */ 0063756, /*CN LDA M11 ; feed frame */ @@ -543,69 +597,107 @@ SR = (SR & IBL_OPT) | IBL_PTR | (dev << IBL_V_DEV); /* set SR */ return SCPE_OK; } -/* Paper tape punch IO instructions */ -int32 ptpio (int32 inst, int32 IR, int32 dat) +/* Paper tape punch I/O signal handler. + + Implementation notes: + + 1. The 12597A duplex register card is used to interface the paper tape + punch to the computer. This card has a device command flip-flop, which + supplies the PUNCH signal to the tape reader. Under simulation, this + state is implied by the activation of the PTP unit. +*/ + +uint32 ptpio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + ptp_flag = ptp_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + ptp_flag = ptp_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (ptp); break; - case ioLIX: /* load */ - dat = 0; - case ioMIX: /* merge */ - if ((ptp_unit.flags & UNIT_ATT) == 0) - dat = dat | PTP_LOW; /* out of tape? */ + + case ioSFS: /* skip if flag is set */ + setstdSKF (ptp); break; - case ioOTX: /* output */ - ptp_unit.buf = dat; + + case ioIOI: /* I/O data input */ + if ((ptp_unit.flags & UNIT_ATT) == 0) /* not attached? */ + data = PTP_LOW; /* report as out of tape */ + else + data = 0; break; + + case ioIOO: /* I/O data output */ + ptp_unit.buf = data; + break; + + + case ioPOPIO: /* power-on preset to I/O */ + ptp_flag = ptp_flagbuf = SET; /* set flag and flag buffer */ + ptp_unit.buf = 0; /* clear output buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - /* action same as CLC */ - 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); - } + /* fall into CLC handler */ + + case ioCLC: /* clear control flip-flop */ + ptp_control = CLEAR; break; - default: - break; - } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -return dat; + case ioSTC: /* set control flip-flop */ + ptp_control = SET; + sim_activate (&ptp_unit, ptp_unit.wait); + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, ptp); /* set standard PRL signal */ + setstdIRQ (select_code, ptp); /* set standard IRQ signal */ + setstdSRQ (select_code, ptp); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + ptp_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + +if (signal > ioCLF) /* multiple signals? */ + ptpio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + ptpio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* Unit service */ t_stat ptp_svc (UNIT *uptr) { -int32 dev; +ptpio (ptp_dib.devno, ioENF, 0); /* set flag */ -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 */ @@ -617,77 +709,113 @@ ptp_unit.pos = ftell (ptp_unit.fileref); /* update position */ return SCPE_OK; } + /* Reset routine */ t_stat ptp_reset (DEVICE *dptr) { -ptp_dib.cmd = ptp_dib.ctl = 0; /* clear cmd, ctl */ -ptp_dib.flg = ptp_dib.fbf = ptp_dib.srq = 1; /* set flg, fbf, srq */ -ptp_unit.buf = 0; +ptpio (ptp_dib.devno, ioPOPIO, 0); /* send POPIO signal */ sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } -/* Terminal IO instructions */ -int32 ttyio (int32 inst, int32 IR, int32 dat) +/* Terminal I/O signal handler */ + +uint32 ttyio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + tty_flag = tty_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + tty_flag = tty_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (tty); break; - case ioLIX: /* load */ - dat = 0; - case ioMIX: /* merge */ - dat = dat | tty_buf; + + case ioSFS: /* skip if flag is set */ + setstdSKF (tty); + break; + + + case ioIOI: /* I/O data input */ + data = tty_buf; + if (!(tty_mode & TM_KBD) && sim_is_active (&tty_unit[TTO])) - dat = dat | TP_BUSY; + data = data | TP_BUSY; break; - case ioOTX: /* output */ - if (dat & TM_MODE) tty_mode = dat & (TM_KBD|TM_PRI|TM_PUN); - tty_buf = dat & 0377; + + case ioIOO: /* I/O data output */ + if (data & TM_MODE) + tty_mode = data & (TM_KBD|TM_PRI|TM_PUN); + + tty_buf = data & 0377; break; + + case ioPOPIO: /* power-on preset to I/O */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - clrCTL (dev); /* clear control */ - setFSR (dev); /* set flag */ + tty_control = CLEAR; /* clear control */ + tty_flag = tty_flagbuf = SET; /* set flag and flag buffer */ tty_mode = TM_KBD; /* set tty, clear print/punch */ - tty_buf = 0; /* clear buffer */ tty_shin = 0377; /* input inactive */ tty_lf = 0; /* no lf pending */ 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); - } + + case ioCLC: /* clear control flip-flop */ + tty_control = CLEAR; break; - default: - break; - } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -return dat; + case ioSTC: /* set control flip-flop */ + tty_control = SET; + + if (!(tty_mode & TM_KBD)) /* output? */ + sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, tty); /* set standard PRL signal */ + setstdIRQ (select_code, tty); /* set standard IRQ signal */ + setstdSRQ (select_code, tty); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + tty_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + ttyio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + ttyio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* TTY input service routine. The console input poll routine is scheduled with a ten millisecond period @@ -732,12 +860,11 @@ return dat; t_stat tti_svc (UNIT *uptr) { -int32 c, dev; +int32 c; uptr->wait = sim_rtcn_calb (POLL_RATE, TMR_POLL); /* calibrate poll timer */ sim_activate (uptr, uptr->wait); /* continue poll */ -dev = tty_dib.devno; /* get device no */ tty_shin = 0377; /* assume inactive */ if (tty_lf) { /* auto lf pending? */ c = 012; /* force lf */ @@ -752,7 +879,9 @@ else { if (tty_mode & TM_KBD) { /* keyboard enabled? */ tty_buf = c; /* put char in buf */ uptr->pos = uptr->pos + 1; - setFSR (dev); /* set flag */ + + ttyio (tty_dib.devno, ioENF, 0); /* set flag */ + if (c) { tto_out (c); /* echo? */ return ttp_out (c); /* punch? */ @@ -762,11 +891,12 @@ else tty_shin = c; /* no, char shifts in */ return SCPE_OK; } + /* TTY output service routine */ t_stat tto_svc (UNIT *uptr) { -int32 c, dev; +int32 c; t_stat r; c = tty_buf; /* get char */ @@ -776,11 +906,13 @@ 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 */ + +ttyio (tty_dib.devno, ioENF, 0); /* set flag */ + return ttp_out (c); /* punch if enabled */ } + t_stat tto_out (int32 c) { t_stat r; @@ -795,6 +927,7 @@ if (tty_mode & TM_PRI) { /* printing? */ return SCPE_OK; } + t_stat ttp_out (int32 c) { if (tty_mode & TM_PUN) { /* punching? */ @@ -810,16 +943,16 @@ if (tty_mode & TM_PUN) { /* punching? */ return SCPE_OK; } + /* TTY reset routine */ 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_buf = 0; -tty_shin = 0377; /* input inactive */ -tty_lf = 0; /* no lf pending */ +if (sim_switches & SWMASK ('P')) /* PON reset? */ + tty_buf = 0; /* clear buffer */ + +ttyio (tty_dib.devno, ioPOPIO, 0); /* send POPIO signal */ + tty_unit[TTI].wait = POLL_WAIT; /* reset initial poll */ sim_rtcn_init (tty_unit[TTI].wait, TMR_POLL); /* init poll timer */ sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ @@ -827,6 +960,7 @@ sim_cancel (&tty_unit[TTO]); /* cancel output */ return SCPE_OK; } + t_stat tty_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 u = uptr - tty_dev.units; @@ -838,6 +972,7 @@ tty_unit[u].flags = (tty_unit[u].flags & ~TT_MODE) | val; return SCPE_OK; } + t_stat tty_set_alf (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 u = uptr - tty_dev.units; @@ -846,6 +981,7 @@ if (u != TTI) return SCPE_NOFNC; return SCPE_OK; } + /* Synchronize polling. Return an event time corresponding either with the amount of time remaining @@ -872,7 +1008,7 @@ int32 poll_time; } -/* Clock I/O instructions. +/* Clock I/O signal handler. The time base generator (CLK) provides periodic interrupts from 100 microseconds to 1000 seconds. The CLK uses a calibrated timer to provide the @@ -888,78 +1024,108 @@ int32 poll_time; expected. */ -int32 clkio (int32 inst, int32 IR, int32 dat) +uint32 clkio (uint32 select_code, IOSIG signal, uint32 data) { -int32 dev; +const IOSIG base_signal = IOBASE (signal); /* derive base signal */ -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ +switch (base_signal) { /* dispatch base I/O signal */ - case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + case ioCLF: /* clear flag flip-flop */ + clk_flag = clk_flagbuf = CLEAR; break; - case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + + case ioSTF: /* set flag flip-flop */ + case ioENF: /* enable flag */ + clk_flag = clk_flagbuf = SET; break; - case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + + case ioSFC: /* skip if flag is clear */ + setstdSKF (clk); break; - case ioMIX: /* merge */ - dat = dat | clk_error; + + case ioSFS: /* skip if flag is set */ + setstdSKF (clk); break; - case ioLIX: /* load */ - dat = clk_error; + + case ioIOI: /* I/O data input */ + data = clk_error; break; - case ioOTX: /* output */ - clk_select = dat & 07; /* save select */ + + case ioIOO: /* I/O data output */ + clk_select = data & 07; /* save select */ sim_cancel (&clk_unit); /* stop the clock */ - clrCTL (dev); /* clear control */ + clk_control = CLEAR; /* clear control */ + clkio (select_code, ioSIR, 0); /* set interrupt request (IOO normally doesn't) */ break; + + case ioPOPIO: /* power-on preset to I/O */ + clk_flag = clk_flagbuf = SET; /* set flag and flag buffer */ + /* fall into CRS handler */ + case ioCRS: /* control reset */ - /* action same as CLC */ - 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 */ + /* fall into CLC handler */ - if (clk_unit.flags & UNIT_DIAG) /* diag mode? */ - clk_unit.flags = clk_unit.flags & ~UNIT_IDLE; /* not calibrated */ - else - clk_unit.flags = clk_unit.flags | UNIT_IDLE; /* is calibrated */ - - if (!sim_is_active (&clk_unit)) { /* clock running? */ - clk_tick = clk_delay (0); /* get tick count */ - - if ((clk_unit.flags & UNIT_DIAG) == 0) /* calibrated? */ - if (clk_select == 2) /* 10 msec. interval? */ - clk_tick = sync_poll (INITIAL); /* sync poll */ - else - sim_rtcn_init (clk_tick, TMR_CLK); /* initialize timer */ - - sim_activate (&clk_unit, clk_tick); /* start clock */ - clk_ctr = clk_delay (1); /* set repeat ctr */ - } - clk_error = 0; /* clear error */ - } + case ioCLC: /* clear control flip-flop */ + clk_control = CLEAR; + sim_cancel (&clk_unit); /* deactivate unit */ break; - default: - break; - } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -return dat; + case ioSTC: /* set control flip-flop */ + clk_control = SET; + if (clk_unit.flags & UNIT_DIAG) /* diag mode? */ + clk_unit.flags = clk_unit.flags & ~UNIT_IDLE; /* not calibrated */ + else + clk_unit.flags = clk_unit.flags | UNIT_IDLE; /* is calibrated */ + + if (!sim_is_active (&clk_unit)) { /* clock running? */ + clk_tick = clk_delay (0); /* get tick count */ + + if ((clk_unit.flags & UNIT_DIAG) == 0) /* calibrated? */ + if (clk_select == 2) /* 10 msec. interval? */ + clk_tick = sync_poll (INITIAL); /* sync poll */ + else + sim_rtcn_init (clk_tick, TMR_CLK); /* initialize timer */ + + sim_activate (&clk_unit, clk_tick); /* start clock */ + clk_ctr = clk_delay (1); /* set repeat ctr */ + } + clk_error = 0; /* clear error */ + break; + + + case ioSIR: /* set interrupt request */ + setstdPRL (select_code, clk); /* set standard PRL signal */ + setstdIRQ (select_code, clk); /* set standard IRQ signal */ + setstdSRQ (select_code, clk); /* set standard SRQ signal */ + break; + + + case ioIAK: /* interrupt acknowledge */ + clk_flagbuf = CLEAR; + break; + + + default: /* all other signals */ + break; /* are ignored */ + } + + +if (signal > ioCLF) /* multiple signals? */ + clkio (select_code, ioCLF, 0); /* issue CLF */ +else if (signal > ioSIR) /* signal affected interrupt status? */ + clkio (select_code, ioSIR, 0); /* set interrupt request */ + +return data; } + /* CLK unit service. As with the I/O handler, if the time base period is set to ten milliseconds, @@ -968,10 +1134,8 @@ return dat; t_stat clk_svc (UNIT *uptr) { -int32 dev; - -dev = clk_dib.devno; /* get device no */ -if (!CTL (dev)) return SCPE_OK; /* CTL off? done */ +if (!clk_control) /* control clear? */ + return SCPE_OK; /* done */ if (clk_unit.flags & UNIT_DIAG) /* diag mode? */ clk_tick = clk_delay (0); /* get fixed delay */ @@ -983,26 +1147,32 @@ else sim_activate (uptr, clk_tick); /* reactivate */ clk_ctr = clk_ctr - 1; /* decrement counter */ if (clk_ctr <= 0) { /* end of interval? */ - if (FLG (dev)) clk_error = CLK_ERROR; /* overrun? error */ - else { setFSR (dev); } /* else set flag */ + if (clk_flag) + clk_error = CLK_ERROR; /* overrun? error */ + else + clkio (clk_dib.devno, ioENF, 0); /* set flag */ clk_ctr = clk_delay (1); /* reset counter */ } return SCPE_OK; } + /* Reset routine */ t_stat clk_reset (DEVICE *dptr) { -clk_dib.cmd = clk_dib.ctl = 0; /* clear cmd, ctl */ -clk_dib.flg = clk_dib.fbf = 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 */ +if (sim_switches & SWMASK ('P')) { /* PON reset? */ + clk_error = 0; /* clear error */ + clk_select = 0; /* clear select */ + clk_ctr = 0; /* clear counter */ + } + +clkio (clk_dib.devno, ioPOPIO, 0); /* send POPIO signal */ + return SCPE_OK; } + /* Clock delay routine */ int32 clk_delay (int32 flg) diff --git a/HP2100/hp2100_sys.c b/HP2100/hp2100_sys.c index b4abeaca..98e0e76d 100644 --- a/HP2100/hp2100_sys.c +++ b/HP2100/hp2100_sys.c @@ -23,6 +23,12 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 03-Sep-08 JDB Fixed IAK instruction dual-use mnemonic display + 07-Aug-08 JDB Moved hp_setdev, hp_showdev from hp2100_cpu.c + Changed sim_load to use WritePW instead of direct M[] access + 18-Jun-08 JDB Added PIF device + 17-Jun-08 JDB Moved fmt_char() function from hp2100_baci.c + 26-May-08 JDB Added MPX device 24-Apr-08 JDB Changed fprint_sym to handle step with irq pending 07-Dec-07 JDB Added BACI device 27-Nov-07 JDB Added RTE OS/VMA/EMA mnemonics @@ -50,13 +56,17 @@ #include extern DEVICE cpu_dev; -extern UNIT cpu_unit; +extern UNIT cpu_unit; +extern REG cpu_reg[]; + extern DEVICE mp_dev; extern DEVICE dma0_dev, dma1_dev; extern DEVICE ptr_dev, ptp_dev; extern DEVICE tty_dev, clk_dev; -extern DEVICE lps_dev, lpt_dev; +extern DEVICE lps_dev; +extern DEVICE lpt_dev; extern DEVICE baci_dev; +extern DEVICE mpx_dev; extern DEVICE mtd_dev, mtc_dev; extern DEVICE msd_dev, msc_dev; extern DEVICE dpd_dev, dpc_dev; @@ -65,9 +75,7 @@ extern DEVICE drd_dev, drc_dev; extern DEVICE ds_dev; extern DEVICE muxl_dev, muxu_dev, muxc_dev; extern DEVICE ipli_dev, iplo_dev; -extern REG cpu_reg[]; -extern uint16 *M; -extern uint32 fwanxm; +extern DEVICE pif_dev; /* SCP data structures and interface routines @@ -99,6 +107,7 @@ DEVICE *sim_devices[] = { &lps_dev, &lpt_dev, &baci_dev, + &mpx_dev, &dpd_dev, &dpc_dev, &dqd_dev, &dqc_dev, &drd_dev, &drc_dev, @@ -107,6 +116,7 @@ DEVICE *sim_devices[] = { &msd_dev, &msc_dev, &muxl_dev, &muxu_dev, &muxc_dev, &ipli_dev, &iplo_dev, + &pif_dev, NULL }; @@ -163,7 +173,7 @@ for (zerocnt = 1;; zerocnt = -10) { /* block loop */ 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; + WritePW (origin, word); origin = origin + 1; csum = csum + word; } @@ -210,7 +220,7 @@ static const char *opcode[] = { /* These mnemonics are used by debug printouts, so put them first. */ "$LIBR", "$LIBX", ".TICK", ".TNAM", /* RTE-6/VM OS firmware */ - ".STIO", ".FNW", ".IRT", ".LLS", + ".STIO", ".FNW", ".IRT", ".LLS", ".SIP", ".YLD", ".CPM", ".ETEQ", ".ENTN", "$OTST", ".ENTC", ".DSPI", "$DCPC", "$MPV", "$DEV", "$TBG", /* alternates for dual-use */ @@ -411,6 +421,7 @@ if (sw & SIM_SW_STOP) { /* simulator stop? */ irq = calc_int (); /* check interrupt */ if (irq && (!ion_defer || !calc_defer())) { /* pending interrupt and not deferred? */ + addr = irq; /* set display address to trap cell */ inst = val[0] = ReadIO (irq, SMAP); /* load trap cell instruction */ val[1] = ReadIO (irq + 1, SMAP); /* might be multi-word */ val[2] = ReadIO (irq + 2, SMAP); /* although it's unlikely */ @@ -718,3 +729,77 @@ if (clef) { /* CLE seen? */ } return ret; } + + +/* Format a character into a printable string. + + Control characters are translated to readable strings. Printable characters + retain their original form but are enclosed in single quotes. Characters + outside of the ASCII range are represented as escaped octal values. +*/ + +const char *fmt_char (uint8 ch) +{ +static const char *const ctl [] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", + "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", + "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", + "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" }; +static char rep [5]; + +if (ch <= '\037') /* ASCII control character? */ + return ctl [ch]; /* return string representation */ + +else if (ch == '\177') /* ASCII delete? */ + return "DEL"; /* return string representation */ + +else if (ch > '\177') { /* beyond printable range? */ + sprintf (rep, "\\%03o", ch); /* format value */ + return rep; /* return escaped octal code */ + } + +else { /* printable character */ + rep [0] = '\''; /* form string */ + rep [1] = ch; /* containing character */ + rep [2] = '\''; + rep [3] = '\0'; + return rep; /* return quoted character */ + } +} + + +/* Set device number */ + +t_stat hp_setdev (UNIT *uptr, int32 num, char *cptr, void *desc) +{ +DEVICE *dptr = (DEVICE *) desc; +DIB *dibp; +int32 i, newdev; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +if ((desc == NULL) || (num > 1)) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +newdev = get_uint (cptr, 8, I_DEVMASK - num, &r); +if (r != SCPE_OK) return r; +if (newdev < VARDEV) return SCPE_ARG; +for (i = 0; i <= num; i++, dibp++) dibp->devno = newdev + i; +return SCPE_OK; +} + + +/* Show device number */ + +t_stat hp_showdev (FILE *st, UNIT *uptr, int32 num, void *desc) +{ +DEVICE *dptr = (DEVICE *) desc; +DIB *dibp; +int32 i; + +if ((desc == NULL) || (num > 1)) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +fprintf (st, "devno=%o", dibp->devno); +for (i = 1; i <= num; i++) fprintf (st, "/%o", dibp->devno + i); +return SCPE_OK; +} diff --git a/I1401/i1401_cd.c b/I1401/i1401_cd.c index 34c80756..eea3b5b2 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -171,26 +171,32 @@ 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 (r = cdr_svc (&cdr_unit)) /* process */ + return r; } -if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ +if ((cdr_unit.flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_UNATT; 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 */ +for (i = 0; i < 2 * CBUFSIZE; i++) /* clear extended buf */ + rbuf[i] = 0; fgets (rbuf, (cbn)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */ cdr_unit.fileref); -if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */ +if (feof (cdr_unit.fileref)) /* eof? */ + return STOP_NOCD; if (ferror (cdr_unit.fileref)) { /* error? */ ind[IN_READ] = 1; perror ("Card reader I/O error"); clearerr (cdr_unit.fileref); - if (iochk) return SCPE_IOERR; + if (iochk) + return SCPE_IOERR; 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 */ + if (feof (cdr_unit.fileref)) /* eof? set flag */ + ind[IN_LST] = 1; fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); } if (cbn) { /* column binary */ @@ -228,13 +234,17 @@ 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? */ +if (s1sel) /* stacker 1? */ + uptr = &stack_unit[1]; +else if (s2sel) /* stacker 2? */ + uptr = &stack_unit[2]; else uptr = &stack_unit[0]; /* then default */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = bcd2ascii (rbuf[i], uptr->flags & UNIT_PCH); -for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0; +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 */ @@ -242,7 +252,8 @@ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* error? */ perror ("Card stacker I/O error"); clearerr (uptr->fileref); - if (iochk) return SCPE_IOERR; + if (iochk) + return SCPE_IOERR; } return SCPE_OK; } @@ -260,10 +271,13 @@ static char pbuf[(2 * CDP_WIDTH) + 1]; /* + null */ t_bool use_h; UNIT *uptr; -if (s8sel) uptr = &stack_unit[2]; /* stack 8? */ -else if (s4sel) uptr = &stack_unit[4]; /* stack 4? */ +if (s8sel) /* stack 8? */ + uptr = &stack_unit[2]; +else if (s4sel) /* stack 4? */ + uptr = &stack_unit[4]; else uptr = &cdp_unit; /* normal output */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_UNATT; use_h = uptr->flags & UNIT_PCH; ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */ cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */ @@ -299,7 +313,8 @@ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* error? */ perror ("Card punch I/O error"); clearerr (uptr->fileref); - if (iochk) return SCPE_IOERR; + if (iochk) + return SCPE_IOERR; ind[IN_PNCH] = 1; } return SCPE_OK; @@ -314,10 +329,14 @@ return SCPE_OK; t_stat select_stack (int32 ilnt, int32 mod) { -if (mod == BCD_ONE) s1sel = 1; -else if (mod == BCD_TWO) s2sel = 1; -else if (mod == BCD_FOUR) s4sel = 1; -else if (mod == BCD_EIGHT) s8sel = 1; +if (mod == BCD_ONE) + s1sel = 1; +else if (mod == BCD_TWO) + s2sel = 1; +else if (mod == BCD_FOUR) + s4sel = 1; +else if (mod == BCD_EIGHT) + s8sel = 1; return SCPE_OK; } @@ -353,8 +372,10 @@ t_stat cdr_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 saved_IS; -for (i = 0; i < CDR_WIDTH; i++) M[CDR_BUF + i] = 0; /* clear buffer */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +for (i = 0; i < CDR_WIDTH; i++) /* clear buffer */ + M[CDR_BUF + i] = 0; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; saved_IS = BOOT_START; return SCPE_OK; } @@ -381,7 +402,8 @@ uint32 i; char bcd; for (i = 0, bcd = 0; i < 12; i++) { /* 'sum' rows */ - if (cb & (1 << i)) bcd |= row_val[i]; + if (cb & (1 << i)) + bcd |= row_val[i]; } return bcd; } diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c index 851a3005..851f0c2a 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,6 +23,9 @@ 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-Jul-08 RMS Added missing A magtape modifier (from Van Snyder) + Fixed tape indicator implementation (from Bob Abeles) + Fixed bug in ZA and ZS (from Bob Abeles) 07-Jul-07 RMS Removed restriction on load-mode binary tape 28-Jun-07 RMS Added support for SS overlap modifiers 22-May-06 RMS Fixed format error in CPU history (found by Peter Schorn) @@ -165,7 +168,8 @@ typedef struct { reason = STOP_INVBR; \ break; \ } \ - if (cpu_unit.flags & XSA) BS = IS; \ + if (cpu_unit.flags & XSA) \ + BS = IS; \ else BS = BA + 0; \ PCQ_ENTRY; \ IS = AS; @@ -220,7 +224,8 @@ extern t_stat write_line (int32 ilnt, int32 mod); extern t_stat inq_io (int32 flag, int32 mod); extern t_stat mt_io (int32 unit, int32 flag, int32 mod); extern t_stat dp_io (int32 fnc, int32 flag, int32 mod); -extern t_stat mt_func (int32 unit, int32 mod); +extern t_stat mt_func (int32 unit, int32 flag, int32 mod); +extern t_bool mt_testind (void); 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); @@ -488,12 +493,23 @@ static const int32 cry_table[100] = { /* Legal modifier tables */ -static const int32 r_mod[] = { BCD_C, -1 }; -static const int32 p_mod[] = { BCD_C, -1 }; -static const int32 w_mod[] = { BCD_S, BCD_SQUARE, -1 }; -static const int32 ss_mod[] = { BCD_ONE, BCD_TWO, BCD_FOUR, BCD_EIGHT, - BCD_DOLLAR, BCD_DECIMAL, BCD_SQUARE, -1 }; -static const int32 mtf_mod[] = { BCD_B, BCD_E, BCD_M, BCD_R, BCD_U, -1 }; +static const int32 r_mod[] = { + BCD_C, -1 + }; +static const int32 p_mod[] = { + BCD_C, -1 + }; +static const int32 w_mod[] = { + BCD_S, BCD_SQUARE, -1 + }; +static const int32 ss_mod[] = { + BCD_ONE, BCD_TWO, BCD_FOUR, BCD_EIGHT, + BCD_DOLLAR, BCD_DECIMAL, BCD_SQUARE, -1 + }; +static const int32 mtf_mod[] = { + BCD_A, BCD_B, BCD_E, + BCD_M, BCD_R, BCD_U, -1 + }; t_stat sim_instr (void) { @@ -509,8 +525,10 @@ t_stat reason, r1, r2; /* Restore saved state */ IS = saved_IS; -if (as_err) AS = AS | BA; /* flag bad addresses */ -if (bs_err) BS = BS | BA; +if (as_err) /* flag bad addresses */ + AS = AS | BA; +if (bs_err) + BS = BS | BA; as_err = bs_err = 0; /* reset error flags */ reason = 0; @@ -525,7 +543,8 @@ while (reason == 0) { /* loop until halted */ saved_IS = IS; /* commit prev instr */ if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; } if (sim_brk_summ && sim_brk_test (IS, SWMASK ('E'))) { /* breakpoint? */ @@ -568,17 +587,20 @@ while (reason == 0) { /* loop until halted */ reason = STOP_NXI; /* illegal inst? */ break; } - if (op == OP_SAR) BS = AS; /* SAR? save ASTAR */ + if (op == OP_SAR) /* SAR? save ASTAR */ + BS = AS; PP (IS); - if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-1: WM? 1 char inst */ + if ((t = M[IS]) & WM) /* I-1: WM? 1 char inst */ + goto CHECK_LENGTH; 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; + if (!(flags & MLS)) + BS = AS; goto CHECK_LENGTH; } D = dev = t; /* could be D char, dev */ @@ -587,11 +609,13 @@ while (reason == 0) { /* loop until halted */ if ((t = M[IS]) & WM) { /* I-3: WM? 3 char inst */ AS = AS | BA; /* ASTAR bad */ - if (!(flags & MLS)) BS = AS; + 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 */ + if (unit == BCD_ZERO) /* convert unit to binary */ + unit = 0; 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? */ @@ -599,10 +623,12 @@ while (reason == 0) { /* loop until halted */ one_table[M[xa + 2] & CHAR]; AS = (AS & INDEXMASK) % MAXMEMSIZE; } - if (!(flags & MLS)) BS = AS; /* not MLS? B = A */ + if (!(flags & MLS)) /* not MLS? B = A */ + BS = AS; PP (IS); - if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-4: WM? 4 char inst */ + if ((t = M[IS]) & WM) /* I-4: WM? 4 char inst */ + goto CHECK_LENGTH; if ((op == OP_B) && (t == BCD_BLANK)) /* BR + space? */ goto CHECK_LENGTH; D = t; /* could be D char */ @@ -631,14 +657,17 @@ while (reason == 0) { /* loop until halted */ } PP (IS); - if (flags & NOWM) goto CHECK_LENGTH; /* I-7: SWM? done */ - if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 7 char inst */ + if (flags & NOWM) /* I-7: SWM? done */ + goto CHECK_LENGTH; + if ((t = M[IS]) & WM) /* WM? 7 char inst */ + goto CHECK_LENGTH; 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? */ + if (reason) /* addr err on last? */ + break; CHECK_LENGTH: if ((flags & BREQ) && ADDR_ERR (BS)) { /* valid B? */ @@ -652,7 +681,8 @@ CHECK_LENGTH: 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; + 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++) @@ -661,9 +691,11 @@ CHECK_LENGTH: 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; 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; + 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" ); @@ -756,18 +788,22 @@ CHECK_LENGTH: do { wm = M[AS]; M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT);/* copy char */ - MM (AS); MM (BS); /* decr pointers */ + MM (AS); /* decr pointers */ + MM (BS); } while ((wm & WM) == 0); /* stop on A WM */ - if (reason) break; /* addr err? stop */ + if (reason) /* addr err? stop */ + break; 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; + 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; + (t <= BCD_NINE)) + qzero = 0; else qzero = 1; } while (BS < bsave); PP (BS); /* BS end is B+1 */ @@ -800,18 +836,33 @@ CHECK_LENGTH: */ case OP_B: /* branch */ - if (ilnt == 4) { BRANCH; } /* uncond branch? */ + if (ilnt == 4) { /* uncond branch? */ + BRANCH; + } else if (ilnt == 5) { /* branch on ind? */ - if (ind[D]) { BRANCH; } /* test indicator */ - if (ind_table[D]) ind[D] = 0; /* reset if needed */ + if (D == IN_END) { /* tape indicator */ + if (mt_testind ()) { /* test, reset */ + BRANCH; + } + else break; + } + if (ind[D]) { /* test indicator */ + BRANCH; + } + if (ind_table[D]) /* reset if needed */ + ind[D] = 0; } 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); } + if ((M[BS] & CHAR) == D) { /* char equal? */ + BRANCH; + } + else { + MM (BS); + } } break; @@ -832,14 +883,21 @@ CHECK_LENGTH: 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 */ + ((D & 2) && ((M[BS] & ZONE) == (D & ZONE)))) { /* d2? test zone */ + BRANCH; + } + else { /* decr pointer */ + MM (BS); + } break; case OP_BBE: /* branch if bit eq */ - if (M[BS] & D & CHAR) { BRANCH; } /* any bits set? */ - else { MM (BS); } /* decr pointer */ + if (M[BS] & D & CHAR) { /* any bits set? */ + BRANCH; + } + else { /* decr pointer */ + MM (BS); + } break; /* Arithmetic instructions A check B check @@ -860,19 +918,24 @@ CHECK_LENGTH: 5,6 invalid B-address 7 normal 8+ normal + ignored modifier + + Despite their names, ZA and ZS are not arithmetic instructions, but copies + with zone stripping. The adder is not used, so BCD conversions do not occur. */ 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; + if (a & WM) /* A word mark? */ + 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 */ + t = a & DIGIT; /* zap zone bits */ + wm = M[BS] = (M[BS] & WM) | t; /* store digit */ MM (AS); } - if (i == 0) i = M[BS] = M[BS] | + 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 */ @@ -888,16 +951,18 @@ CHECK_LENGTH: 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 */ + if (qsign && ((b & BBIT) == 0)) /* normalize sign */ + b = b | ZONE; 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]; + if (qsign && (carry == 0)) /* compl, no carry? */ + M[bsave] = WM + ((b & ZONE) ^ ABIT) + sum_table[10 - t]; break; } do { - if (a & WM) a = WM; /* A WM? char = 0 */ + if (a & WM) /* A WM? char = 0 */ + a = WM; else { a = M[AS]; /* else get A */ MM (AS); @@ -914,7 +979,8 @@ CHECK_LENGTH: 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 (reason) /* address err? */ + break; if (qsign && (carry == 0)) { /* recompl, no carry? */ M[bsave] = M[bsave] ^ ABIT; /* XOR sign */ for (carry = 1; bsave != BS; --bsave) { /* rescan */ @@ -940,7 +1006,8 @@ CHECK_LENGTH: ind[IN_HGH] = col_table[b & CHAR] > col_table [a & CHAR]; ind[IN_LOW] = ind[IN_HGH] ^ 1; } - MM (AS); MM (BS); /* decr pointers */ + MM (AS); /* decr pointers */ + MM (BS); } while ((wm & WM) == 0); /* stop on A, B WM */ if ((a & WM) && !(b & WM)) { /* short A field? */ ind[IN_EQU] = ind[IN_LOW] = 0; @@ -974,72 +1041,104 @@ CHECK_LENGTH: */ case OP_R: /* read */ - if (reason = iomod (ilnt, D, r_mod)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, r_mod)) /* valid modifier? */ + break; reason = read_card (ilnt, D); /* read card */ BS = CDR_BUF + CDR_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } break; case OP_W: /* write */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, w_mod)) /* valid modifier? */ + break; reason = write_line (ilnt, D); /* print line */ BS = LPT_BUF + LPT_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } break; case OP_P: /* punch */ - if (reason = iomod (ilnt, D, p_mod)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, p_mod)) /* valid modifier? */ + break; reason = punch_card (ilnt, D); /* punch card */ BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } break; case OP_WR: /* write and read */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, w_mod)) /* valid modifier? */ + break; 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 */ + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } + if (reason == SCPE_OK) /* merge errors */ + reason = r1; break; case OP_WP: /* write and punch */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, w_mod)) /* valid modifier? */ + break; 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 */ + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } + if (reason == SCPE_OK) /* merge errors */ + reason = r1; break; case OP_RP: /* read and punch */ - if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, NULL)) /* valid modifier? */ + break; 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 */ + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } + if (reason == SCPE_OK) /* merge errors */ + reason = r1; break; case OP_WRP: /* write, read, punch */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ + if (reason = iomod (ilnt, D, w_mod)) /* valid modifier? */ + break; 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; + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } + if (reason == SCPE_OK) /* merge errors */ + 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 */ + if (reason = iomod (ilnt, D, ss_mod)) /* valid modifier? */ + break; + if (reason = select_stack (D)) /* sel stack, error? */ + break; + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + 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 */ + if (reason = carriage_control (D)) /* car ctrl, error? */ + break; + if ((ilnt == 4) || (ilnt == 5)) { /* check for branch */ + BRANCH; + } break; /* MTF - magtape functions - must be at least 4 characters @@ -1053,10 +1152,17 @@ CHECK_LENGTH: */ 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? */ + if (ilnt < 4) /* too short? */ + reason = STOP_INVL; + else if (ioind != BCD_PERCNT) /* valid dev addr? */ + reason = STOP_INVA; + else if (reason = iomod (ilnt, D, mtf_mod)) /* valid modifier? */ + break; + if (dev == IO_MT) /* BCD? */ + reason = mt_func (unit, 0, D); + else if (dev == IO_MTB) /* binary? */ + reason = mt_func (unit, MD_BIN, D); + else reason = STOP_INVA; /* wrong device */ break; /* can't branch */ case OP_RF: case OP_PF: /* read, punch feed */ @@ -1121,27 +1227,32 @@ CHECK_LENGTH: switch (b & CHAR) { /* case on B char */ case BCD_ASTER: /* * */ - if (!qbody || qdollar || !(cpu_unit.flags & EPE)) break; + 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; + if (!qbody || qaster || !(cpu_unit.flags & EPE)) + break; qdollar = 1; /* flag */ goto A_CYCLE; /* take A cycle */ case BCD_ZERO: /* 0 */ if (qawm) { /* left status? */ - if (!qzero) M[BS] = M[BS] | WM; /* first? set WM */ + if (!qzero) /* first? set WM */ + M[BS] = M[BS] | WM; qzero = 1; /* flag suppress */ break; } - if (!qzero) t = t | WM; /* body, first? WM */ + if (!qzero) /* body, first? WM */ + t = t | WM; qzero = 1; /* flag suppress */ goto A_CYCLE; /* take A cycle */ case BCD_BLANK: /* blank */ - if (qawm) break; /* left status? */ + if (qawm) /* left status? */ + break; A_CYCLE: M[BS] = t; /* copy char */ if (a & WM) { /* end of A field? */ @@ -1157,11 +1268,13 @@ CHECK_LENGTH: break; case BCD_C: case BCD_R: case BCD_MINUS: /* C, R, - */ - if (!qsign && !qbody) M[BS] = BCD_BLANK; /* + & status? blank */ + if (!qsign && !qbody) /* + & status? blank */ + M[BS] = BCD_BLANK; break; case BCD_COMMA: /* , */ - if (!qbody) M[BS] = BCD_BLANK; /* status? blank */ + if (!qbody) /* status? blank */ + M[BS] = BCD_BLANK; break; case BCD_AMPER: /* & */ @@ -1172,8 +1285,10 @@ CHECK_LENGTH: MM (BS); /* decr B pointer */ } while ((b & WM) == 0); /* stop on B WM */ - if (reason) break; /* address err? */ - if (!qzero) break; /* rescan? */ + if (reason) /* address err? */ + break; + if (!qzero) /* rescan? */ + break; /* Edit pass 2 - from left to right, suppressing zeroes */ @@ -1193,7 +1308,8 @@ CHECK_LENGTH: break; case BCD_BLANK: /* blank */ - if (qaster) M[BS] = BCD_ASTER; /* if EPE *, repl */ + if (qaster) /* if EPE *, repl */ + M[BS] = BCD_ASTER; break; case BCD_DECIMAL: /* . */ @@ -1216,7 +1332,8 @@ CHECK_LENGTH: BS++; /* BS = addr WM + 1 */ break; } - if (qdecimal && qzero) qdollar = 0; /* no digits? clr $ */ + if (qdecimal && qzero) /* no digits? clr $ */ + qdollar = 0; /* Edit pass 3 (extended print only) - from right to left */ @@ -1268,7 +1385,8 @@ CHECK_LENGTH: MM (AS); /* decr pointers */ MM (BS); } while ((a & WM) == 0); /* until A WM */ - if (reason) break; /* address err? */ + if (reason) /* address err? */ + break; M[BS] = BCD_ZERO; /* zero hi prod */ MM (BS); /* addr low mpyr */ sign = ((M[asave] & ZONE) == BBIT) ^ ((M[BS] & ZONE) == BBIT); @@ -1300,7 +1418,8 @@ CHECK_LENGTH: 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 */ + if (sign) /* if minus, B only */ + M[lowprd] = M[lowprd] & ~ABIT; break; /* Divide. Comments from the PDP-10 based simulator by Len Fehskens. @@ -1342,11 +1461,13 @@ CHECK_LENGTH: ahigh = -1; do { a = M[AS]; /* get dvr char */ - if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */ + if ((a & CHAR) != BCD_ZERO) /* mark non-zero */ + ahigh = AS; MM (AS); } while ((a & WM) == 0); - if (reason) break; /* address err? */ + if (reason) /* address err? */ + break; if (ahigh < 0) { /* div by zero? */ ind[IN_OVF] = 1; /* set ovf indic */ qs = bsave = BS; /* quo, dividend */ @@ -1354,7 +1475,8 @@ CHECK_LENGTH: b = M[bsave]; /* find end divd */ PP (bsave); /* marked by zone */ } while ((b & ZONE) == 0); - if (reason) break; /* address err? */ + if (reason) /* address err? */ + break; if (ADDR_ERR (qs)) { /* address err? */ reason = STOP_WRAP; /* address wrap? */ break; @@ -1391,7 +1513,8 @@ CHECK_LENGTH: bsave++; /* adv divd, quo */ qs++; } while ((b & ZONE) == 0); /* until B sign */ - if (reason) break; /* address err? */ + if (reason) /* address err? */ + break; /* At this point, @@ -1452,9 +1575,13 @@ CHECK_LENGTH: 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? */ + while (BS >= t) /* clear region */ + M[BS--] = 0; + if (BS < 0) /* wrap if needed */ + BS = BS + MEMSIZE; + if (ilnt == 7) { /* branch variant? */ + BRANCH; + } break; /* Modify address instruction A check B check @@ -1481,7 +1608,8 @@ CHECK_LENGTH: 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? */ + if (((a % 4000) + (b % 4000)) >= 4000) /* carry? */ + BS = BS + 2; break; /* Store address instructions A-check B-check @@ -1514,7 +1642,8 @@ CHECK_LENGTH: /* HALT - unless length = 4 (branch), no validity checking; all lengths ok */ case OP_H: /* halt */ - if (ilnt == 4) hb_pend = 1; /* set pending branch */ + if (ilnt == 4) /* set pending branch */ + hb_pend = 1; reason = STOP_HALT; /* stop simulator */ saved_IS = IS; /* commit instruction */ break; @@ -1617,7 +1746,8 @@ void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp) int32 sign = dvrc & ZONE; /* divisor sign */ M[rp] = M[rp] | ZONE; /* assume rem pos */ -if (sign == BBIT) M[rp] = M[rp] & ~ABIT; /* if dvr -, rem - */ +if (sign == BBIT) /* if dvr -, rem - */ + M[rp] = M[rp] & ~ABIT; M[qp] = M[qp] | ZONE; /* assume quo + */ if (((dvdc & ZONE) == BBIT) ^ (sign == BBIT)) /* dvr,dvd diff? */ M[qp] = M[qp] & ~ABIT; /* make quo - */ @@ -1636,10 +1766,13 @@ return; 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; +if ((ilnt != 2) && (ilnt != 5) && (ilnt < 8)) + return SCPE_OK; +if (tptr == NULL) + return STOP_INVM; do { - if (mod == *tptr++) return SCPE_OK; + if (mod == *tptr++) + return SCPE_OK; } while (*tptr >= 0); return STOP_INVM; } @@ -1655,9 +1788,12 @@ return STOP_INVM; 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_INQ) /* inq terminal? */ + return inq_io (flag, mod); +if (dev == IO_DP) /* disk pack? */ + return dp_io (unit, flag, mod); +if (dev == IO_MT) /* magtape? */ + return mt_io (unit, flag, mod); if (dev == IO_MTB) /* binary magtape? */ return mt_io (unit, flag | MD_BIN, mod); return STOP_NXD; /* not implemented */ @@ -1670,17 +1806,19 @@ t_stat cpu_reset (DEVICE *dptr) int32 i; for (i = 0; i < 64; i++) { /* clr indicators */ - if ((i < IN_SSB) || (i > IN_SSG)) ind[i] = 0; /* except SSB-SSG */ + if ((i < IN_SSB) || (i > IN_SSG)) /* except SSB-SSG */ + ind[i] = 0; } ind[IN_UNC] = 1; /* ind[0] always on */ AS = 0; /* clear AS */ -BS = 0; /* clear BS * +BS = 0; /* clear BS */ as_err = 1; -bs_err = 1;/ +bs_err = 1; D = 0; /* clear D */ hb_pend = 0; /* no halt br */ pcq_r = find_reg ("ISQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1690,8 +1828,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & (WM + CHAR); +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & (WM + CHAR); return SCPE_OK; } @@ -1699,7 +1839,8 @@ 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 & (WM + CHAR); return SCPE_OK; } @@ -1713,12 +1854,15 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -if (MEMSIZE > 4000) cpu_unit.flags = cpu_unit.flags | MA; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; +if (MEMSIZE > 4000) + cpu_unit.flags = cpu_unit.flags | MA; else cpu_unit.flags = cpu_unit.flags & ~MA; return SCPE_OK; } @@ -1731,12 +1875,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].ilnt = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -1745,7 +1891,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -1763,14 +1910,17 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ @@ -1802,7 +1952,8 @@ return SCPE_OK; t_stat cpu_show_conv (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (conv_old) fputs ("Old (pre-3.5-1) conversions\n", st); +if (conv_old) + fputs ("Old (pre-3.5-1) conversions\n", st); else fputs ("New conversions\n", st); return SCPE_OK; } diff --git a/I1401/i1401_dat.h b/I1401/i1401_dat.h index 53d85014..4320e9cf 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-2005, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/I1401/i1401_defs.h b/I1401/i1401_defs.h index 7e6b6274..373cec7b 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert 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,6 +23,7 @@ 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-Jul-08 RMS Added IO mode flag for boot (from Bob Abeles) 28-Jun-07 RMS Defined character code for tape mark 14-Nov-04 RMS Added column binary support 27-Oct-04 RMS Added maximum instruction length @@ -247,6 +248,7 @@ #define MD_NORM 0 /* normal (move) */ #define MD_WM 1 /* word mark (load) */ #define MD_BIN 2 /* binary */ +#define MD_BOOT 4 /* boot read */ /* Indicator characters */ diff --git a/I1401/i1401_dp.c b/I1401/i1401_dp.c index cb80dd86..81739b94 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-2005, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -191,8 +191,10 @@ if (sim_is_active (&dp_unit[0])) { /* ctlr busy? */ 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 */ +if (ADDR_ERR (BS)) /* DCF in memory? */ + return STOP_WRAP; +if (M[dcf] & BBIT) /* impl sel? cyl 8-4-2 */ + drv = M[dcf + DCF_SEC + 1] & 0xE; else drv = M[dcf] & DIGIT; /* get drive sel */ if ((drv == 0) || (drv & 1) || (drv > BCD_ZERO)) /* bad drive #? */ return STOP_INVDSK; @@ -206,12 +208,14 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ 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? */ + if (diff < 0) /* error? */ + return STOP_INVDSC; 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; + if (uptr->CYL < 0) + uptr->CYL = 0; else if (uptr->CYL >= DP_NUMCY) { /* too big? */ uptr->CYL = 0; /* system hangs */ return STOP_INVDCY; @@ -231,11 +235,14 @@ if (fnc == FNC_SEEK) { /* seek? */ } BS = dcf + DCF_LEN; /* full DCF */ -if (ADDR_ERR (BS)) return STOP_WRAP; /* DCF in memory? */ +if (ADDR_ERR (BS)) /* DCF in memory? */ + return STOP_WRAP; cnt = dp_get_cnt (dcf); /* get count */ -if (cnt < 0) return STOP_INVDCN; /* bad count? */ +if (cnt < 0) /* bad count? */ + return STOP_INVDCN; -if (fnc >= FNC_WOFF) return STOP_INVDFN; /* invalid func */ +if (fnc >= FNC_WOFF) /* invalid func */ + return STOP_INVDFN; if (mod == BCD_W) { /* write? */ if (fnc == FNC_CHECK) { /* write check? */ qwc = 1; /* special read */ @@ -246,7 +253,8 @@ if (mod == BCD_W) { /* write? */ fnc = fnc + FNC_WOFF; /* change to write */ } } -else if (mod == BCD_R) dp_lastf = fnc; /* read? save func */ +else if (mod == BCD_R) /* read? save func */ + dp_lastf = fnc; else return STOP_INVM; /* other? error */ switch (fnc) { /* case on function */ @@ -256,18 +264,22 @@ switch (fnc) { /* case on function */ /* fall thru */ case FNC_READ: /* read */ psec = dp_fndsec (uptr, sec, dcf); /* find sector */ - if (psec < 0) CRETIOE (iochk, STOP_INVDAD); /* addr cmp error? */ + if (psec < 0) /* addr cmp error? */ + CRETIOE (iochk, STOP_INVDAD); 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 */ + if (cnt < 0) /* bad count? */ + return STOP_INVDCN; + if (qzr) /* zero latch? done */ + break; 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 */ + if (r = dp_nexsec (uptr, psec, dcf)) /* find next */ + break; } break; /* done, clean up */ @@ -282,8 +294,10 @@ switch (fnc) { /* case on function */ 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 */ + if (cnt < 0) /* bad count? */ + return STOP_INVDCN; + if (qzr) /* zero latch? done */ + break; psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } break; /* done, clean up */ @@ -293,29 +307,36 @@ switch (fnc) { /* case on function */ /* fall through */ case FNC_WRITE: /* read */ psec = dp_fndsec (uptr, sec, dcf); /* find sector */ - if (psec < 0) CRETIOE (iochk, STOP_INVDAD); /* addr cmp error? */ + if (psec < 0) /* addr cmp error? */ + CRETIOE (iochk, STOP_INVDAD); 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 */ + if (r = dp_wrsec (uptr, psec, flg)) /* write data */ + break; + if (qzr) /* zero latch? done */ + break; 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 */ + if (r = dp_nexsec (uptr, psec, dcf)) /* find next */ + break; } break; /* done, clean up */ case FNC_WRTRK: /* write track */ if ((uptr->flags & UNIT_WAE) == 0) /* enabled? */ - return STOP_WRADIS; + 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 */ + if (r = dp_wradr (uptr, psec, flg)) /* write addr */ + break; + if (r = dp_wrsec (uptr, psec, flg)) /* write data */ + break; + if (qzr) /* zero latch? done */ + break; psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } break; /* done, clean up */ @@ -326,7 +347,8 @@ switch (fnc) { /* case on function */ if (r == SCPE_OK) { /* normal so far? */ BS++; /* advance BS */ - if (ADDR_ERR (BS)) return STOP_WRAP; /* address error? */ + if (ADDR_ERR (BS)) /* address error? */ + return STOP_WRAP; if (M[BS - 1] != (WM + BCD_GRPMRK)) { /* GM + WM at end? */ ind[IN_LNG] = ind[IN_DSK] = 1; /* no, error */ r = STOP_INVDLN; @@ -366,10 +388,12 @@ for (i = 0; i < DP_ADDR; i++) { /* copy address */ return STOP_WRCHKE; } } - else if (flg) M[BS] = ac & CHAR; /* load mode */ + else if (flg) /* load mode */ + M[BS] = ac & CHAR; else M[BS] = (M[BS] & WM) | (ac & CHAR); /* move mode */ ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; + if (ADDR_ERR (BS)) + return STOP_WRAP; } return SCPE_OK; } @@ -395,10 +419,13 @@ for (i = 0; i < lim; i++) { /* copy data */ return STOP_WRCHKE; } } - else if (flg) M[BS] = *ap & (WM | CHAR); /* load mode */ + else if (flg) /* load mode */ + M[BS] = *ap & (WM | CHAR); else M[BS] = (M[BS] & WM) | (*ap & CHAR); /* word mode */ - ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; + ap++; /* adv ptrs */ + BS++; + if (ADDR_ERR (BS)) + return STOP_WRAP; } return SCPE_OK; } @@ -417,11 +444,16 @@ for (i = 0; i < DP_ADDR; i++) { /* copy address */ ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ return STOP_INVDLN; } - if (flg) *ap = M[BS] & (WM | CHAR); /* L? copy WM */ + if (flg) /* L? copy WM */ + *ap = M[BS] & (WM | CHAR); 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; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; + da++; /* adv ptrs */ + ap++; + BS++; + if (ADDR_ERR (BS)) + return STOP_WRAP; } return SCPE_OK; } @@ -441,11 +473,16 @@ for (i = 0; i < lim; i++) { /* copy data */ ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ return STOP_INVDLN; } - if (flg) *ap = M[BS] & (WM | CHAR); /* load, copy WM */ + if (flg) /* load, copy WM */ + *ap = M[BS] & (WM | CHAR); 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; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; + da++; /* adv ptrs */ + ap++; + BS++; + if (ADDR_ERR (BS)) + return STOP_WRAP; } return SCPE_OK; } @@ -460,14 +497,18 @@ 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 */ +if (dp_zeroad (ap)) /* addr zero? ok */ + return psec; +if (dp_cmp_ad (ap, dcf)) /* addr comp? ok */ + return psec; 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? */ + if (dp_zeroad (ap)) /* no implicit match */ + continue; + if (dp_cmp_ad (ap, dcf)) /* match? */ + return psec; } ind[IN_UNA] = ind[IN_DSK] = 1; /* no match */ return -1; @@ -482,8 +523,10 @@ 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 */ + if (dp_zeroad (ap)) /* addr zero? ok */ + return SCPE_OK; + if (dp_cmp_ad (ap, dcf)) /* addr comp? ok */ + return SCPE_OK; } ind[IN_UNA] = ind[IN_DSK] = 1; /* no, error */ return STOP_INVDAD; @@ -496,7 +539,8 @@ 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 */ + if (*ap & CHAR) /* nonzero? lose */ + return FALSE; } return TRUE; /* all zeroes */ } @@ -535,7 +579,8 @@ 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? */ + if ((c == 0) || (c > BCD_ZERO)) /* invalid? */ + return -1; r = (r * 10) + bcd_to_bin[c]; /* cvt to bin */ ad++; /* next digit */ } @@ -550,7 +595,8 @@ 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? */ + if (flg) /* load mode? */ + M[ad + len - 1] = bin_to_bcd[r]; else M[ad + len - 1] = (M[ad + len - 1] & WM) | bin_to_bcd[r]; val = val / 10; } @@ -562,8 +608,10 @@ return; 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 */ +if (cnt < 0) /* bad count? */ + return -1; +if (cnt == 0) /* 0 => 1000 */ + return 1000; return cnt; } @@ -573,7 +621,8 @@ 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; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; da++; } return; @@ -585,7 +634,8 @@ t_stat dp_reset (DEVICE *dptr) { int32 i; -for (i = 0; i < DP_NUMDR; i++) dp_unit[i].CYL = 0; /* reset cylinder */ +for (i = 0; i < DP_NUMDR; i++) /* reset cylinder */ + dp_unit[i].CYL = 0; 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; diff --git a/I1401/i1401_iq.c b/I1401/i1401_iq.c index 93be3152..2d299e4d 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-2005, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -93,33 +93,40 @@ 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 */ +/* if (ind[IN_INR] == 0) /* return if no req */ + return SCPE_OK; 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 (stop_cpu) /* interrupt? */ + return SCPE_STOP; } - if (t < SCPE_KFLAG) return t; /* if not char, err */ + if (t < SCPE_KFLAG) /* if not char, err */ + return t; t = t & 0177; - if ((t == '\r') || (t == '\n')) break; + 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"); + 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; + if ((t == '~') && (wm_seen == 0)) + wm_seen = WM; else { M[BS] = wm_seen | ascii2bcd (t); wm_seen = 0; } } else M[BS] = (M[BS] & WM) | ascii2bcd (t); - if (!wm_seen) BS++; + if (!wm_seen) + BS++; if (ADDR_ERR (BS)) { BS = BA | (BS % MAXMEMSIZE); return STOP_NXM; @@ -132,11 +139,14 @@ switch (mod) { /* case on mod */ 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"); - if (conv_old) sim_putchar ('~'); + if (i && ((i % INQ_WIDTH) == 0)) + puts_tty ("\r\n"); + if (conv_old) + sim_putchar ('~'); else sim_putchar ('`'); } - if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); + if (i && ((i % INQ_WIDTH) == 0)) + puts_tty ("\r\n"); sim_putchar (bcd2ascii (t & CHAR, use_h)); if (ADDR_ERR (BS)) { BS = BA | (BS % MAXMEMSIZE); @@ -160,8 +170,10 @@ 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 */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return temp; +if ((temp & 0177) == inq_char) /* set indicator */ + ind[IN_INR] = 1; return SCPE_OK; } @@ -169,8 +181,10 @@ return SCPE_OK; void puts_tty (char *cptr) { -if (cptr == NULL) return; -while (*cptr != 0) sim_putchar (*cptr++); +if (cptr == NULL) + return; +while (*cptr != 0) + sim_putchar (*cptr++); return; } diff --git a/I1401/i1401_lp.c b/I1401/i1401_lp.c index 5bd4b5d8..f15ab913 100644 --- a/I1401/i1401_lp.c +++ b/I1401/i1401_lp.c @@ -1,6 +1,6 @@ /* i1401_lp.c: IBM 1403 line printer simulator - Copyright (c) 1993-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -114,7 +114,8 @@ int32 i, t, wm, sup; char *bcd2asc; 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) /* attached? */ + return SCPE_UNATT; wm = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_SQUARE); sup = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_S); ind[IN_LPT] = 0; /* clear error */ @@ -123,14 +124,18 @@ if (conv_old) /* get print chain */ else bcd2asc = pch_table[GET_PCHAIN (lpt_unit.flags)]; 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 */ + if (wm) /* wmarks -> 1 or sp */ + lbuf[i] = (t & WM)? '1': ' '; else lbuf[i] = bcd2asc[t & CHAR]; /* normal */ } lbuf[LPT_WIDTH] = 0; /* trailing null */ -for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--) lbuf[i] = 0; +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 */ +if (lines) /* cc action? do it */ + space (lines, lflag); +else if (sup == 0) /* default? 1 line */ + space (1, FALSE); else { fputc ('\r', lpt_unit.fileref); /* sup -> overprint */ lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ @@ -140,7 +145,8 @@ if (ferror (lpt_unit.fileref)) { /* error? */ ind[IN_LPT] = 1; perror ("Line printer I/O error"); clearerr (lpt_unit.fileref); - if (iochk) return SCPE_IOERR; + if (iochk) + return SCPE_IOERR; } return SCPE_OK; } @@ -165,7 +171,8 @@ mod = mod & DIGIT; /* isolate value */ switch (action) { case 0: /* to channel now */ - if ((mod == 0) || (mod > 12) || CHP (mod, cct[cctptr])) return SCPE_OK; + 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); @@ -181,11 +188,13 @@ switch (action) { return SCPE_OK; case 2: /* space now */ - if (mod <= 3) return space (mod, FALSE); + 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 */ + if ((mod == 0) || (mod > 12)) /* check channel */ + return SCPE_OK; ind[IN_CC9] = ind[IN_CC12] = 0; for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ if (CHP (mod, cct[(cctptr + i) % cctlnt])) { @@ -211,12 +220,14 @@ t_stat space (int32 count, int32 sflag) { int32 i; -if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; +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); + 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 */ diff --git a/I1401/i1401_mt.c b/I1401/i1401_mt.c index 65edf46a..2da50d84 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,13 @@ mt 7-track magtape + 11-Jul-08 RMS Added -n (no rewind) option to BOOT (from Van Snyder) + Added tape mark detect to diagnostic read (from Bob Abeles) + Added tape mark detect in multi-character records (from Bob Abeles) + Fixed memory leak in tape rewind-unload op (from Bob Abeles) + Fixed bug, BOOT ignores GM+WM in memory (from Bob Abeles) + Fixed handling of indicators (from Bob Abeles) + Fixed bug to mask input to 6b on read (from Bob Abeles) 07-Jul-07 RMS Removed restriction on load-mode binary tape 28-Jun-07 RMS Revised read tape mark behavior based on real hardware (found by Van Snyder) @@ -70,6 +77,24 @@ 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. + + (Notes on indicators from Bob Abeles) + The 1401 implements a "tape indicator" latch per tape drive. When a + 1401 branch-on-indicator instruction addresses the "end-of-reel" + indicator, the 1401 addresses the "tape indicator" latch in the + currently selected and ready tape drive. The tape drive itself resets + its "tape indicator" latch only when a tape unload occurs. Tape + unload may be initiated by push button control or by the CPU "Rewind + Tape and Unload" instruction. The tape drive sets the "tape + indicator" latch when in write status and the end-of-reel reflective + strip photocell is activated. The CPU resets the "tape indicator" + latch in the selected and ready tape drive when the "end-of-reel" + indicator is tested by a branch-on-indicator instruction. If no tape + drive is selected, or the currently selected tape drive is not ready, + the "end-of-reel" indicator will appear to be off and no "tape + indicator" latch will be reset. The CPU sets the "tape indicator" + latch in the selected and ready tape drive whenever it reads a tape- + mark character in the first character position of a record. */ #include "i1401_defs.h" @@ -77,8 +102,10 @@ #define MT_NUMDR 7 /* #drives */ #define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */ +#define IND u3 /* drive indicator */ uint8 dbuf[MT_MAXFR]; /* tape buffer */ +int32 mt_sel = 0; /* selected unit */ extern uint8 M[]; /* memory */ extern int32 ind[64]; @@ -88,8 +115,10 @@ extern FILE *sim_deb; t_stat mt_reset (DEVICE *dptr); t_stat mt_boot (int32 unitno, DEVICE *dptr); +t_stat mt_attach (UNIT *uptr, char *cp); +t_stat mt_detach (UNIT *uptr); t_stat mt_map_status (t_stat st); -UNIT *get_unit (int32 unit); +UNIT *mt_sel_unit (int32 unit); /* MT data structures @@ -116,8 +145,13 @@ UNIT mt_unit[] = { }; REG mt_reg[] = { - { FLDATA (END, ind[IN_END], 0) }, { FLDATA (ERR, ind[IN_TAP], 0) }, + { FLDATA (IND1, mt_unit[1].IND, 0) }, + { FLDATA (IND2, mt_unit[2].IND, 0) }, + { FLDATA (IND3, mt_unit[3].IND, 0) }, + { FLDATA (IND4, mt_unit[4].IND, 0) }, + { FLDATA (IND5, mt_unit[5].IND, 0) }, + { FLDATA (IND6, mt_unit[6].IND, 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 }, @@ -141,7 +175,7 @@ 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_boot, &mt_attach, &mt_detach, NULL, DEV_DEBUG }; @@ -149,58 +183,74 @@ DEVICE mt_dev = { Inputs: unit = unit character + flag = normal, word mark, binary, or boot mode mod = modifier character Outputs: status = status */ -t_stat mt_func (int32 unit, int32 mod) +t_stat mt_func (int32 unit, int32 flag, int32 mod) { t_mtrlnt tbc; UNIT *uptr; t_stat st; -if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ +ind[IN_TAP] = 0; /* clear error */ +if ((uptr = mt_sel_unit (unit)) == NULL) /* sel unit, save */ + return STOP_INVMTU; /* (not valid) */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_UNATT; switch (mod) { /* case on modifier */ case BCD_A: /* diagnostic read */ - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, - ">>MT%d: diagnostic read\n", unit); - ind[IN_END] = 0; /* clear end of file */ - st = sim_tape_sprecf (uptr, &tbc); /* space fwd */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: diagnostic read\n", unit); + st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */ + if (st != MTSE_TMK) { /* not tmk? */ + if (st == MTSE_RECE) /* rec in error? */ + ind[IN_TAP] = 1; + else if (st != MTSE_OK) { /* stop on error */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ", stopped by status = %d\n", st); + break; + } + if (!(flag & MD_BIN) && /* BCD tape and */ + ((dbuf[0] & CHAR) == BCD_TAPMRK)) /* first char TMK? */ + uptr->IND = 1; /* set indicator */ + } break; case BCD_B: /* backspace */ - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, - ">>MT%d: backspace\n", unit); - ind[IN_END] = 0; /* clear end of file */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: backspace\n", unit); st = sim_tape_sprecr (uptr, &tbc); /* space rev */ break; /* end case */ case BCD_E: /* erase = nop */ - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, - ">>MT%d: erase\n", unit); - if (sim_tape_wrp (uptr)) return STOP_MTL; + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: erase\n", unit); + if (sim_tape_wrp (uptr)) /* write protected? */ + return STOP_MTL; return SCPE_OK; case BCD_M: /* write tapemark */ - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, - ">>MT%d: write tape mark\n", unit); + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: write tape mark\n", unit); st = sim_tape_wrtmk (uptr); /* write tmk */ break; case BCD_R: /* rewind */ - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, - ">>MT%d: rewind\n", unit); + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: rewind\n", unit); sim_tape_rewind (uptr); /* update position */ return SCPE_OK; case BCD_U: /* unload */ - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, - ">>MT%d: rewind and unload\n", unit); + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: rewind and unload\n", unit); sim_tape_rewind (uptr); /* update position */ - return detach_unit (uptr); /* detach */ + st = mt_detach (uptr); /* detach */ + break; default: return STOP_INVM; @@ -213,7 +263,7 @@ return mt_map_status (st); Inputs: unit = unit character - flag = normal, word mark, or binary mode + flag = normal, word mark, binary, or boot mode mod = modifier character Outputs: status = status @@ -233,30 +283,34 @@ t_stat st; t_bool passed_eot; UNIT *uptr; -if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ +ind[IN_TAP] = 0; /* clear error */ +if ((uptr = mt_sel_unit (unit)) == NULL) /* sel unit, save */ + return STOP_INVMTU; /* (not valid) */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_UNATT; switch (mod) { case BCD_R: /* read */ if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, ">>MT%d: read from %d", unit, BS); - 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_TMK) { /* tape mark? */ - ind[IN_END] = 1; /* set indicator */ - tbc = 1; /* one char read */ - dbuf[0] = BCD_TAPMRK; /* BCD tapemark */ - } - else if (st != MTSE_OK) { /* stop on error */ - if (DEBUG_PRS (mt_dev)) - fprintf (sim_deb, ", stopped by status = %d\n", st); - break; + if (st != MTSE_TMK) { /* not tmk? */ + if (st == MTSE_RECE) /* rec in error? */ + ind[IN_TAP] = 1; + else if (st != MTSE_OK) { /* stop on error */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ", stopped by status = %d\n", st); + break; + } + if (!(flag & MD_BIN) && /* BCD tape and */ + ((dbuf[0] & CHAR) == BCD_TAPMRK)) /* first char TMK? */ + uptr->IND = 1; /* set indicator */ } for (i = 0; i < tbc; i++) { /* loop thru buf */ - if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */ + if (!(flag & MD_BOOT) && /* not boot? check */ + (M[BS] == (BCD_GRPMRK + WM))) { /* GWM in memory? */ if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, " to %d, stopped by GMWM\n", BS); BS++; /* incr BS */ @@ -266,7 +320,7 @@ switch (mod) { } return SCPE_OK; /* done */ } - t = dbuf[i]; /* get char */ + t = dbuf[i] & CHAR; /* get char, strip parity */ if (!(flag & MD_BIN) && (t == BCD_ALT)) /* BCD mode alt blank? */ t = BCD_BLANK; /* real blank */ if (flag & MD_WM) { /* word mk mode? */ @@ -278,14 +332,16 @@ switch (mod) { } } else M[BS] = (M[BS] & WM) | (t & CHAR); /* preserve mem WM */ - if (!wm_seen) BS++; + 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 */ + if (flag & MD_WM) /* LCA: clear WM */ + M[BS] = BCD_GRPMRK; else M[BS] = (M[BS] & WM) | BCD_GRPMRK; /* MCW: save WM */ } if (DEBUG_PRS (mt_dev)) @@ -298,11 +354,12 @@ switch (mod) { break; case BCD_W: - if (sim_tape_wrp (uptr)) return STOP_MTL; /* locked? */ - if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ;/* eor? */ + if (sim_tape_wrp (uptr)) /* locked? */ + return STOP_MTL; + if (M[BS] == (BCD_GRPMRK + WM)) /* eor? */ + return STOP_MTZ; if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, ">>MT%d: write from %d", unit, BS); - ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) { if ((t & WM) && (flag & MD_WM)) /* WM in wm mode? */ dbuf[tbc++] = BCD_WM; @@ -314,7 +371,8 @@ switch (mod) { return STOP_WRAP; } } - if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, " to %d\n", BS - 1); + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, " to %d\n", BS - 1); passed_eot = sim_tape_eot (uptr); /* passed EOT? */ st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */ if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */ @@ -332,11 +390,13 @@ switch (mod) { return mt_map_status (st); } -/* Get unit pointer from unit number */ +/* Select unit - save selection if valid, return unit pointer */ -UNIT *get_unit (int32 unit) +UNIT *mt_sel_unit (int32 unit) { -if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL; +if ((unit <= 0) || (unit >= MT_NUMDR)) + return NULL; +mt_sel = unit; /* save selected unit */ return mt_dev.units + unit; } @@ -360,12 +420,14 @@ switch (st) { return SCPE_MTRLNT; case MTSE_TMK: /* end of file */ - ind[IN_END] = 1; /* set end mark */ + if (mt_sel != 0) + mt_unit[mt_sel].IND = 1; /* set indicator latch */ break; case MTSE_IOERR: /* IO error */ ind[IN_TAP] = 1; /* set error */ - if (iochk) return SCPE_IOERR; + if (iochk) + return SCPE_IOERR; break; case MTSE_RECE: /* record in error */ @@ -380,6 +442,21 @@ switch (st) { return SCPE_OK; } +/* Test and reset selected tape drive's indicator latch */ + +t_bool mt_testind () +{ +t_bool v; + +if (mt_sel == 0) /* any mt selected? */ + return FALSE; +if (!(mt_unit[mt_sel].flags & UNIT_ATT)) /* attached? */ + return FALSE; +v = mt_unit[mt_sel].IND; /* save latch */ +mt_unit[mt_sel].IND = 0; /* reset latch */ +return v; +} + /* Reset routine */ t_stat mt_reset (DEVICE *dptr) @@ -387,22 +464,48 @@ 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); +for (i = 0; i < MT_NUMDR; i++) { /* per drive resets */ + if (uptr = mt_sel_unit (i)) { + MT_CLR_PNU (uptr); /* clear pos flag */ + uptr->IND = 0; /* clear ind latch */ + } } -ind[IN_END] = ind[IN_TAP] = 0; /* clear indicators */ +ind[IN_TAP] = 0; /* clear mt err ind */ +mt_sel = 0; /* clear unit select */ return SCPE_OK; } -/* Bootstrap routine */ +/* Bootstrap routine + + The 1401 Reference manual states, "...tape data starts loading at address 001 + and continues until an inter-record gap is sensed." GM+WM in memory is ignored. +*/ t_stat mt_boot (int32 unitno, DEVICE *dptr) { extern int32 saved_IS; +extern int32 sim_switches; -sim_tape_rewind (&mt_unit[unitno]); /* force rewind */ +if ((sim_switches & SWMASK ('N')) == 0) /* unless -n */ + sim_tape_rewind (&mt_unit[unitno]); /* force rewind */ BS = 1; /* set BS = 001 */ -mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */ +mt_io (unitno, MD_WM + MD_BOOT, BCD_R); /* LDA %U1 001 R */ saved_IS = 1; return SCPE_OK; } + +/* Attach routine */ + +t_stat mt_attach (UNIT *uptr, char *cp) +{ +uptr->IND = 0; /* reset indicator latch */ +return sim_tape_attach (uptr, cp); /* tape unit attach */ +} + +/* Detach routine */ + +t_stat mt_detach (UNIT *uptr) +{ +uptr->IND = 0; /* reset indicator latch */ +return sim_tape_detach (uptr); /* tape unit detach */ +} diff --git a/I1401/i1401_sys.c b/I1401/i1401_sys.c index cd4c19da..43387338 100644 --- a/I1401/i1401_sys.c +++ b/I1401/i1401_sys.c @@ -1,6 +1,6 @@ /* i1401_sys.c: IBM 1401 simulator interface - Copyright (c) 1993-2005, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -132,31 +132,37 @@ t_stat r; extern int32 cctlnt, cctptr, cct[CCT_LNT]; char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; +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; + 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; + 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; + if (ptr >= CCT_LNT) + return SCPE_FMT; cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; +if (ptr == 0) + return SCPE_FMT; cctlnt = ptr; cctptr = 0; -for (rpt = 0; rpt < cctlnt; rpt++) cct[rpt] = cctbuf[rpt]; +for (rpt = 0; rpt < cctlnt; rpt++) + cct[rpt] = cctbuf[rpt]; return SCPE_OK; } @@ -182,8 +188,10 @@ extern int32 hun_table[64], ten_table[64], one_table[64]; addr = hun_table[dig[0] & CHAR] + ten_table[dig[1]] + one_table[dig[2]]; xa = (addr >> V_INDEX) & M_INDEX; -if (xa) fprintf (of, " %d,%d", addr & ADDRMASK, ((xa - (X1 >> V_INDEX)) / 5) + 1); -else if (addr >= MAXMEMSIZE) fprintf (of, " %d*", addr & ADDRMASK); +if (xa) + fprintf (of, " %d,%d", addr & ADDRMASK, ((xa - (X1 >> V_INDEX)) / 5) + 1); +else if (addr >= MAXMEMSIZE) + fprintf (of, " %d*", addr & ADDRMASK); else fprintf (of, " %d", addr); return; } @@ -197,9 +205,10 @@ t_bool use_h = sw & SWMASK ('F'); fprintf (of, "DCW @%c", bcd2ascii (op, use_h)); /* assume it's data */ for (i = 1; i < sim_emax; i++) { - if (val[i] & WM) break; - fprintf (of, "%c", bcd2ascii (val[i], use_h)); - } + if (val[i] & WM) + break; + fprintf (of, "%c", bcd2ascii (val[i], use_h)); + } fprintf (of, "@"); return -(i - 1); /* return # chars */ } @@ -230,7 +239,8 @@ extern int32 op_table[64], len_table[9]; if (sw & SWMASK ('C')) { /* character? */ t = val[0]; if (uptr->flags & UNIT_BCD) { - if (t & WM) fputc (wmch, of); + if (t & WM) + fputc (wmch, of); fputc (bcd2ascii (t & CHAR, use_h), of); } else fprintf (of, FMTASC (t & 0177)); @@ -250,23 +260,31 @@ if (sw & SWMASK ('S')) { /* string? */ i = 0; do { t = val[i++]; - if (t & WM) fputc (wmch, of); + if (t & WM) + fputc (wmch, of); fputc (bcd2ascii (t & CHAR, use_h), of); } while ((i < LINE_LNT) && ((val[i] & WM) == 0)); return -(i - 1); } -if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; +if ((sw & SWMASK ('M')) == 0) + return SCPE_ARG; -if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */ +if ((val[0] & WM) == 0) /* WM under op? */ + return STOP_NOWM; op = val[0]& CHAR; /* isolate op */ -if (opcode[op] == NULL) return dcw (of, op, val, sw); /* invalid op */ +if (opcode[op] == NULL) /* invalid op */ + return dcw (of, op, val, sw); flags = op_table[op]; /* get flags */ for (ilnt = 1; ilnt < sim_emax; ilnt++) { /* find inst lnt */ - if (val[ilnt] & WM) break; + if (val[ilnt] & WM) + break; } -if ((flags & (NOWM | HNOP)) && (ilnt > 7)) ilnt = 7; /* cs, swm, h, nop? */ -else if ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) ilnt = 4; -else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */ +if ((flags & (NOWM | HNOP)) && (ilnt > 7)) /* cs, swm, h, nop? */ + ilnt = 7; +else if ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) + ilnt = 4; +else if ((ilnt > 8) && (op != OP_NOP)) /* cap length */ + ilnt = 8; if (ilnt == 3) { /* lnt = 3? */ fprintf (of, "DSA"); /* assume DSA */ fprint_addr (of, val); /* print addr */ @@ -283,7 +301,8 @@ if (ilnt > 2) { /* A address? */ bcd2ascii (val[3], sw)); else fprint_addr (of, &val[1]); } -if (ilnt > 5) fprint_addr (of, &val[4]); /* B address? */ +if (ilnt > 5) /* B address? */ + fprint_addr (of, &val[4]); if ((ilnt == 2) || (ilnt == 5) || (ilnt == 8)) /* d character? */ fprintf (of, " '%c", bcd2ascii (val[ilnt - 1], use_h)); return -(ilnt - 1); /* return # chars */ @@ -299,14 +318,17 @@ char gbuf[CBUFSIZE]; cptr = get_glyph (cptr, gbuf, ','); /* get address */ addr = get_uint (gbuf, 10, MAXMEMSIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; +if (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 ((r != SCPE_OK) || (index == 0)) + return SCPE_ARG; } else index = 0; -if (*cptr != 0) return SCPE_ARG; +if (*cptr != 0) + return SCPE_ARG; val[0] = store_addr_h (addr); val[1] = store_addr_t (addr) | (index << V_ZONE); val[2] = store_addr_u (addr); @@ -317,8 +339,9 @@ 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; +if ((cptr[0] != '%') || (cptr[3] != 0) || + !isalnum (cptr[1]) || !isalnum (cptr[2])) + return SCPE_ARG; val[0] = BCD_PERCNT; val[1] = ascii2bcd (cptr[1]); val[2] = ascii2bcd (cptr[2]); @@ -352,24 +375,30 @@ if ((sw & SWMASK ('C')) || (sw & SWMASK ('S')) || (*cptr == wmch) || wm_seen = 0; for (i = 0; (i < sim_emax) && (*cptr != 0); ) { t = *cptr++; /* get character */ - if (cflag && (wm_seen == 0) && (t == wmch)) wm_seen = WM; + if (cflag && (wm_seen == 0) && (t == wmch)) + wm_seen = WM; else if (uptr->flags & UNIT_BCD) { - if (t < 040) return SCPE_ARG; + if (t < 040) + return SCPE_ARG; val[i++] = ascii2bcd (t) | wm_seen; wm_seen = 0; } else val[i++] = t; } - if ((i == 0) || wm_seen) return SCPE_ARG; + if ((i == 0) || wm_seen) + return SCPE_ARG; return -(i - 1); } -if (cflag == 0) return SCPE_ARG; /* CPU only */ +if (cflag == 0) /* CPU only */ + return SCPE_ARG; 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 (opcode[op] && strcmp (gbuf, opcode[op]) == 0) + break; } -if (op >= 64) return SCPE_ARG; /* successful? */ +if (op >= 64) /* successful? */ + return SCPE_ARG; 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)) || @@ -389,8 +418,10 @@ if ((gbuf[0] == '\'') || (gbuf[0] == '"')) { /* d character? */ val[ilnt] = ascii2bcd (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; +else if (gbuf[0] != 0) /* not done? */ + return SCPE_ARG; +if ((op_table[op] & len_table[ilnt]) == 0) + return STOP_INVL; return -(ilnt - 1); } @@ -398,8 +429,10 @@ return -(ilnt - 1); int32 bcd2ascii (int32 c, t_bool use_h) { -if (conv_old) return bcd_to_ascii_old[c]; -else if (use_h) return bcd_to_ascii_h[c]; +if (conv_old) + return bcd_to_ascii_old[c]; +else if (use_h) + return bcd_to_ascii_h[c]; else return bcd_to_ascii_a[c]; } @@ -407,6 +440,7 @@ else return bcd_to_ascii_a[c]; int32 ascii2bcd (int32 c) { -if (conv_old) return ascii_to_bcd_old[c]; +if (conv_old) + return ascii_to_bcd_old[c]; else return ascii_to_bcd[c]; } diff --git a/I1620/i1620_cd.c b/I1620/i1620_cd.c index df19931e..d7e7cb7a 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-2007, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -238,12 +238,14 @@ switch (op) { /* case on op */ case OP_RN: /* read numeric */ r = cdr_read (); /* fill reader buf */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; 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 */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; cdc = 0; } M[pa] = cdc; /* store digit */ @@ -253,12 +255,14 @@ switch (op) { /* case on op */ case OP_RA: /* read alphameric */ r = cdr_read (); /* fill reader buf */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; 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 */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; cdc = 0; }; M[pa] = (M[pa] & FLAG) | (cdc & DIGIT); /* store 2 digits */ @@ -286,9 +290,11 @@ if ((cdr_unit.flags & UNIT_ATT) == 0) { /* attached? */ return SCPE_UNATT; } -for (i = 0; i < CD_LEN + 2; i++) cdr_buf[i] = ' '; /* clear buffer */ +for (i = 0; i < CD_LEN + 2; i++) /* clear buffer */ + cdr_buf[i] = ' '; fgets (cdr_buf, CD_LEN + 2, cdr_unit.fileref); /* read card */ -if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */ +if (feof (cdr_unit.fileref)) /* eof? */ + return STOP_NOCD; if (ferror (cdr_unit.fileref)) { /* error? */ ind[IN_RDCHK] = 1; /* set read check */ perror ("CDR I/O error"); @@ -297,7 +303,8 @@ if (ferror (cdr_unit.fileref)) { /* error? */ } 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 */ +if (feof (cdr_unit.fileref)) /* eof? set last */ + ind[IN_LAST] = 1; fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); /* "backspace" */ return SCPE_OK; } @@ -332,7 +339,8 @@ old_io_stop = io_stop; io_stop = 1; r = cdr (OP_RN, 0, 0, 0); /* read card @ 0 */ io_stop = old_io_stop; -if (r != SCPE_OK) return r; /* error? */ +if (r != SCPE_OK) /* error? */ + return r; saved_PC = BOOT_START; return SCPE_OK; } @@ -391,7 +399,8 @@ 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; + 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 */ @@ -404,7 +413,8 @@ while (ncd-- >= 0) { /* until done */ PP (pa); /* incr mem addr */ } r = cdp_write (len); /* punch card */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; } return SCPE_OK; } @@ -418,7 +428,8 @@ if ((cdp_unit.flags & UNIT_ATT) == 0) { /* attached? */ return SCPE_UNATT; } -while ((len > 0) && (cdp_buf[len - 1] == ' ')) --len; /* trim spaces */ +while ((len > 0) && (cdp_buf[len - 1] == ' ')) /* trim spaces */ + --len; cdp_buf[len] = '\n'; /* newline, null */ cdp_buf[len + 1] = 0; diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c index eba47e6e..bf3d761e 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-2006, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -463,8 +463,10 @@ t_stat reason; /* Restore saved state */ PC = saved_PC; -if ((cpu_unit.flags & IF_IA) == 0) iae = 0; -if ((cpu_unit.flags & IF_IDX) == 0) idxe = idxb = 0; +if ((cpu_unit.flags & IF_IA) == 0) + iae = 0; +if ((cpu_unit.flags & IF_IDX) == 0) + idxe = idxb = 0; upd_ind (); /* update indicators */ reason = 0; @@ -474,7 +476,8 @@ while (reason == 0) { /* loop until halted */ saved_PC = PC; /* commit prev instr */ if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; } if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ @@ -507,7 +510,8 @@ while (reason == 0) { /* loop until halted */ 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 (reason != SCPE_OK) /* stop if error */ + break; } if (flags & (IF_VQA | IF_4QA | IF_NQX)) { /* need Q? */ reason = get_addr (qla, /* get Q addr */ @@ -519,11 +523,13 @@ while (reason == 0) { /* loop until halted */ break; } } - else if (flags & IF_IMM) QAR = qla; /* immediate? */ + else if (flags & IF_IMM) /* immediate? */ + QAR = qla; if (hst_lnt) { /* history enabled? */ hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; + 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++) @@ -662,7 +668,8 @@ while (reason == 0) { /* loop until halted */ if ((ind[t] != 0) ^ (op == OP_BNI)) { /* ind value correct? */ BRANCH (PAR); /* branch */ } - if (ind_table[t] > 0) ind[t] = 0; /* reset if needed */ + if (ind_table[t] > 0) /* reset if needed */ + ind[t] = 0; break; /* Add/subtract/compare - P,Q are valid */ @@ -670,22 +677,28 @@ while (reason == 0) { /* loop until halted */ 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; + if (sta == ADD_CARRY) /* cout => ovflo */ + ind[IN_OVF] = 1; + 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; + if (sta == ADD_CARRY) /* cout => ovflo */ + ind[IN_OVF] = 1; + 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; + if (sta == ADD_CARRY) /* cout => ovflo */ + ind[IN_OVF] = 1; + if (ar_stop && ind[IN_OVF]) + reason = STOP_OVERFL; break; /* Multiply - P,Q are valid */ @@ -733,7 +746,7 @@ while (reason == 0) { /* loop until halted */ 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 */ + reason = SCPE_OK; /* no */ break; /* Edit special feature instructions */ @@ -810,7 +823,8 @@ while (reason == 0) { /* loop until halted */ break; } reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 0, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; + if (ar_stop && ind[IN_OVF]) + reason = STOP_OVERFL; BRANCH (PAR); /* branch to P */ break; @@ -821,7 +835,8 @@ while (reason == 0) { /* loop until halted */ break; } reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 3, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; + if (ar_stop && ind[IN_OVF]) + reason = STOP_OVERFL; BRANCH (PAR); /* branch to P */ break; @@ -834,7 +849,8 @@ while (reason == 0) { /* loop until halted */ break; } reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 0, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; + if (ar_stop && ind[IN_OVF]) + reason = STOP_OVERFL; if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */ BRANCH (PAR); /* branch */ } @@ -847,7 +863,8 @@ while (reason == 0) { /* loop until halted */ break; } reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 3, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; + if (ar_stop && ind[IN_OVF]) + reason = STOP_OVERFL; if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */ BRANCH (PAR); /* branch */ } @@ -936,30 +953,36 @@ while (reason == 0) { /* loop until halted */ 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; + 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; + 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; + 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; + 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; + if (ar_stop && ind[IN_OVF]) + reason = STOP_FPDVZ; + if (ar_stop && ind[IN_EXPCHK]) + reason = STOP_EXPCHK; break; case OP_FSL: @@ -1014,7 +1037,8 @@ 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 */ +if (BAD_DIGIT (d) || BAD_DIGIT (d1)) /* bad? error */ + return -1; return ((d * 10) + d1); /* cvt to binary */ } @@ -1040,7 +1064,8 @@ 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) /* init indirect */ + indir = FLAG; else indir = 0; cnt = 0; /* count depth */ @@ -1054,13 +1079,16 @@ do { 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 < 0) /* -? 10's comp */ + addr = addr + 100000; } - if (addr >= (int32) MEMSIZE) return STOP_INVPAD; /* invalid addr? */ + if (addr >= (int32) MEMSIZE) /* invalid addr? */ + return STOP_INVPAD; alast = addr; /* new address */ lnt = ADDR_LEN; /* std len */ } while (indir && (cnt++ < ind_max)); -if (cnt > ind_max) return STOP_INVPIA; /* indir too deep? */ +if (cnt > ind_max) /* indir too deep? */ + return STOP_INVPIA; *reta = addr; /* return address */ return SCPE_OK; } @@ -1080,15 +1108,18 @@ 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? */ +if (signok && (M[alast] & FLAG)) /* signed? */ + sign = 1; 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 */ + if (BAD_DIGIT (t)) /* bad? error */ + return STOP_INVDIG; addr = (addr * 10) + t; /* cvt to bin */ } while (--lnt > 0); -if (sign) *val = -addr; /* minus? */ +if (sign) /* minus? */ + *val = -addr; else *val = addr; return SCPE_OK; } @@ -1107,9 +1138,11 @@ t_stat get_idx (uint32 aidx) { int32 i, idx; -if (idxe == 0) return -1; /* indexing off? */ +if (idxe == 0) /* indexing off? */ + return -1; for (i = idx = 0; i < 3; i++) { /* 3 flags worth */ - if (M[aidx] & FLAG) idx = idx | (1 << i); /* test flag */ + if (M[aidx] & FLAG) /* test flag */ + idx = idx | (1 << i); MM (aidx); /* next digit */ } return idx; @@ -1125,8 +1158,10 @@ 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? */ +if (!idxe) /* off? */ + ind[IN_IXN] = 1; +else if (!idxb) /* on, band A? */ + ind[IN_IXA] = 1; else ind[IN_IXB] = 1; /* no, band B */ return; } @@ -1142,8 +1177,10 @@ 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) */ + MM (d); /* decr mem addrs */ + MM (s); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while (((t & FLAG) == 0) || (cnt <= skp)); /* until flag */ return SCPE_OK; } @@ -1156,10 +1193,13 @@ 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) */ + PP (d); /* incr mem addrs */ + PP (s); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } -if (cpy) M[d] = M[s] & (FLAG | DIGIT); /* copy rec mark */ +if (cpy) /* copy rec mark */ + M[d] = M[s] & (FLAG | DIGIT); return SCPE_OK; } @@ -1173,7 +1213,8 @@ 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 */ + MM (d); /* decr mem addrs */ + MM (s); } M[d] = (M[s] & DIGIT) | FLAG; /* set flag on last */ return SCPE_OK; @@ -1187,9 +1228,11 @@ uint32 cnt = 0; M[d] = M[s] & DIGIT; /* first w/o flag */ do { - MM (d); MM (s); /* decr mem addrs */ + MM (d); /* decr mem addrs */ + MM (s); M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while ((M[d] & FLAG) == 0); /* until src flag */ return SCPE_OK; } @@ -1211,7 +1254,8 @@ do { 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) */ + if (cnt >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; cnt = cnt + 2; } while (t == 0); /* until dst flag */ M[d] = M[d] | FLAG; /* set flag at end */ @@ -1234,7 +1278,8 @@ do { 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) */ + if (cnt >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; cnt = cnt + 2; } while ((t & FLAG) == 0); /* until src flag */ return SCPE_OK; @@ -1274,28 +1319,36 @@ dst = M[d] & DIGIT; /* 1st digits */ src = M[s] & DIGIT; if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ return STOP_INVDIG; -if (comp) src = 10 - src; /* complement? */ +if (comp) /* complement? */ + src = 10 - src; res = add_one_digit (dst, src, &cry); /* add */ -if (sto) M[d] = (M[d] & FLAG) | res; /* store */ +if (sto) /* store */ + M[d] = (M[d] & FLAG) | res; 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 */ + if (src_f) /* src done? src = 0 */ + src = 0; else { src = M[s] & DIGIT; /* get src digit */ - if (cnt >= skp) src_f = M[s] & FLAG; /* get src flag */ + if (cnt >= skp) /* get src flag */ + src_f = M[s] & FLAG; MM (s); /* decr src addr */ } if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ return STOP_INVDIG; - if (comp) src = 9 - src; /* complement? */ + if (comp) /* complement? */ + src = 9 - src; res = add_one_digit (dst, src, &cry); /* add */ - if (sto) M[d] = dst_f | res; /* store */ + if (sto) /* store */ + M[d] = dst_f | res; MM (d); /* decr dst addr */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while (dst_f == 0); /* until dst done */ -if (!src_f) ind[IN_OVF] = 1; /* !src done? ovf */ +if (!src_f) /* !src done? ovf */ + ind[IN_OVF] = 1; if (comp && !cry && !ind[IN_EZ]) { /* recomp needed? */ ind[IN_HP] = ind[IN_HP] ^ 1; /* flip indicator */ if (sto) { /* storing? */ @@ -1310,8 +1363,10 @@ if (comp && !cry && !ind[IN_EZ]) { /* recomp needed? */ *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 (ind[IN_EZ]) /* res = 0? clr HP */ + ind[IN_HP] = 0; +if (!comp && cry) /* set status */ + *sta = ADD_CARRY; return SCPE_OK; } @@ -1330,8 +1385,10 @@ 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 (res & FLAG) /* carry out? */ + *cry = 1; +if (res & DIGIT) /* nz? clr ind */ + ind[IN_EZ] = 0; return res & DIGIT; } @@ -1369,14 +1426,19 @@ pro = PROD_AREA + PROD_AREA_LEN - 1; /* product ptr */ do { mpyd = M[mpy] & DIGIT; /* multiplier digit */ mpyf = (M[mpy] & FLAG) && (cnt != 0); /* last digit flag */ - if (BAD_DIGIT (mpyd)) return STOP_INVDIG; /* bad? */ + if (BAD_DIGIT (mpyd)) /* bad? */ + return STOP_INVDIG; 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) */ + if (r != SCPE_OK) /* error? */ + return r; + MM (mpy); /* decr mpyr, prod addrs */ + MM (pro); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while ((mpyf == 0) || (cnt <= 1)); /* until mpyr flag */ -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ +if (ind[IN_EZ]) /* res = 0? clr HP */ + ind[IN_HP] = 0; M[PROD_AREA + PROD_AREA_LEN - 1] |= sign; /* set final sign */ return SCPE_OK; } @@ -1422,32 +1484,42 @@ 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? */ + if (BAD_DIGIT (mpcd)) /* bad? */ + return STOP_INVDIG; 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? */ + if (BAD_DIGIT (mptd)) /* bad? */ + return STOP_INVDIG; prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ + if (BAD_DIGIT (prod)) /* bad? */ + return STOP_INVDIG; 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? */ + if (BAD_DIGIT (mptd)) /* bad? */ + return STOP_INVDIG; prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ + if (BAD_DIGIT (prod)) /* bad? */ + return STOP_INVDIG; 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? */ + if (BAD_DIGIT (prod)) /* bad? */ + return STOP_INVDIG; M[prwp] = add_one_digit (prod, 0, &cry); /* add cry */ - if (cryc++ > MEMSIZE) return STOP_FWRAP; + if (cryc++ > MEMSIZE) + return STOP_FWRAP; } - MM (mpcp); MM (prop); /* decr mpc, prod ptrs */ - if (mpcc++ > MEMSIZE) return STOP_FWRAP; + MM (mpcp); /* decr mpc, prod ptrs */ + MM (prop); + if (mpcc++ > MEMSIZE) + return STOP_FWRAP; } while ((mpcf == 0) || (mpcc <= 1)); /* until mpcf flag */ -if (last) M[prop] = M[prop] | FLAG; /* flag high product */ +if (last) /* flag high product */ + M[prop] = M[prop] | FLAG; return SCPE_OK; } @@ -1601,7 +1673,8 @@ ind[IN_HP] = (quos == 0); /* set indicators */ do { r = div_one_digit (dvd, dvr, 10, &quod, &quop); /* dev quo digit */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; /* Store quotient digit and advance current dividend pointer */ @@ -1614,13 +1687,15 @@ do { first = FALSE; } else M[quop] = quod; /* store quo digit */ - if (quod) *ez = 0; /* if nz, clr ind */ + if (quod) /* if nz, clr ind */ + *ez = 0; 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 */ +if (*ez) /* res = 0? clr HP */ + ind[IN_HP] = 0; M[PROD_AREA + PROD_AREA_LEN - 1] |= dvds; /* remainder sign */ M[quop] = M[quop] | quos; /* quotient sign */ PP (quop); /* high remainder */ @@ -1659,20 +1734,26 @@ for (qd = 0; qd < max; qd++) { /* devel quo dig */ cry = 1; /* carry in = 1 */ do { /* sub dvr fm dvd */ dvdd = M[dvdp] & DIGIT; /* dividend digit */ - if (BAD_DIGIT (dvdd)) return STOP_INVDIG; /* bad? */ + if (BAD_DIGIT (dvdd)) /* bad? */ + return STOP_INVDIG; dvrd = M[dvrp] & DIGIT; /* divisor digit */ dvrf = M[dvrp] & FLAG; /* divisor flag */ - if (BAD_DIGIT (dvrd)) return STOP_INVDIG; /* bad? */ + if (BAD_DIGIT (dvrd)) /* bad? */ + return STOP_INVDIG; M[dvdp] = add_one_digit (dvdd, 9 - dvrd, &cry); /* sub */ - MM (dvdp); MM (dvrp); /* decr ptrs */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ + MM (dvdp); /* decr ptrs */ + MM (dvrp); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } 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? */ + if (BAD_DIGIT (dvdd)) /* bad? */ + return STOP_INVDIG; M[dvdp] = add_one_digit (dvdd, 9, &cry); /* sub */ } - if (!cry) break; /* !cry = negative */ + if (!cry) /* !cry = negative */ + break; } /* Add back the divisor to correct for the negative result */ @@ -1686,13 +1767,16 @@ do { 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 */ + MM (dvdp); /* decr ptrs */ + MM (dvrp); + cnt++; } 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 */ +if (quop != NULL) /* set quo addr */ + *quop = dvdp; *quod = qd; /* set quo digit */ return SCPE_OK; } @@ -1718,9 +1802,12 @@ 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) */ + if (M[d] & DIGIT) /* nz dig? clr ind */ + ind[IN_EZ] = 0; + MM (d); /* decr pointers */ + MM (s); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ return SCPE_OK; } @@ -1734,9 +1821,12 @@ 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) */ + if (M[d] & DIGIT) /* nz dig? clr ind */ + ind[IN_EZ] = 0; + MM (d); /* decr pointers */ + MM (s); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ return SCPE_OK; } @@ -1750,9 +1840,12 @@ 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) */ + if (M[d] & DIGIT) /* nz dig? clr ind */ + ind[IN_EZ] = 0; + MM (d); /* decr pointers */ + MM (s); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ return SCPE_OK; } @@ -1766,9 +1859,12 @@ 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) */ + if (M[d] & DIGIT) /* nz dig? clr ind */ + ind[IN_EZ] = 0; + MM (d); /* decr pointers */ + MM (s); + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while ((t & FLAG) == 0); /* until src flag */ return SCPE_OK; } @@ -1803,18 +1899,22 @@ 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? */ + if (r != SCPE_OK) /* err? */ + return r; 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; + if (tblc++ > MEMSIZE) + return STOP_FWRAP; } while (tf == 0); /* until flag */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ + if (cnt++ >= MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while (sf == 0); -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ +if (ind[IN_EZ]) /* res = 0? clr HP */ + ind[IN_HP] = 0; M[PROD_AREA + PROD_AREA_LEN - 1] |= sign; /* set sign */ return SCPE_OK; } @@ -1848,7 +1948,8 @@ 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 (r != SCPE_OK) /* error? */ + return r; if (first) { /* first pass? */ if (octd >= 8) { /* overflow? */ ind[IN_OVF] = 1; /* set indicator */ @@ -1858,20 +1959,25 @@ for ( ;; ) { first = FALSE; } else M[d] = octd; /* store quo digit */ - if (octd) *ez = 0; /* if nz, clr ind */ + if (octd) /* if nz, clr ind */ + *ez = 0; PP (tbl); /* incr tbl addr */ - if ((M[tbl] & REC_MARK) == REC_MARK) break; /* record mark? */ + if ((M[tbl] & REC_MARK) == REC_MARK) /* record mark? */ + break; PP (tbl); /* skip flag */ - if ((M[tbl] & REC_MARK) == REC_MARK) break; /* record mark? */ + if ((M[tbl] & REC_MARK) == REC_MARK) /* record mark? */ + break; 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 (ctr++ > MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } -if (*ez) ind[IN_HP] = 0; /* res = 0? clr HP */ +if (*ez) /* res = 0? clr HP */ + ind[IN_HP] = 0; M[d] = M[d] | sign; /* set result sign */ return SCPE_OK; } @@ -1885,16 +1991,20 @@ static t_bool one_time = TRUE; PR1 = IR2 = 1; /* invalidate PR1,IR2 */ ind[0] = 0; -for (i = IN_SW4 + 1; i < NUM_IND; i++) ind[i] = 0; /* init indicators */ -if (cpu_unit.flags & IF_IA) iae = 1; /* indirect enabled? */ +for (i = IN_SW4 + 1; i < NUM_IND; i++) /* init indicators */ + ind[i] = 0; +if (cpu_unit.flags & IF_IA) /* indirect enabled? */ + iae = 1; else iae = 0; idxe = idxb = 0; /* indexing off */ pcq_r = find_reg ("PCQ", NULL, dptr); /* init old PC queue */ -if (pcq_r) pcq_r->qptr = 0; +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 */ +if (one_time) /* set default tables */ + cpu_set_table (&cpu_unit, 1, NULL, NULL); one_time = FALSE; return SCPE_OK; } @@ -1903,8 +2013,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & (FLAG | DIGIT); +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & (FLAG | DIGIT); return SCPE_OK; } @@ -1912,7 +2024,8 @@ 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 & (FLAG | DIGIT); return SCPE_OK; } @@ -1926,11 +2039,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } @@ -1938,8 +2053,9 @@ 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 (val) + cpu_unit.flags = (cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MII_OPT)) | + IF_DIV | IF_IA | IF_EDT; else cpu_unit.flags = cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MI_OPT); return SCPE_OK; } @@ -1950,7 +2066,8 @@ 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"); + if (sim_log) + fprintf (sim_log, "Feature is standard on 1620 Model 2\n"); return SCPE_NOFNC; } return SCPE_OK; @@ -1962,7 +2079,8 @@ 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"); + if (sim_log) + fprintf (sim_log, "Feature is not available on 1620 Model 1\n"); return SCPE_NOFNC; } return SCPE_OK; @@ -1972,7 +2090,8 @@ return SCPE_OK; t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (saved_PC & 1) return SCPE_NOFNC; +if (saved_PC & 1) + return SCPE_NOFNC; PR1 = saved_PC; return SCPE_OK; } @@ -2000,12 +2119,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].vld = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -2014,7 +2135,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -2032,14 +2154,17 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ diff --git a/I1620/i1620_defs.h b/I1620/i1620_defs.h index 6f32af3a..ec671606 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-2005, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/I1620/i1620_dp.c b/I1620/i1620_dp.c index a99e90bb..7dde5d31 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-2005, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -150,7 +150,8 @@ int32 drv, sa, sec, psec, cnt, qwc, qnr, t; UNIT *uptr; t_stat r; -if (pa & 1) return STOP_INVDCF; /* dcf must be even */ +if (pa & 1) /* dcf must be even */ + return STOP_INVDCF; 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 */ @@ -159,7 +160,8 @@ if (((dp_unit[0].flags & UNIT_DIS) == 0) && /* only drive 0? */ (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? */ +if (drv >= DP_NUMDR) /* invalid? */ + return STOP_INVDRV; uptr = dp_dev.units + drv; /* get unit ptr */ if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ ind[IN_DERR] = 1; /* no, error */ @@ -170,7 +172,8 @@ 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? */ + if (f1 != FNC_SEEK) /* really? */ + return STOP_INVFNC; uptr->CYL = (sec / (DP_NUMSF * DP_NUMSC)) % /* set cyl # */ DP_NUMCY; return SCPE_OK; /* done! */ @@ -178,13 +181,17 @@ if (op == OP_K) { /* seek? */ 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? */ +if ((t < 0) || (t & 1)) /* bad address? */ + return STOP_INVDBA; 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 */ +if (f1 >= FNC_WRI) /* invalid func? */ + return STOP_INVFNC; +if (op == OP_RN) /* read? set wch */ + qwc = f1 & FNC_WCH; else if (op == OP_WN) { /* write? */ - if (op & FNC_WCH) return STOP_INVFNC; /* cant check */ + if (op & FNC_WCH) /* cant check */ + return STOP_INVFNC; f1 = f1 + FNC_WRI; /* offset fnc */ } else return STOP_INVFNC; /* not R or W */ @@ -193,9 +200,11 @@ 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? */ + if (cnt <= 0) /* bad count? */ + return STOP_INVDCN; psec = dp_fndsec (uptr, sec, TRUE); /* find sector */ - if (psec < 0) CRETIOE (dp_stop, STOP_DACERR); /* error? */ + if (psec < 0) /* error? */ + CRETIOE (dp_stop, STOP_DACERR); do { /* loop on count */ if (r = dp_rdsec (uptr, psec, qnr, qwc)) /* read sector */ break; @@ -216,12 +225,16 @@ switch (f1 & ~(FNC_WCH | FNC_NRL)) { /* case on function */ break; /* done, clean up */ case FNC_SEC + FNC_WRI: /* write */ - if (cnt <= 0) return STOP_INVDCN; /* bad count? */ + if (cnt <= 0) /* bad count? */ + return STOP_INVDCN; psec = dp_fndsec (uptr, sec, FALSE); /* find sector */ - if (psec < 0) CRETIOE (dp_stop, STOP_DACERR); /* error? */ + if (psec < 0) /* error? */ + CRETIOE (dp_stop, STOP_DACERR); 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 */ + if (r = dp_tstgm (M[dp_ba], qnr)) /* start with gm? */ + break; + if (r = dp_wrsec (uptr, psec, qnr)) /* write data */ + break; sec++; psec++; /* next sector */ } while ((--cnt > 0) && ((r = dp_nexsec (uptr, sec, psec, FALSE)) == SCPE_OK)); @@ -232,9 +245,12 @@ switch (f1 & ~(FNC_WCH | FNC_NRL)) { /* case on function */ 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 */ + if (r = dp_tstgm (M[dp_ba], qnr)) /* start with gm? */ + break; + if (r = dp_wradr (uptr, psec, qnr)) /* write addr */ + break; + if (r = dp_wrsec (uptr, psec, qnr)) /* write data */ + break; psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } break; /* done, clean up */ @@ -250,7 +266,8 @@ if ((r == SCPE_OK) && !qnr) { /* eor check? */ } } if ((r != SCPE_OK) && /* error? */ - (dp_stop || !ind[IN_DERR])) return r; /* iochk or stop? */ + (dp_stop || !ind[IN_DERR])) /* iochk or stop? */ + return r; return SCPE_OK; /* continue */ } @@ -282,7 +299,8 @@ for (i = 0; i < DP_ADDR; i++) { /* copy/check addr */ } } else M[dp_ba] = ad & (FLAG | DIGIT); /* store digit */ - if (dp_tstgm (*ap, qnr)) return STOP_WRLERR; /* grp mrk on disk? */ + if (dp_tstgm (*ap, qnr)) /* grp mrk on disk? */ + return STOP_WRLERR; ap++; PP (dp_ba); /* adv ptrs */ } return SCPE_OK; @@ -306,7 +324,8 @@ for (i = 0; i < DP_DATA; i++) { /* copy data */ } } else M[dp_ba] = *ap & (FLAG | DIGIT); /* flag + digit */ - if (dp_tstgm (*ap, qnr)) return STOP_WRLERR; /* grp mrk on disk? */ + if (dp_tstgm (*ap, qnr)) /* grp mrk on disk? */ + return STOP_WRLERR; ap++; PP (dp_ba); /* adv ptrs */ } return SCPE_OK; @@ -322,7 +341,8 @@ 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 (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 */ @@ -342,7 +362,8 @@ 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 (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 */ @@ -362,10 +383,12 @@ 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 */ +if (dp_zeroad (ap)) /* addr zero? ok */ + return psec; dskad = dp_cvt_ad (ap); /* cvt addr */ if (dskad == sec) { /* match? */ - if (rd || ((*ap & FLAG) == 0)) return psec; /* read or !wprot? */ + if (rd || ((*ap & FLAG) == 0)) /* read or !wprot? */ + return psec; ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ return -1; } @@ -373,10 +396,12 @@ 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_zeroad (ap)) /* no implicit match */ + continue; dskad = dp_cvt_ad (ap); /* cvt addr */ if (dskad == sec) { /* match? */ - if (rd || ((*ap & FLAG) == 0)) return psec; /* read or !wprot? */ + if (rd || ((*ap & FLAG) == 0)) /* read or !wprot? */ + return psec; ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ return -1; } @@ -395,10 +420,12 @@ 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 */ + if (dp_zeroad (ap)) /* addr zero? ok */ + return SCPE_OK; dskad = dp_cvt_ad (ap); /* cvt addr */ if ((dskad == sec) && /* match? */ - (rd || ((*ap & FLAG) == 0))) return SCPE_OK; /* read or !wprot? */ + (rd || ((*ap & FLAG) == 0))) /* read or !wprot? */ + return SCPE_OK; ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ return STOP_DACERR; } @@ -413,7 +440,8 @@ 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 */ + if (*ap & DIGIT) /* nonzero? lose */ + return FALSE; } return TRUE; /* all zeroes */ } @@ -438,7 +466,8 @@ 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? */ + if (BAD_DIGIT (c)) /* bad digit? */ + return -1; r = (r * 10) + c; /* bcd to binary */ } return r; @@ -463,7 +492,8 @@ int32 r; for (r = 0; len > 0; len--) { /* loop thru char */ c = M[ad] & DIGIT; /* get digit */ - if (BAD_DIGIT (c)) return -1; /* invalid? */ + if (BAD_DIGIT (c)) /* invalid? */ + return -1; r = (r * 10) + c; /* cvt to bin */ PP (ad); /* next digit */ } @@ -476,7 +506,8 @@ 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; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; da++; } return; @@ -488,7 +519,8 @@ t_stat dp_reset (DEVICE *dptr) { int32 i; -for (i = 0; i < DP_NUMDR; i++) dp_unit[i].CYL = 0; /* reset cylinder */ +for (i = 0; i < DP_NUMDR; i++) /* reset cylinder */ + dp_unit[i].CYL = 0; 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 6ce4c4b2..d9d9b510 100644 --- a/I1620/i1620_fp.c +++ b/I1620/i1620_fp.c @@ -71,11 +71,13 @@ uint8 d0, d1, esign; esign = M[ad] & FLAG; /* get exp sign */ d0 = M[ad] & DIGIT; /* get exp lo digit */ MM (ad); -if ((M[ad] & FLAG) == 0) return STOP_FPMF; /* no flag on hi exp? */ +if ((M[ad] & FLAG) == 0) /* no flag on hi exp? */ + return STOP_FPMF; 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? */ +if (BAD_DIGIT (d1) || BAD_DIGIT (d0)) /* exp bad dig? */ + return STOP_INVDIG; 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 +89,12 @@ 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) /* unpack dst */ + return r; +if ((r = fp_unpack (sad, sfp)) != SCPE_OK) /* unpack src */ + return r; +if (sfp->lnt != dfp->lnt) /* lnts must be equal */ + return STOP_FPUNL; return SCPE_OK; } @@ -103,7 +108,8 @@ 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? */ + if (fp->exp < 0) /* underflow? */ + return fp_zero (fp); mad = fp->addr; for (i = 0; i < fp->lnt; i++) { /* mant = 99...99 */ M[mad] = (M[mad] & FLAG) | 9; @@ -123,11 +129,13 @@ void fp_rsh (FPA *fp, uint32 n) { uint32 i, sad, dad; -if (n == 0) return; /* zero? done */ +if (n == 0) /* zero? done */ + return; 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; + if (i >= (fp->lnt - n)) + M[dad] = M[dad] & FLAG; else M[dad] = (M[dad] & FLAG) | (M[sad] & DIGIT); MM (dad); MM (sad); @@ -180,7 +188,8 @@ for (l = 1; l <= FP_LMAX; l++) { /* scan to get length */ if (d) z = 0; /* non-zero? */ if ((l != 1) && (M[ad] & FLAG)) { /* flag past first dig? */ *lnt = l; /* set returns */ - if (zro) *zro = z; + if (zro) + *zro = z; return SCPE_OK; } MM (ad); @@ -194,7 +203,8 @@ 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]) /* clr/set sign */ + M[d] = M[d] & ~FLAG; else M[d] = M[d] | FLAG; for (i = 0; i < l; i++) { /* copy src */ M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* preserve flags */ @@ -215,8 +225,10 @@ 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) /* >? done */ + return 1; + if (dd < sd) /* = ((int32) dfp.lnt))) { /* src = 0, or too small? */ - if (dfp.zero) return fp_zero (&dfp); /* res = dst, zero? */ + if (dfp.zero) /* res = dst, zero? */ + return fp_zero (&dfp); 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? */ + if (sfp.zero) /* res = src, zero? */ + return fp_zero (&dfp); 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); @@ -271,7 +286,8 @@ if (dif > 0) { /* src denormalized? */ MM (sad); } } -if (r != SCPE_OK) return r; /* add error? */ +if (r != SCPE_OK) /* add error? */ + return r; hi = ADDR_S (dfp.addr, dfp.lnt - 1); /* addr of hi digit */ if (sta == ADD_CARRY) { /* carry out? */ @@ -281,7 +297,8 @@ if (sta == ADD_CARRY) { /* carry out? */ 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 if (ind[IN_EZ]) /* result zero? */ + return fp_zero (&dfp); else { while ((M[hi] & DIGIT) == 0) { /* until normalized */ fp_lsh_1 (&dfp); /* left shift */ @@ -301,11 +318,14 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; +if (sfp.zero || dfp.zero) /* either zero? */ + return fp_zero (&dfp); r = mul_field (dfp.addr, sfp.addr); /* mul, set EZ, HP */ -if (r != SCPE_OK) return r; +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 */ @@ -329,12 +349,14 @@ int32 ez; t_stat r; r = fp_unpack_two (d, s, &dfp, &sfp); /* unpack operands */ -if (r != SCPE_OK) return r; /* error? */ +if (r != SCPE_OK) /* error? */ + return r; 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? */ +if (dfp.zero) /* divide into zero? */ + return fp_zero (&dfp); for (i = 0; i < PROD_AREA_LEN; i++) /* clear prod area */ M[PROD_AREA + i] = 0; @@ -349,10 +371,13 @@ else { dfp.exp = dfp.exp - sfp.exp; /* res exp = diff */ } r = xmt_divd (pad, dfp.addr); /* xmt dividend */ -if (r != SCPE_OK) return r; /* error? */ +if (r != SCPE_OK) /* error? */ + return r; r = div_field (a100ml, sfp.addr, &ez); /* divide fractions */ -if (r != SCPE_OK) return r; /* error? */ -if (ez) return fp_zero (&dfp); /* result zero? */ +if (r != SCPE_OK) /* error? */ + return r; +if (ez) /* result zero? */ + return fp_zero (&dfp); ind[IN_HP] = ((dfp.sign ^ sfp.sign) == 0); /* set res sign */ ind[IN_EZ] = 0; /* not zero */ @@ -368,7 +393,8 @@ t_stat fp_fsr (uint32 d, uint32 s) uint32 cnt; uint8 t; -if (d == s) return SCPE_OK; /* no move? */ +if (d == s) /* no move? */ + return SCPE_OK; cnt = 0; M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* move 1st wo flag */ @@ -376,7 +402,8 @@ do { MM (d); /* decr ptrs */ MM (s); t = M[d] = M[s] & (FLAG | DIGIT); /* copy others */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ + if (cnt++ > MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while ((t & FLAG) == 0); /* until src flag */ cnt = 0; @@ -384,7 +411,8 @@ do { MM (d); /* decr pointer */ t = M[d]; /* save old val */ M[d] = 0; /* zero field */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ + if (cnt++ > MEMSIZE) /* (stop runaway) */ + return STOP_FWRAP; } while ((t & FLAG) == 0); /* until dst flag */ return SCPE_OK; } @@ -397,10 +425,12 @@ uint32 i, lnt; uint8 sign; t_stat r; -if (d == s) return SCPE_OK; +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? */ +if (r != SCPE_OK) /* error? */ + return r; 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 */ @@ -414,6 +444,7 @@ while ((M[d] & FLAG) == 0) { /* until flag */ M[d] = 0; /* clear field */ PP (d); } -if (sign) M[d] = FLAG; /* -? zero under sign */ +if (sign) /* -? zero under sign */ + M[d] = FLAG; return SCPE_OK; } diff --git a/I1620/i1620_lp.c b/I1620/i1620_lp.c index daa2152f..4254bf09 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-2007, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -164,7 +164,8 @@ switch (op) { /* decode op */ case OP_K: /* control */ lpt_savctrl = (f0 << 4) | f1; /* form ctrl */ - if (lpt_savctrl & K_IMM) return lpt_print (); /* immediate? */ + if (lpt_savctrl & K_IMM) /* immediate? */ + return lpt_print (); break; case OP_DN: @@ -177,18 +178,21 @@ switch (op) { /* decode op */ 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? */ + if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ + break; lpc = alp_to_lpt[(z << 4) | d]; /* translate pair */ if (lpc < 0) { /* bad char? */ ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; } 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; + if (r != SCPE_OK) + return r; } return sta; @@ -213,18 +217,21 @@ 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; + ((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 */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; } 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; + if (r != SCPE_OK) + return r; } return sta; } @@ -264,12 +271,16 @@ 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; + 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; +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); @@ -322,7 +333,8 @@ void lpt_buf_init (void) int32 i; lpt_bptr = 0; -for (i = 0; i < LPT_WIDTH + 1; i++) lpt_buf[i] = 0; +for (i = 0; i < LPT_WIDTH + 1; i++) + lpt_buf[i] = 0; return; } diff --git a/I1620/i1620_pt.c b/I1620/i1620_pt.c index b564f40c..dff4ac06 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-2005, Robert M Supnik + Copyright (c) 2002-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -222,14 +222,16 @@ 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 (r != SCPE_OK) /* error? */ + return r; if (ptc & PT_EL) { /* end record? */ M[pa] = REC_MARK; /* store rec mark */ return sta; /* done */ } if (bad_par[ptc]) { /* bad parity? */ ind[IN_RDCHK] = 1; /* set read check */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; M[pa] = 0; /* store zero */ } else M[pa] = ptr_to_num[ptc]; /* translate, store */ @@ -240,7 +242,8 @@ switch (op) { /* case on op */ 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 (r != SCPE_OK) /* error? */ + return r; if (ptc & PT_EL) { /* end record? */ M[pa] = REC_MARK; /* store rec mark */ M[pa - 1] = 0; @@ -249,7 +252,8 @@ switch (op) { /* case on op */ mc = ptr_to_alp[ptc]; /* translate */ if (bad_par[ptc] || (mc < 0)) { /* bad par or char? */ ind[IN_RDCHK] = 1; /* set read check */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; mc = 0; /* store blank */ } M[pa] = (M[pa] & FLAG) | (mc & DIGIT); /* store 2 digits */ @@ -273,7 +277,8 @@ uint32 i; uint8 ptc; t_stat r, sta; -if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO; +if ((cpu_unit.flags & IF_BIN) == 0) + return STOP_INVIO; sta = SCPE_OK; switch (op) { /* case on op */ @@ -281,7 +286,8 @@ 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 (r != SCPE_OK) /* error? */ + return r; if (ptc & PT_EL) { /* end record? */ M[pa] = REC_MARK; /* store rec mark */ M[pa - 1] = 0; @@ -289,7 +295,8 @@ switch (op) { /* case on op */ } if (bad_par[ptc]) { /* bad parity? */ ind[IN_RDCHK] = 1; /* set read check */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; } M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */ M[pa - 1] = (M[pa - 1] & FLAG) | @@ -358,7 +365,8 @@ t_stat ptr_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 saved_PC; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; saved_PC = BOOT_START; return SCPE_OK; } @@ -397,7 +405,8 @@ switch (op) { /* decode op */ CRETIOE (io_stop, STOP_INVCHR); } r = ptp_write (ptc); /* write char */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; pa = ADDR_A (pa, 2); /* incr mem addr */ } break; @@ -428,9 +437,11 @@ switch (op) { /* decode op */ 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 */ + if (bad_par[ptc]) /* set parity */ + ptc = ptc | PT_C; r = ptp_write (ptc); /* write char */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; pa = ADDR_A (pa, 2); /* incr mem addr */ } break; @@ -457,7 +468,8 @@ for (i = 0; i < MEMSIZE; i++) { /* stop runaway */ ((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? */ + if (r != SCPE_OK) /* error? */ + return r; PP (pa); /* incr mem addr */ } return STOP_RWRAP; diff --git a/I1620/i1620_sys.c b/I1620/i1620_sys.c index 3c62370e..40ec70d3 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-2005, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -127,31 +127,37 @@ t_stat r; extern int32 cct_lnt, cct_ptr, cct[CCT_LNT]; char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; +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; + 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; + 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; + if (ptr >= CCT_LNT) + return SCPE_FMT; cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; +if (ptr == 0) + return SCPE_FMT; cct_lnt = ptr; cct_ptr = 0; -for (rpt = 0; rpt < cct_lnt; rpt++) cct[rpt] = cctbuf[rpt]; +for (rpt = 0; rpt < cct_lnt; rpt++) + cct[rpt] = cctbuf[rpt]; return SCPE_OK; } @@ -286,7 +292,8 @@ if ((cpu_unit.flags & IF_IDX) && flg) { /* indexing? */ idx = idx | (1 << i); dig[ADDR_LEN - 2 - i] = dig[ADDR_LEN - 2 - i] & ~FLAG; } - if (idx) fprintf (of, "(%d)", idx); /* print */ + if (idx) /* print */ + fprintf (of, "(%d)", idx); } return; } @@ -312,10 +319,12 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, int32 pmp, qmp, i, c, d, any; uint32 op, qv, opfl; -if (uptr == NULL) uptr = &cpu_unit; +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 */ + if (addr & 1) /* must be even */ + return SCPE_ARG; c = ((val[0] & DIGIT) << 4) | (val[1] & DIGIT); if (alp_to_cdp[c] > 0) fprintf (of, "%c", alp_to_cdp[c]); @@ -325,9 +334,11 @@ if (sw & SWMASK ('C')) { /* character? */ else fprintf (of, FMTASC (val[0] & 0177)); return SCPE_OK; } -if ((uptr->flags & UNIT_BCD) == 0) return SCPE_ARG; /* CPU or disk? */ +if ((uptr->flags & UNIT_BCD) == 0) /* CPU or disk? */ + return SCPE_ARG; if (sw & SWMASK ('D')) { /* dump? */ - for (i = d = 0; i < LINE_LNT; i++) d = d | val[i]; + 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)? "_": " "); @@ -338,10 +349,12 @@ if (sw & SWMASK ('D')) { /* dump? */ return -(i - 1); } if (sw & SWMASK ('S')) { /* string? */ - if (addr & 1) return SCPE_ARG; /* must be even */ + if (addr & 1) /* must be even */ + return SCPE_ARG; 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; + if (alp_to_cdp[c] < 0) + break; fprintf (of, "%c", alp_to_cdp[c]); } if (i == 0) { @@ -350,24 +363,32 @@ if (sw & SWMASK ('S')) { /* string? */ } return -(i - 1); } -if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; +if ((sw & SWMASK ('M')) == 0) + return SCPE_ARG; -if (addr & 1) return SCPE_ARG; /* must be even */ +if (addr & 1) /* must be even */ + return SCPE_ARG; 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; + 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 */ +if ((val[0] | val[1]) & FLAG) /* flags force */ + pmp = qmp = 1; 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; + ((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 (opcode[i].str == NULL) + return SCPE_ARG; +if (I_GETQP (opfl) == I_M_QNP) /* Q no print? */ + qmp = 0; fprintf (of, opcode[i].str); /* print opcode */ if (I_GETPP (opfl) == I_M_PP) /* P required? */ @@ -383,7 +404,8 @@ 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); + if (!any) + fputc (',', of); any = 1; fprintf (of, "%d", i); } @@ -399,7 +421,8 @@ int32 i, sign = 0, addr, index; static int32 idx_tst[ADDR_LEN] = { 0, 4, 2, 1, 0 }; char *tptr; -if (*cptr == '+') cptr++; /* +? skip */ +if (*cptr == '+') /* +? skip */ + cptr++; else if (*cptr == '-') { /* -? skip, flag */ sign = 1; cptr++; @@ -414,16 +437,20 @@ if ((cpu_unit.flags & IF_IDX) && (flg & I_M_QX) && /* index allowed? */ 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 (*tptr++ != ')') + return SCPE_ARG; } else index = 0; -if (*tptr != 0) return SCPE_ARG; /* all done? */ +if (*tptr != 0) /* all done? */ + return SCPE_ARG; 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 (sign) /* set sign */ + val[ADDR_LEN - 1] = val[ADDR_LEN - 1] | FLAG; +if (flg & I_M_QM) /* set immediate */ + val[0] = val[0] | FLAG; return SCPE_OK; } @@ -445,13 +472,17 @@ 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)) /* absorb spaces */ + cptr++; if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */ - if ((t = *cptr & 0x7F) == 0) return SCPE_ARG; /* get char */ + if ((t = *cptr & 0x7F) == 0) /* get char */ + return SCPE_ARG; if (uptr->flags & UNIT_BCD) { /* BCD? */ - if (addr & 1) return SCPE_ARG; + if (addr & 1) + return SCPE_ARG; t = cdr_to_alp[t]; /* convert */ - if (t < 0) return SCPE_ARG; /* invalid? */ + if (t < 0) /* invalid? */ + return SCPE_ARG; val[0] = (t >> 4) & DIGIT; /* store */ val[1] = t & DIGIT; return -1; @@ -460,26 +491,33 @@ if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */ return SCPE_OK; } -if ((uptr->flags & UNIT_BCD) == 0) return SCPE_ARG; /* CPU or disk? */ +if ((uptr->flags & UNIT_BCD) == 0) /* CPU or disk? */ + return SCPE_ARG; if ((sw & SWMASK ('S')) || ((*cptr == '"') && cptr++)) { /* string? */ - if (addr & 1) return SCPE_ARG; /* must be even */ + if (addr & 1) /* must be even */ + return SCPE_ARG; 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? */ + if (t < 0) /* invalid? */ + return SCPE_ARG; val[i] = (t >> 4) & DIGIT; /* store */ val[i + 1] = t & DIGIT; } - if (i == 0) return SCPE_ARG; /* final check */ + if (i == 0) /* final check */ + return SCPE_ARG; return -(i - 1); } -if (addr & 1) return SCPE_ARG; /* even addr? */ +if (addr & 1) /* even addr? */ + return SCPE_ARG; 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 (strcmp (gbuf, opcode[i].str) == 0) + break; } -if (opcode[i].str == NULL) return SCPE_ARG; /* successful? */ +if (opcode[i].str == NULL) /* successful? */ + return SCPE_ARG; opfl = opcode[i].opv & 0xFF0000; /* get flags */ val[0] = (opcode[i].opv & 0xFF) / 10; /* store opcode */ val[1] = (opcode[i].opv & 0xFF) % 10; @@ -492,10 +530,11 @@ for (i = ADDR_LEN - 1; i >= 0; i--) { /* set P,Q fields */ 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; + 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; +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 */ @@ -503,25 +542,31 @@ if (I_GETQP (opfl) != I_M_QNP) { /* Q field allowed? */ if (parse_addr (gbuf, &val[I_Q], I_GETQF (opfl))) return SCPE_ARG; } - else if (I_GETQP (opfl) == I_M_QP) 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 */ + if ((t < '0') || (t > '9')) /* must be digit */ + return SCPE_ARG; 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? */ + if (la == '0') /* 10? */ + t = 10; + else if ((la == '1') && (*fptr == 0)) /* 11 & end field? */ + t = 11; else --fptr; /* dont lookahead */ } - if (t <= last) return SCPE_ARG; /* in order? */ + if (t <= last) /* in order? */ + return SCPE_ARG; val[t] = val[t] | FLAG; /* set flag */ last = t; /* continue */ } -if (*cptr != 0) return SCPE_ARG; +if (*cptr != 0) + return SCPE_ARG; return -(INST_LEN - 1); } diff --git a/I1620/i1620_tty.c b/I1620/i1620_tty.c index aacbbd0f..648beeef 100644 --- a/I1620/i1620_tty.c +++ b/I1620/i1620_tty.c @@ -1,6 +1,6 @@ /* i1620_tty.c: IBM 1620 typewriter - Copyright (c) 2002-2005, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -169,11 +169,13 @@ switch (op) { /* case on op */ tto_write ('\r'); break; case 3: /* backspace */ - if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; + 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; + if ((cpu_unit.flags & IF_MII) == 0) + return STOP_INVFNC; tto_write ('\n'); break; case 8: /* tab */ @@ -188,8 +190,10 @@ switch (op) { /* case on op */ 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? */ + if (r != SCPE_OK) /* error? */ + return r; + if (ttc == 0x7F) /* end record? */ + return SCPE_OK; M[pa] = ttc & (FLAG | DIGIT); /* store char */ PP (pa); /* incr mem addr */ } @@ -199,8 +203,10 @@ switch (op) { /* case on op */ 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? */ + if (r != SCPE_OK) /* error? */ + return r; + if (ttc == 0x7F) /* end record? */ + return SCPE_OK; 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 */ @@ -216,12 +222,14 @@ switch (op) { /* case on op */ case OP_WA: for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ d = M[pa] & DIGIT; /* get digit */ - if ((d & 0xA) == REC_MARK) return sta; /* 8-2 char? done */ + if ((d & 0xA) == REC_MARK) /* 8-2 char? done */ + return sta; 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 */ - if (io_stop) sta = STOP_INVCHR; /* set return status */ + if (io_stop) /* set return status */ + sta = STOP_INVCHR; } tto_write (ttc & 0x7F); /* write */ pa = ADDR_A (pa, 2); /* incr mem addr */ @@ -246,9 +254,12 @@ 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 == '~') || (raw == '`')) flg = FLAG; /* flag? mark */ + if (r != SCPE_OK) /* error? */ + return r; + if (raw == '\r') /* return? mark */ + *c = 0x7F; + else if ((raw == '~') || (raw == '`')) /* flag? mark */ + flg = FLAG; else if (cp = strchr (tti_to_num, raw)) /* legal? */ *c = ((int8) (cp - tti_to_num)) | flg; /* assemble char */ else raw = 007; /* beep! */ @@ -267,8 +278,10 @@ 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 */ + if (r != SCPE_OK) /* error? */ + return r; + if (raw == '\r') /* return? mark */ + *c = 0x7F; else if (tti_to_alp[raw] >= 0) /* legal char? */ *c = tti_to_alp[raw]; /* xlate */ else raw = 007; /* beep! */ @@ -286,7 +299,8 @@ 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? */ +if (t < SCPE_KFLAG) /* error? */ + return t; *c = t & 0177; /* store character */ return SCPE_OK; } @@ -305,9 +319,11 @@ for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ 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? */ + if (d & FLAG) /* flag? */ + tto_write ('`'); r = tto_write (num_to_tto[d & DIGIT]); /* write */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; PP (pa); /* incr mem addr */ } return STOP_RWRAP; @@ -322,7 +338,8 @@ 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 */ + while (rpt-- > 0) /* use spaces */ + sim_putchar (' '); return SCPE_OK; } if (c == '\r') { /* return? */ @@ -335,7 +352,8 @@ 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? */ +if (c == '\b') /* backspace? */ + tto_col = tto_col? tto_col - 1: 0; else tto_col++; /* normal */ if (tto_col > TTO_COLMAX) { /* line wrap? */ sim_putchar ('\r'); @@ -353,7 +371,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? */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return temp; return SCPE_OK; } diff --git a/I7094/i7094_binloader.c b/I7094/i7094_binloader.c index 6089937e..86c7d5cd 100644 --- a/I7094/i7094_binloader.c +++ b/I7094/i7094_binloader.c @@ -1,6 +1,6 @@ /* i7094_binloader.c: IBM 7094 simulator interface - Copyright (c) 2006, David G. Pitts + Copyright (c) 2008, David G. Pitts Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -115,7 +115,7 @@ binloader (FILE *fd, char *file, int loadpt) char *op = inbuf; int i; - if (*op == IBSYSSYM) /* End of object marker */ + if (*op == IBSYSSYM) /* End of object marker */ break; for (i = 0; i < WORDPERREC; i++) @@ -125,7 +125,8 @@ binloader (FILE *fd, char *file, int loadpt) t_uint64 ldata; otag = *op++; - if (otag == ' ') break; + if (otag == ' ') + break; strncpy (item, op, CHARWORD); item[CHARWORD] = '\0'; #ifdef WIN32 @@ -185,7 +186,8 @@ binloader (FILE *fd, char *file, int loadpt) #ifdef DEBUGLOADER fprintf (lfd, " PC = %05o\n", PC); #endif - if (transfer) goto GOSTART; + if (transfer) + goto GOSTART; break; case RELXFER_TAG: @@ -196,7 +198,8 @@ binloader (FILE *fd, char *file, int loadpt) #ifdef DEBUGLOADER fprintf (lfd, " PC = %05o\n", PC); #endif - if (transfer) goto GOSTART; + if (transfer) + goto GOSTART; break; default: ; diff --git a/I7094/i7094_cd.c b/I7094/i7094_cd.c index 4029c49f..88a15ebe 100644 --- a/I7094/i7094_cd.c +++ b/I7094/i7094_cd.c @@ -1,6 +1,6 @@ /* i7094_cd.c: IBM 711/721 card reader/punch - Copyright (c) 2003-2007, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -182,7 +182,8 @@ DEVICE cdp_dev = { t_stat cdr_chsel (uint32 ch, uint32 sel, uint32 unit) { -if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */ +if (sel & CHSL_NDS) /* nds? nop */ + return ch6_end_nds (ch); switch (sel) { /* case on data sel */ @@ -210,7 +211,8 @@ uint32 i, col, row, bufw, colbin; char cdr_cbuf[(2 * CD_CHRLNT) + 2]; t_uint64 dat = 0; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* not attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return SCPE_UNATT; switch (cdr_sta) { /* case on state */ case CDS_INIT: /* initial state */ @@ -275,7 +277,8 @@ t_stat cdr_reset (DEVICE *dptr) { uint32 i; -for (i = 0; i < CD_BINLNT; i++) cdr_bbuf[i] = 0; /* clear buffer */ +for (i = 0; i < CD_BINLNT; i++) /* clear buffer */ + cdr_bbuf[i] = 0; cdr_sta = 0; /* clear state */ cdr_bptr = 0; /* clear buf ptr */ sim_cancel (&cdr_unit); /* stop reader */ @@ -310,9 +313,11 @@ return SCPE_OK; t_stat cd_attach (UNIT *uptr, char *cptr) { -t_stat r = attach_unit (uptr, cptr); +t_stat r; -if (r != SCPE_OK) return r; /* attach */ +r = attach_unit (uptr, cptr); +if (r != SCPE_OK) /* attach */ + return r; if (sim_switches & SWMASK ('T')) /* text? */ uptr->flags = uptr->flags & ~UNIT_CBN; else if (sim_switches & SWMASK ('C')) /* column binary? */ @@ -335,7 +340,8 @@ return (uptr->flags & UNIT_ATT)? SCPE_NOFNC: SCPE_OK; t_stat cdp_chsel (uint32 ch, uint32 sel, uint32 unit) { -if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */ +if (sel & CHSL_NDS) /* nds? nop */ + return ch6_end_nds (ch); switch (sel) { /* case on cmd */ @@ -393,7 +399,8 @@ switch (cdp_sta) { /* case on state */ case CDS_DATA: /* data state */ if (!ch6_qconn (CH_A, U_CDP)) /* chan disconnect? */ return cdp_card_end (uptr); /* write card */ - if (cdp_chob_v) cdp_chob_v = 0; /* valid? clear */ + if (cdp_chob_v) /* valid? clear */ + cdp_chob_v = 0; else ind_ioc = 1; /* no, io check */ ch6_req_wr (CH_A, U_CDP); /* req channel */ sim_activate (uptr, (cdp_bptr & 1)? cdp_tleft: cdp_tright); @@ -418,8 +425,10 @@ uint32 i, col, row, bufw, colbin; char *pch, bcd, cdp_cbuf[(2 * CD_CHRLNT) + 2]; t_uint64 dat; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* not attached? */ -if (uptr->flags & UNIT_PCA) pch = bcd_to_ascii_a; +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return SCPE_UNATT; +if (uptr->flags & UNIT_PCA) + pch = bcd_to_ascii_a; else pch = bcd_to_ascii_h; for (col = 0; col < ((2 * CD_CHRLNT) + 1); col++) cdp_cbuf[col] = ' '; /* clear char buf */ @@ -428,7 +437,8 @@ for (col = 0; col < 72; col++) { /* process 72 columns */ dat = bit_masks[35 - (col % 36)]; /* mask for column */ for (row = 0; row < 12; row++) { /* proc 12 rows */ bufw = (row * 2) + (col / 36); /* index to buffer */ - if (cdp_bbuf[bufw] & dat) colbin |= col_masks[row]; + if (cdp_bbuf[bufw] & dat) + colbin |= col_masks[row]; } if (cdp_unit.flags & UNIT_CBN) { /* column binary? */ cdp_cbuf[2 * col] = pch[(colbin >> 6) & 077]; @@ -462,7 +472,8 @@ t_stat cdp_reset (DEVICE *dptr) { uint32 i; -for (i = 0; i < 24; i++) cdp_bbuf[i] = 0; /* clear buffer */ +for (i = 0; i < 24; i++) /* clear buffer */ + cdp_bbuf[i] = 0; cdp_sta = 0; /* clear state */ cdp_bptr = 0; /* clear buf ptr */ cdp_chob = 0; @@ -493,7 +504,8 @@ uint32 i; char bcd; for (i = 0, bcd = 0; i < 12; i++) { /* 'sum' rows */ - if (cb & (1 << i)) bcd |= row_val[i]; + if (cb & (1 << i)) + bcd |= row_val[i]; } return bcd; } diff --git a/I7094/i7094_clk.c b/I7094/i7094_clk.c index f931d956..f516819a 100644 --- a/I7094/i7094_clk.c +++ b/I7094/i7094_clk.c @@ -1,6 +1,6 @@ /* i7094_clk.c: IBM 7094 clock - Copyright (c) 2003-2006, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -70,7 +70,8 @@ if ((clk_dev.flags & DEV_DIS) == 0) { /* clock enabled? */ ctr = ReadP (CLK_CTR); ctr = (ctr + 1) & DMASK; /* increment */ WriteP (CLK_CTR, ctr); - if ((ctr & MMASK) == 0) chtr_clk = 1; /* overflow? req trap */ + if ((ctr & MMASK) == 0) /* overflow? req trap */ + chtr_clk = 1; sim_activate (uptr, sim_rtcn_calb (CLK_TPS, TMR_CLK)); /* reactivate unit */ } return SCPE_OK; @@ -84,10 +85,12 @@ time_t curtim; t_uint64 ctr; struct tm *tptr; -if (bufsiz < 12) return 0; +if (bufsiz < 12) + return 0; curtim = time (NULL); /* get time */ tptr = localtime (&curtim); /* decompose */ -if (tptr == NULL) return 0; /* error? */ +if (tptr == NULL) /* error? */ + return 0; buf[0] = bcd_2d (tptr->tm_mon + 1, buf + 1); buf[2] = bcd_2d (tptr->tm_mday, buf + 3); @@ -107,9 +110,12 @@ uint8 d1, d2; d1 = n / 10; d2 = n % 10; -if (d1 == 0) d1 = BCD_ZERO; -if (d2 == 0) d2 = BCD_ZERO; -if (b2 != NULL) *b2 = d2; +if (d1 == 0) + d1 = BCD_ZERO; +if (d2 == 0) + d2 = BCD_ZERO; +if (b2 != NULL) + *b2 = d2; return d1; } @@ -118,7 +124,8 @@ return d1; t_stat clk_reset (DEVICE *dptr) { chtr_clk = 0; -if (clk_dev.flags & DEV_DIS) sim_cancel (&clk_unit); +if (clk_dev.flags & DEV_DIS) + sim_cancel (&clk_unit); else sim_activate (&clk_unit, sim_rtcn_init (clk_unit.wait, TMR_CLK)); return SCPE_OK; } diff --git a/I7094/i7094_com.c b/I7094/i7094_com.c index ea4e8728..4a665453 100644 --- a/I7094/i7094_com.c +++ b/I7094/i7094_com.c @@ -1,6 +1,6 @@ /* i7094_com.c: IBM 7094 7750 communications interface simulator - Copyright (c) 2005-2006, Robert M Supnik + Copyright (c) 2005-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,8 @@ com 7750 controller coml 7750 lines + 19-Nov-2008 RMS Revised for common TMXR show routines + This module implements an abstract simulator for the IBM 7750 communications computer as used by the CTSS system. The 7750 supports up to 112 lines; the simulator supports 33. The 7750 can handle both high-speed lines, in @@ -221,8 +223,6 @@ t_stat comto_svc (UNIT *uptr); t_stat com_reset (DEVICE *dptr); t_stat com_attach (UNIT *uptr, char *cptr); t_stat com_detach (UNIT *uptr); -t_stat com_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat com_show (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat com_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat com_show_freeq (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat com_show_inq (FILE *st, UNIT *uptr, int32 val, void *desc); @@ -285,11 +285,12 @@ REG com_reg[] = { }; MTAB com_mod[] = { - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &com_summ }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &com_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &com_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &com_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &com_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &com_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_FQ, "FREEQ", NULL, NULL, &com_show_ctrl, 0 }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_IQ, "INQ", NULL, @@ -311,7 +312,7 @@ DEVICE com_dev = { &com_dib, DEV_NET | DEV_DIS }; -/* COMLL data structures +/* COML data structures coml_dev COML device descriptor coml_unit COML unit descriptor @@ -360,11 +361,11 @@ MTAB coml_mod[] = { { UNIT_K35+UNIT_2741, UNIT_K35 , "KSR-35", "KSR-35", NULL }, // { UNIT_K35+UNIT_2741, UNIT_2741, "2741", "2741", NULL }, { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &com_desc }, + &tmxr_dscln, NULL, (void *) &com_desc }, { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", - &tmxr_set_log, &tmxr_show_log, &com_desc }, + &tmxr_set_log, &tmxr_show_log, (void*) &com_desc }, { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", - &tmxr_set_nolog, NULL, &com_desc }, + &tmxr_set_nolog, NULL, (void *) &com_desc }, { 0 } }; @@ -419,7 +420,8 @@ return SCPE_OK; t_stat com_chwr (uint32 ch, t_uint64 val, uint32 stopf) { -if (stopf) com_stop = 1; +if (stopf) + com_stop = 1; else { com_chob = val; /* store data */ com_chob_v = 1; /* set valid */ @@ -437,8 +439,10 @@ switch (com_sta) { /* case on state */ case CHSL_SNS: /* prepare data */ com_sns &= ~COMS_DYN; /* clear dynamic flags */ - if (com_free.head) com_set_sns (COMS_INBF); /* free space? */ - if (com_inpq.head) com_set_sns (COMS_DATR); /* pending input? */ + if (com_free.head) /* free space? */ + com_set_sns (COMS_INBF); + if (com_inpq.head) /* pending input? */ + com_set_sns (COMS_DATR); com_buf[0] = (com_sns >> 24) & DMASK; /* buffer is 2 words */ com_buf[1] = (com_sns << 12) & DMASK; com_bptr = 0; @@ -455,11 +459,13 @@ switch (com_sta) { /* case on state */ return SCPE_OK; } dat = com_buf[com_bptr++]; /* get word */ - if (!com_stop) ch9_req_rd (com_ch, dat); /* send wd to chan */ + if (!com_stop) /* send wd to chan */ + ch9_req_rd (com_ch, dat); break; case CHSL_SNS|CHSL_3RD: /* 3rd state */ - if (com_qdone (com_ch)) return SCPE_OK; /* done? exit */ + if (com_qdone (com_ch)) /* done? exit */ + return SCPE_OK; com_sta = CHSL_SNS; /* repeat sequence */ break; } @@ -479,18 +485,22 @@ t_uint64 dat; switch (com_sta) { /* case on state */ case CHSL_RDS: /* read start */ - for (i = 0; i < COM_BUFSIZ; i++) com_buf[i] = 0; /* clear chan buf */ + for (i = 0; i < COM_BUFSIZ; i++) /* clear chan buf */ + com_buf[i] = 0; com_buf[0] = com_msgn; /* 1st char is msg num */ com_msgn = (com_msgn + 1) & 03777; /* incr msg num */ for (i = 1, j = 0; i < COMI_12BMAX; i++) { /* fill buffer */ ent = com_gethd_free (&com_inpq); /* get next entry */ - if (ent == 0) break; /* q empty, done */ - if ((i % 3) == 0) j++; /* next word? */ + if (ent == 0) /* q empty, done */ + break; + if ((i % 3) == 0) /* next word? */ + j++; com_buf[j] = (com_buf[j] << 12) | /* pack data */ ((t_uint64) (com_pkt[ent].data & 07777)); } for (k = i % 3; k < 3; k++) { /* fill with EOM */ - if (k == 0) j++; /* next word? */ + if (k == 0) /* next word? */ + j++; com_buf[j] = (com_buf[j] << 12) | COMI_EOM; } com_bptr = 0; /* init buf ptr */ @@ -503,7 +513,8 @@ switch (com_sta) { /* case on state */ com_end (com_ch, 0, CHSL_RDS|CHSL_3RD); /* end, next state */ else { /* more to do */ dat = com_buf[com_bptr++]; /* get word */ - if (!com_stop) ch9_req_rd (com_ch, dat); /* give to channel */ + if (!com_stop) /* give to channel */ + ch9_req_rd (com_ch, dat); } break; @@ -514,7 +525,8 @@ switch (com_sta) { /* case on state */ break; case CHSL_WRS: /* write start */ - for (i = 0; i < COM_BUFSIZ; i++) com_buf[i] = 0; /* clear chan buf */ + for (i = 0; i < COM_BUFSIZ; i++) /* clear chan buf */ + com_buf[i] = 0; com_bptr = 0; /* init buf ptr */ com_sta = CHSL_WRS|CHSL_2ND; /* next state */ ch_req |= REQ_CH (com_ch); /* request channel */ @@ -533,13 +545,16 @@ switch (com_sta) { /* case on state */ ln = COMO_GETLN (dat); /* line number */ if (ln >= (COM_TLINES + COM_LBASE)) /* invalid line? */ return STOP_INVLIN; - if (dat & COMO_CTLRST) return STOP_INVMSG; /* char must be 0 */ - if (ln >= COM_LBASE) com_reset_ln (ln - COM_LBASE); + if (dat & COMO_CTLRST) /* char must be 0 */ + return STOP_INVMSG; + if (ln >= COM_LBASE) + com_reset_ln (ln - COM_LBASE); com_end (com_ch, 0, CHSL_WRS|CHSL_4TH); /* end, last state */ } else { /* data message */ ccnt = (((uint32) dat >> 12) & 07777) + 1; /* char count plus EOM */ - if (dat & COMO_LIN12B) ccnt = ccnt << 1; /* 12b? double */ + if (dat & COMO_LIN12B) /* 12b? double */ + ccnt = ccnt << 1; com_blim = (ccnt + 6 + 5) / 6; /* buffer limit */ if ((com_blim == 1) || (com_blim >= COMO_BMAX)) return STOP_INVMSG; @@ -560,9 +575,11 @@ switch (com_sta) { /* case on state */ (ln >= COM_LBASE)) { uln = ln - COM_LBASE; /* unit number */ for (i = 2, j = 0; i < COMO_12BMAX; i++) { /* unpack 12b char */ - if ((i % 3) == 0) j++; + if ((i % 3) == 0) + j++; chr = (uint16) (com_buf[j] >> ((2 - (i % 3)) * 12)) & 07777; - if (chr == COMO_EOM12B) break; /* EOM? */ + if (chr == COMO_EOM12B) /* EOM? */ + break; if (!com_new_puttl (&com_outq[uln], chr)) return STOP_NOOFREE; /* append to outq */ } @@ -570,7 +587,8 @@ switch (com_sta) { /* case on state */ } com_end (com_ch, 0, CHSL_WRS|CHSL_4TH); /* end, last state */ } - else if (!com_stop) ch_req |= REQ_CH (com_ch); /* request channel */ + else if (!com_stop) /* request channel */ + ch_req |= REQ_CH (com_ch); break; case CHSL_WRS|CHSL_4TH: /* buffer done */ @@ -596,14 +614,19 @@ t_stat r; sim_activate (uptr, uptr->wait); /* continue poll */ c = sim_poll_kbd (); /* get character */ -if (c && !(c & (SCPE_BREAK|SCPE_KFLAG))) return c; /* error? */ -if (!com_enab || (c & SCPE_BREAK)) return SCPE_OK; /* !enab, break? done */ +if (c && !(c & (SCPE_BREAK|SCPE_KFLAG))) /* error? */ + return c; +if (!com_enab || (c & SCPE_BREAK)) /* !enab, break? done */ + return SCPE_OK; if (coml_unit[COM_MLINES].NEEDID) /* ID needed? */ return com_send_id (COM_MLINES); if ((c & SCPE_KFLAG) && ((c = c & 0177) != 0)) { /* char input? */ - if (r = com_queue_in (COM_MLINES, c)) return r; - if (sim_tt_outcvt (c, TT_MODE_7P) >= 0) sim_putchar (c); - if (c == '\r') sim_putchar ('\n'); + if (r = com_queue_in (COM_MLINES, c)) + return r; + if (sim_tt_outcvt (c, TT_MODE_7P) >= 0) + sim_putchar (c); + if (c == '\r') + sim_putchar ('\n'); } return com_test_atn (com_ch); /* set ATN if input */ } @@ -618,10 +641,12 @@ t_stat comi_svc (UNIT *uptr) int32 c, ln, t; t_stat r; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; t = sim_rtcn_calb (com_tps, TMR_COM); /* calibrate */ sim_activate (uptr, t); /* continue poll */ -if (!com_enab) return SCPE_OK; /* not enabled? exit */ +if (!com_enab) /* not enabled? exit */ + return SCPE_OK; ln = tmxr_poll_conn (&com_desc); /* look for connect */ if (ln >= 0) { /* got one? */ com_ldsc[ln].rcve = 1; /* rcv enabled */ @@ -631,11 +656,13 @@ if (ln >= 0) { /* got one? */ tmxr_poll_rx (&com_desc); /* poll for input */ for (ln = 0; ln < COM_MLINES; ln++) { /* loop thru mux */ if (com_ldsc[ln].conn) { /* connected? */ - if (coml_unit[ln].NEEDID) return com_send_id (ln); + if (coml_unit[ln].NEEDID) + return com_send_id (ln); c = tmxr_getc_ln (&com_ldsc[ln]); /* get char */ if (c) { /* any char? */ c = c & 0177; /* mask to 7b */ - if (r = com_queue_in (ln, c)) return r; /* queue char, err? */ + if (r = com_queue_in (ln, c)) /* queue char, err? */ + return r; if (com_ldsc[ln].xmte) { /* output enabled? */ if (sim_tt_outcvt (c, TT_MODE_7P) >= 0) /* echo char */ tmxr_putc_ln (&com_ldsc[ln], c); @@ -664,8 +691,10 @@ uint32 c, c1; if (com_outq[COM_MLINES].head == 0) /* no more characters? */ return com_send_ccmp (COM_MLINES); /* free any remaining */ c = com_queue_out (COM_MLINES, &c1); /* get character, cvt */ -if (c) sim_putchar (c); /* printable? output */ -if (c1) sim_putchar (c1); /* second char? output */ +if (c) /* printable? output */ + sim_putchar (c); +if (c1) /* second char? output */ + sim_putchar (c1); sim_activate (uptr, uptr->wait); /* next char */ if (com_not_ret[COM_MLINES] >= COMI_CMAX) /* completion needed? */ return com_send_ccmp (COM_MLINES); /* generate msg */ @@ -684,8 +713,10 @@ if (com_outq[ln].head == 0) /* no more characters? * if (com_ldsc[ln].conn) { /* connected? */ if (com_ldsc[ln].xmte) { /* output enabled? */ c = com_queue_out (ln, &c1); /* get character, cvt */ - if (c) tmxr_putc_ln (&com_ldsc[ln], c); /* printable? output */ - if (c1) tmxr_putc_ln (&com_ldsc[ln], c1); /* print second */ + if (c) /* printable? output */ + tmxr_putc_ln (&com_ldsc[ln], c); + if (c1) /* print second */ + tmxr_putc_ln (&com_ldsc[ln], c1); } /* end if */ tmxr_poll_tx (&com_desc); /* poll xmt */ sim_activate (uptr, uptr->wait); /* next char */ @@ -720,16 +751,20 @@ t_stat com_queue_in (uint32 ln, uint32 c) { uint16 out; -if (c == com_intr) out = COMI_INTR; -else if (c == com_quit) out = COMI_QUIT; +if (c == com_intr) + out = COMI_INTR; +else if (c == com_quit) + out = COMI_QUIT; else { if (coml_unit[ln].flags & UNIT_K35) { /* KSR-35? */ - if (islower (c)) c = toupper (c); /* convert LC to UC */ + if (islower (c)) /* convert LC to UC */ + c = toupper (c); } else c |= (com_epar[c]? COMI_PARITY: 0); /* add even parity */ out = (~c) & 0377; /* 1's complement */ } -if (!com_inp_msg (ln, out)) return STOP_NOIFREE; /* input message */ +if (!com_inp_msg (ln, out)) /* input message */ + return STOP_NOIFREE; return SCPE_OK; } @@ -741,7 +776,8 @@ uint32 c, ent, raw; *c1 = 0; /* assume non-printing */ ent = com_gethd_free (&com_outq[ln]); /* get character */ -if (ent == 0) return 0; /* nothing? */ +if (ent == 0) /* nothing? */ + return 0; raw = com_pkt[ent].data; /* get 12b character */ com_not_ret[ln]++; if (raw == COMO_BITRPT) { /* insert delay? */ @@ -750,7 +786,8 @@ if (raw == COMO_BITRPT) { /* insert delay? */ } c = (~raw >> 1) & 0177; /* remove start, parity */ if (c >= 040) { /* printable? */ - if (c == 0177) return 0; /* DEL? ignore */ + if (c == 0177) /* DEL? ignore */ + return 0; if ((coml_unit[ln].flags & UNIT_K35) && islower (c)) /* KSR-35 LC? */ c = toupper (c); /* cvt to UC */ return c; @@ -795,7 +832,8 @@ t_stat com_send_ccmp (uint32 ln) uint32 t; if (t = com_not_ret[ln]) { /* chars not returned? */ - if (t > COMI_CMAX) t = COMI_CMAX; /* limit to max */ + if (t > COMI_CMAX) /* limit to max */ + t = COMI_CMAX; com_not_ret[ln] -= t; /* keep count */ if (!com_inp_msg (ln, COMI_COMP (t))) /* gen completion msg */ return STOP_NOIFREE; @@ -807,7 +845,8 @@ return SCPE_OK; void com_skip_outc (uint32 ln) { -if (com_gethd_free (&com_outq[ln])) com_not_ret[ln]++; /* count it */ +if (com_gethd_free (&com_outq[ln])) /* count it */ + com_not_ret[ln]++; return; } @@ -815,7 +854,8 @@ return; t_uint64 com_getob (uint32 ch) { -if (com_chob_v) com_chob_v = 0; /* valid? clear */ +if (com_chob_v) /* valid? clear */ + com_chob_v = 0; else if (!com_stop) { /* not stopped? */ ch9_set_ioc (com_ch); /* IO check */ com_set_sns (COMS_ITMO); /* set sense bit */ @@ -827,7 +867,8 @@ return com_chob; t_stat com_test_atn (uint32 ch) { -if (com_inpq.head) ch9_set_atn (ch); +if (com_inpq.head) + ch9_set_atn (ch); return SCPE_OK; } @@ -885,7 +926,8 @@ uint16 ent; if ((ent = lh->head) != 0) { lh->head = com_pkt[ent].next; - if (lh->head == 0) lh->tail = 0; + if (lh->head == 0) + lh->tail = 0; } else lh->tail = 0; return ent; @@ -895,7 +937,8 @@ return ent; void com_puttl (LISTHD *lh, uint16 ent) { -if (lh->tail == 0) lh->head = ent; +if (lh->tail == 0) + lh->head = ent; else com_pkt[lh->tail].next = ent; com_pkt[ent].next = 0; lh->tail = ent; @@ -927,9 +970,12 @@ void com_set_sns (t_uint64 stat) { com_sns |= stat; com_sns &= ~(COMS_PCHK|COMS_DCHK|COMS_EXCC); -if (com_sns & COMS_PALL) com_sns |= COMS_PCHK; -if (com_sns & COMS_DALL) com_sns |= COMS_DCHK; -if (com_sns & COMS_EALL) com_sns |= COMS_EXCC; +if (com_sns & COMS_PALL) + com_sns |= COMS_PCHK; +if (com_sns & COMS_DALL) + com_sns |= COMS_DCHK; +if (com_sns & COMS_EALL) + com_sns |= COMS_EXCC; return; } @@ -963,7 +1009,8 @@ com_chob_v = 0; com_stop = 0; com_bptr = 0; com_blim = 0; -for (i = 0; i < COM_BUFSIZ; i++) com_buf[i] = 0; +for (i = 0; i < COM_BUFSIZ; i++) + com_buf[i] = 0; com_inpq.head = 0; /* init queues */ com_inpq.tail = 0; for (i = 0; i < COM_TLINES; i++) { @@ -991,7 +1038,8 @@ t_stat com_attach (UNIT *uptr, char *cptr) t_stat r; r = tmxr_attach (&com_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ +if (r != SCPE_OK) /* error */ + return r; sim_rtcn_init (uptr->wait, TMR_COM); sim_activate (uptr, 100); /* quick poll */ return SCPE_OK; @@ -1005,42 +1053,12 @@ uint32 i; t_stat r; r = tmxr_detach (&com_desc, uptr); /* detach */ -for (i = 0; i < COM_MLINES; i++) com_ldsc[i].rcve = 0; /* disable rcv */ +for (i = 0; i < COM_MLINES; i++) /* disable rcv */ + com_ldsc[i].rcve = 0; sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat com_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -uint32 i, t; - -for (i = t = 0; i < COM_MLINES; i++) t = t + (com_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat com_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -uint32 i, t; - -for (i = t = 0; i < COM_MLINES; i++) t = t + (com_ldsc[i].conn != 0); -if (t) { - for (i = 0; i < COM_MLINES; i++) { - if (com_ldsc[i].conn) { - if (val) tmxr_fconns (st, &com_ldsc[i], i); - else tmxr_fstats (st, &com_ldsc[i], i); - } - } - } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - /* Reset an individual line */ void com_reset_ln (uint32 ln) @@ -1048,7 +1066,8 @@ void com_reset_ln (uint32 ln) while (com_gethd_free (&com_outq[ln])) ; com_not_ret[ln] = 0; sim_cancel (&coml_unit[ln]); -if ((ln < COM_MLINES) && (com_ldsc[ln].conn == 0)) coml_unit[ln].CONN = 0; +if ((ln < COM_MLINES) && (com_ldsc[ln].conn == 0)) + coml_unit[ln].CONN = 0; return; } @@ -1061,8 +1080,10 @@ uint32 i, next; next = lh->head; for (i = 0; i < COM_PKTSIZ; i++) { if (next == 0) { - if (i == 0) fprintf (st, "%s is empty\n", name); - else if (i == 1) fprintf (st, "%s has 1 entry\n", name); + if (i == 0) + fprintf (st, "%s is empty\n", name); + else if (i == 1) + fprintf (st, "%s has 1 entry\n", name); else fprintf (st, "%s had %d entries\n", name, i); return i; } @@ -1078,7 +1099,8 @@ uint32 c; fprintf (st, "%03o", ch); c = (~ch) & 0177; -if (((ch & 07400) == 0) && (c >= 040) && (c != 0177)) fprintf (st, "[%c]", c); +if (((ch & 07400) == 0) && (c >= 040) && (c != 0177)) + fprintf (st, "[%c]", c); return; } @@ -1095,7 +1117,8 @@ uint32 entc, ln, i, next; if (entc = com_show_qsumm (st, &com_inpq, "Input queue")) { for (i = 0, next = com_inpq.head; next != 0; i++, next = com_pkt[next].next) { - if ((i % 4) == 0) fprintf (st, "%d:\t", i); + if ((i % 4) == 0) + fprintf (st, "%d:\t", i); ln = com_pkt[next].data; next = com_pkt[next].next; if (next == 0) { @@ -1106,7 +1129,8 @@ if (entc = com_show_qsumm (st, &com_inpq, "Input queue")) { com_show_char (st, com_pkt[next].data); fputc ((((i % 4) == 3)? '\n': '\t'), st); } - if (i % 4) fputc ('\n', st); + if (i % 4) + fputc ('\n', st); } return SCPE_OK; } @@ -1121,11 +1145,13 @@ sprintf (name, "Output queue %d", ln); if (entc = com_show_qsumm (st, &com_outq[ln], name)) { for (i = 0, next = com_outq[ln].head; next != 0; i++, next = com_pkt[next].next) { - if ((i % 8) == 0) fprintf (st, "%d:\t", i); + if ((i % 8) == 0) + fprintf (st, "%d:\t", i); com_show_char (st, com_pkt[next].data >> 1); fputc ((((i % 8) == 7)? '\n': '\t'), st); } - if (i % 8) fputc ('\n', st); + if (i % 8) + fputc ('\n', st); } return SCPE_OK; } @@ -1141,9 +1167,13 @@ return SCPE_OK; t_stat com_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (!com_enab) fprintf (st, "Controller is not initialized\n"); -if (val & COMR_FQ) com_show_freeq (st, uptr, 1, desc); -if (val & COMR_IQ) com_show_inq (st, uptr, 1, desc); -if (val & COMR_OQ) com_show_aoutq (st, uptr, 1, desc); +if (!com_enab) + fprintf (st, "Controller is not initialized\n"); +if (val & COMR_FQ) + com_show_freeq (st, uptr, 1, desc); +if (val & COMR_IQ) + com_show_inq (st, uptr, 1, desc); +if (val & COMR_OQ) + com_show_aoutq (st, uptr, 1, desc); return SCPE_OK; } diff --git a/I7094/i7094_cpu.c b/I7094/i7094_cpu.c index e5a49877..87c46fca 100644 --- a/I7094/i7094_cpu.c +++ b/I7094/i7094_cpu.c @@ -617,7 +617,8 @@ t_bool tracing; /* Restore register state */ ch_set_map (); /* set dispatch map */ -if (!(cpu_model & (I_94|I_CT))) mode_multi = 1; /* ~7094? MTM always on */ +if (!(cpu_model & (I_94|I_CT))) /* ~7094? MTM always on */ + mode_multi = 1; eamask = mode_storn? A704_MASK: AMASK; /* set eff addr mask */ inst_base = inst_base & ~AMASK; /* A/B sel is 1b */ data_base = data_base & ~AMASK; @@ -649,16 +650,19 @@ while (reason == SCPE_OK) { /* loop until error */ } if (sim_interval <= 0) { /* intv cnt expired? */ - if (reason = sim_process_event ()) break; /* process events */ + if (reason = sim_process_event ()) /* process events */ + break; chtr_pend = chtr_eval (NULL); /* eval chan traps */ } for (i = 0; ch_req && (i < NUM_CHAN); i++) { /* loop thru channels */ if (ch_req & REQ_CH (i)) { /* channel request? */ - if (reason = ch_proc (i)) break; + if (reason = ch_proc (i)) + break; } chtr_pend = chtr_eval (NULL); - if (reason) break; /* error? */ + if (reason) /* error? */ + break; } if (chtr_pend) { /* channel trap? */ @@ -681,7 +685,8 @@ while (reason == SCPE_OK) { /* loop until error */ } oldPC = PC; /* save current PC */ PC = (PC + 1) & eamask; /* increment PC */ - if (!ReadI (oldPC, &IR)) continue; /* get inst; trap? */ + if (!ReadI (oldPC, &IR)) /* get inst; trap? */ + continue; } sim_interval = sim_interval - 1; @@ -718,20 +723,24 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 02: /* TIX */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (xr > dec) { /* if xr > decr */ put_xr (tag, xr - dec); /* xr -= decr */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = addr; /* branch */ } break; case 03: /* TXH */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (xr > dec) { /* if xr > decr */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = addr; /* branch */ } break; @@ -743,20 +752,25 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 06: /* TNX */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); - if (xr > dec) put_xr (tag, xr - dec); /* if xr > decr */ + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); + if (xr > dec) /* if xr > decr */ + put_xr (tag, xr - dec); else { /* xr -= decr */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = addr; /* branch */ } break; case 07: /* TXL */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (xr <= dec) { /* if xr <= decr */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = addr; /* branch */ } break; @@ -769,25 +783,31 @@ while (reason == SCPE_OK) { /* loop until error */ op = GET_OPC (IR); /* get opcode */ fl = op_flags[op]; /* get flags */ if (fl & I_MODEL & ~cpu_model) { /* invalid for model? */ - if (stop_illop) reason = STOP_ILLEG; /* possible stop */ + if (stop_illop) /* possible stop */ + reason = STOP_ILLEG; continue; } if (tag && (fl & I_X)) /* tag and indexable? */ ea = (addr - get_xri (tag)) & eamask; /* do indexing */ else ea = addr; if (TST_IND (IR) && (fl & I_N)) { /* indirect? */ - if (!ReadI (ea, &SR)) continue; /* get ind; trap? */ + if (!ReadI (ea, &SR)) /* get ind; trap? */ + continue; addr = (uint32) SR & eamask; /* get address */ tagi = GET_TAG (SR); /* get tag */ if (tagi) /* tag? */ ea = (addr - get_xri (tagi)) & eamask; /* do indexing */ else ea = addr; } - if ((fl & I_R) && !Read (ea, &SR)) continue; /* read opnd; trap? */ + if ((fl & I_R) && !Read (ea, &SR)) /* read opnd; trap? */ + continue; else if (fl & I_D) { /* double prec? */ - if ((ea & 1) && fp_trap (TRAP_F_ODD)) continue; - if (!Read (ea, &SR)) continue; /* SR gets high */ - if (!Read (ea | 1, &sr1)) continue; /* "sr1" gets low */ + if ((ea & 1) && fp_trap (TRAP_F_ODD)) + continue; + if (!Read (ea, &SR)) /* SR gets high */ + continue; + if (!Read (ea | 1, &sr1)) /* "sr1" gets low */ + continue; } if (tracing) { /* tracing or history? */ if (hst_lnt) /* history enabled? */ @@ -802,7 +822,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 00000: /* HTR */ case 01000: /* also -HTR */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ht_pend = 1; /* transfer pending */ ht_addr = ea; /* save address */ reason = STOP_HALT; /* halt if I/O done */ @@ -824,7 +845,8 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00040: /* TLQ */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); s1 = (AC & AC_S)? 1: 0; /* get AC, MQ sign, */ s2 = (MQ & SIGN)? 1: 0; /* magnitude */ t1 = AC & AC_MMASK; @@ -832,7 +854,8 @@ while (reason == SCPE_OK) { /* loop until error */ if ((s1 != s2)? s2: /* y, br if MQ- */ ((t1 != t2) && (s2 ^ (t1 > t2)))) { /* n, br if sgn-^AC>MQ */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; @@ -842,10 +865,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00042: /* TIO */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((SI & AC) == (AC & DMASK)) { /* if ind on */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; @@ -859,10 +884,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00046: /* TIF */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((SI & AC) == 0) { /* if ind off */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; @@ -873,7 +900,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 00054: /* RFT */ t = IR & RMASK; - if ((SI & t) == 0) PC = (PC + 1) & eamask; /* if ind off, skip */ + if ((SI & t) == 0) /* if ind off, skip */ + PC = (PC + 1) & eamask; break; case 00055: /* SIR */ @@ -882,7 +910,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 00056: /* RNT */ t = IR & RMASK; - if ((SI & t) == t) PC = (PC + 1) & eamask; /* if ind on, skip */ + if ((SI & t) == t) /* if ind on, skip */ + PC = (PC + 1) & eamask; break; case 00057: /* RIR */ @@ -890,24 +919,30 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00074: /* TSX */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); - if (tag) put_xr (tag, ~oldPC + 1); /* save -inst loc */ + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); + if (tag) /* save -inst loc */ + put_xr (tag, ~oldPC + 1); PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ break; case 00100: /* TZE */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((AC & AC_MMASK) == 0) { /* if AC Q,P,1-35 = 0 */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; case 00101: /* (CTSS) TIA */ - if (prot_trap (0)) break; /* not user mode? */ + if (prot_trap (0)) /* not user mode? */ + break; PCQ_ENTRY; PC = ea; inst_base = 0; @@ -918,7 +953,8 @@ while (reason == SCPE_OK) { /* loop until error */ SR = ea; while (sc) { ea = (uint32) ((AC & 077) + SR) & eamask; - if (!Read (ea, &SR)) break; + if (!Read (ea, &SR)) + break; AC = (AC & AC_S) | ((AC >> 6) & 0017777777777) | (SR & 0770000000000); sc--; @@ -928,10 +964,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00120: /* TPL */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((AC & AC_S) == 0) { /* if AC + */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; @@ -943,10 +981,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00140: /* TOV */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (ind_ovf) { /* if overflow */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ ind_ovf = 0; /* clear overflow */ } @@ -954,10 +994,12 @@ while (reason == SCPE_OK) { /* loop until error */ case 00161: /* TQO */ if (!mode_ftrap) { /* only in 704 mode */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (ind_mqo) { /* if MQ overflow */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ ind_mqo = 0; /* clear overflow */ } @@ -965,10 +1007,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00162: /* TQP */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((MQ & SIGN) == 0) { /* if MQ + */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; @@ -986,12 +1030,14 @@ while (reason == SCPE_OK) { /* loop until error */ case 00220: /* DVH */ if (op_div (SR, 043)) { ind_dvc = 1; - if (!prot_trap (0)) reason = STOP_DIVCHK; + if (!prot_trap (0)) + reason = STOP_DIVCHK; } break; case 00221: /* DVP */ - if (op_div (SR, 043)) ind_dvc = 1; + if (op_div (SR, 043)) + ind_dvc = 1; break; case 00224: /* VDH */ @@ -999,79 +1045,95 @@ while (reason == SCPE_OK) { /* loop until error */ sc = GET_VCNT (IR); if (op_div (SR, sc)) { ind_dvc = 1; - if (!prot_trap (0)) reason = STOP_DIVCHK; + if (!prot_trap (0)) + reason = STOP_DIVCHK; } break; case 00225: /* VDP */ case 00227: /* for diagnostic */ sc = GET_VCNT (IR); - if (op_div (SR, sc)) ind_dvc = 1; + if (op_div (SR, sc)) + ind_dvc = 1; break; case 00240: /* FDH */ spill = op_fdv (SR); if (spill == TRAP_F_DVC) { ind_dvc = 1; - if (!prot_trap (0)) reason = STOP_DIVCHK; + if (!prot_trap (0)) + reason = STOP_DIVCHK; } - else if (spill) fp_trap (spill); + else if (spill) + fp_trap (spill); break; case 00241: /* FDP */ spill = op_fdv (SR); - if (spill == TRAP_F_DVC) ind_dvc = 1; - else if (spill) fp_trap (spill); + if (spill == TRAP_F_DVC) + ind_dvc = 1; + else if (spill) + fp_trap (spill); break; case 00260: /* FMP */ spill = op_fmp (SR, 1); /* MQ * SR */ - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00261: /* DFMP */ spill = op_dfmp (SR, sr1, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00300: /* FAD */ spill = op_fad (SR, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00301: /* DFAD */ spill = op_dfad (SR, sr1, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00302: /* FSB */ spill = op_fad (SR ^ SIGN, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00303: /* DFSB */ spill = op_dfad (SR ^ SIGN, sr1, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00304: /* FAM */ spill = op_fad (SR & ~SIGN, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00305: /* DFAM */ spill = op_dfad (SR & ~SIGN, sr1, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00306: /* FSM */ spill = op_fad (SR | SIGN, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00307: /* DFSM */ spill = op_dfad (SR | SIGN, sr1, 1); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 00320: /* ANS */ @@ -1089,16 +1151,19 @@ while (reason == SCPE_OK) { /* loop until error */ t1 = AC & AC_MMASK; /* magnitudes */ t2 = SR & MMASK; if (s1 ^ s2) { /* diff signs? */ - if (s1) PC = (PC + 2) & eamask; /* AC < mem? skip 2 */ + if (s1) /* AC < mem? skip 2 */ + PC = (PC + 2) & eamask; } - else if (t1 == t2) PC = (PC + 1) & eamask; /* equal? skip 1 */ + else if (t1 == t2) /* equal? skip 1 */ + PC = (PC + 1) & eamask; else if ((t1 < t2) ^ s1) /* AC < mem, AC +, or */ PC = (PC + 2) & eamask; /* AC > mem, AC -? */ break; case 00361: /* ACL */ t = (AC + SR) & DMASK; /* AC P,1-35 + SR */ - if (t < SR) t = (t + 1) & DMASK; /* end around carry */ + if (t < SR) /* end around carry */ + t = (t + 1) & DMASK; AC = (AC & (AC_S | AC_Q)) | t; /* preserve AC S,Q */ break; @@ -1115,7 +1180,8 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00420: /* HPR */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; reason = STOP_HALT; /* halt if I/O done */ break; @@ -1133,13 +1199,16 @@ while (reason == SCPE_OK) { /* loop until error */ case 00443: /* DLD */ AC = (SR & MMASK) | ((SR & SIGN)? AC_S: 0); /* normal load */ - if (!Read (ea | 1, &SR)) break; /* second load */ + if (!Read (ea | 1, &SR)) /* second load */ + break; MQ = SR; - if (ea & 1) fp_trap (TRAP_F_ODD); /* trap after exec */ + if (ea & 1) /* trap after exec */ + fp_trap (TRAP_F_ODD); break; case 00444: /* OFT */ - if ((SI & SR) == 0) PC = (PC + 1) & eamask; /* skip if ind off */ + if ((SI & SR) == 0) /* skip if ind off */ + PC = (PC + 1) & eamask; break; case 00445: /* RIS */ @@ -1147,7 +1216,8 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00446: /* ONT */ - if ((SI & SR) == SR) PC = (PC + 1) & eamask;/* skip if ind on */ + if ((SI & SR) == SR) /* skip if ind on */ + PC = (PC + 1) & eamask; break; case 00460: /* LDA (704) */ @@ -1163,7 +1233,8 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00520: /* ZET */ - if ((SR & MMASK) == 0) PC = (PC + 1) & eamask; /* skip if M 1-35 = 0 */ + if ((SR & MMASK) == 0) /* skip if M 1-35 = 0 */ + PC = (PC + 1) & eamask; break; case 00522: /* XEC */ @@ -1177,11 +1248,13 @@ while (reason == SCPE_OK) { /* loop until error */ goto XEC; /* start over */ case 00534: /* LXA */ - if (tag) put_xr (tag, (uint32) SR); /* M addr -> xr */ + if (tag) /* M addr -> xr */ + put_xr (tag, (uint32) SR); break; case 00535: /* LAC */ - if (tag) put_xr (tag, NEG ((uint32) SR)); /* -M addr -> xr */ + if (tag) /* -M addr -> xr */ + put_xr (tag, NEG ((uint32) SR)); break; case 00560: /* LDQ */ @@ -1189,12 +1262,14 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00562: /* (CTSS) LRI */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ind_reloc = ((uint32) SR) & VA_BLK; break; case 00564: /* ENB */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; chtr_enab = (uint32) SR; /* set enables */ chtr_inht = 0; /* clear inhibit */ chtr_inhi = 1; /* 1 cycle delay */ @@ -1255,11 +1330,13 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00734: /* PAX */ - if (tag) put_xr (tag, (uint32) AC); /* AC addr -> xr */ + if (tag) /* AC addr -> xr */ + put_xr (tag, (uint32) AC); break; case 00737: /* PAC */ - if (tag) put_xr (tag, NEG ((uint32) AC)); /* -AC addr -> xr */ + if (tag) /* -AC addr -> xr */ + put_xr (tag, NEG ((uint32) AC)); break; case 00754: /* PXA */ @@ -1271,7 +1348,8 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00760: /* PSE */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; reason = op_pse (ea); break; @@ -1295,7 +1373,8 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00774: /* AXT */ - if (tag) put_xr (tag, addr); /* IR addr -> xr */ + if (tag) /* IR addr -> xr */ + put_xr (tag, addr); break; /* Negative instructions */ @@ -1320,7 +1399,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 01054: /* LFT */ t = (IR & RMASK) << 18; - if ((SI & t) == 0) PC = (PC + 1) & eamask; /* if ind off, skip */ + if ((SI & t) == 0) /* if ind off, skip */ + PC = (PC + 1) & eamask; break; case 01055: /* SIL */ @@ -1329,7 +1409,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 01056: /* LNT */ t = (IR & RMASK) << 18; - if ((SI & t) == t) PC = (PC + 1) & eamask; /* if ind on, skip */ + if ((SI & t) == t) /* if ind on, skip */ + PC = (PC + 1) & eamask; break; case 01057: /* RIL */ @@ -1337,16 +1418,19 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 01100: /* TNZ */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((AC & AC_MMASK) != 0) { /* if AC != 0 */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; case 01101: /* (CTSS) TIB */ - if (prot_trap (0)) break; /* not user mode? */ + if (prot_trap (0)) /* user mode? */ + break; PCQ_ENTRY; PC = ea; mode_user = 1; @@ -1358,7 +1442,8 @@ while (reason == SCPE_OK) { /* loop until error */ SR = ea; while (sc) { ea = (uint32) ((MQ >> 30) + SR) & eamask; - if (!Read (ea, &SR)) break; + if (!Read (ea, &SR)) + break; MQ = ((MQ << 6) & DMASK) | (MQ >> 30); AC = (AC & AC_S) | ((AC + SR) & AC_MMASK); sc--; @@ -1368,10 +1453,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 01120: /* TMI */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if ((AC & AC_S) != 0) { /* if AC - */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; @@ -1383,10 +1470,12 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 01140: /* TNO */ - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (!ind_ovf) { /* if no overflow */ PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } ind_ovf = 0; /* clear overflow */ @@ -1397,7 +1486,8 @@ while (reason == SCPE_OK) { /* loop until error */ SR = ea; while (sc) { ea = (uint32) ((MQ >> 30) + SR) & eamask; - if (!Read (ea, &SR)) break; + if (!Read (ea, &SR)) + break; MQ = ((MQ << 6) & DMASK) | (SR >> 30); sc--; } @@ -1407,72 +1497,87 @@ while (reason == SCPE_OK) { /* loop until error */ case 01200: /* MPR */ op_mpy (0, SR, 043); - if (MQ & B1) AC = (AC & AC_S) | ((AC + 1) & AC_MMASK); + if (MQ & B1) + AC = (AC & AC_S) | ((AC + 1) & AC_MMASK); break; case 01240: /* DFDH */ spill = op_dfdv (SR, sr1); if (spill == TRAP_F_DVC) { ind_dvc = 1; - if (!prot_trap (0)) reason = STOP_DIVCHK; + if (!prot_trap (0)) + reason = STOP_DIVCHK; } - else if (spill) fp_trap (spill); + else if (spill) + fp_trap (spill); break; case 01241: /* DFDP */ spill = op_dfdv (SR, sr1); - if (spill == TRAP_F_DVC) ind_dvc = 1; - else if (spill) fp_trap (spill); + if (spill == TRAP_F_DVC) + ind_dvc = 1; + else if (spill) + fp_trap (spill); break; case 01260: /* UFM */ spill = op_fmp (SR, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01261: /* DUFM */ spill = op_dfmp (SR, sr1, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01300: /* UFA */ spill = op_fad (SR, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01301: /* DUFA */ spill = op_dfad (SR, sr1, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01302: /* UFS */ spill = op_fad (SR ^ SIGN, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01303: /* DUFS */ spill = op_dfad (SR ^ SIGN, sr1, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01304: /* UAM */ spill = op_fad (SR & ~SIGN, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01305: /* DUAM */ spill = op_dfad (SR & ~SIGN, sr1, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01306: /* USM */ spill = op_fad (SR | SIGN, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01307: /* DUSM */ spill = op_dfad (SR | SIGN, sr1, 0); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); break; case 01320: /* ANA */ @@ -1481,8 +1586,10 @@ while (reason == SCPE_OK) { /* loop until error */ case 01340: /* LAS */ t = AC & AC_MMASK; /* AC Q,P,1-35 */ - if (t < SR) PC = (PC + 2) & eamask; - else if (t == SR) PC = (PC + 1) & eamask; + if (t < SR) + PC = (PC + 2) & eamask; + else if (t == SR) + PC = (PC + 1) & eamask; break; case 01400: /* SBM */ @@ -1498,19 +1605,23 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 01520: /* NZT */ - if ((SR & MMASK) != 0) PC = (PC + 1) & eamask; ; + if ((SR & MMASK) != 0) + PC = (PC + 1) & eamask; break; case 01534: /* LXD */ - if (tag) put_xr (tag, GET_DEC (SR)); /* M decr -> xr */ + if (tag) /* M decr -> xr */ + put_xr (tag, GET_DEC (SR)); break; case 01535: /* LDC */ - if (tag) put_xr (tag, NEG (GET_DEC (SR))); /* -M decr -> xr */ + if (tag) /* -M decr -> xr */ + put_xr (tag, NEG (GET_DEC (SR))); break; case 01564: /* (CTSS) LPI */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ind_start = ((uint32) SR) & VA_BLK; ind_limit = (GET_DEC (SR) & VA_BLK) | VA_OFF; break; @@ -1526,7 +1637,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 01603: /* DST */ SR = (AC & MMASK) | ((AC & AC_S)? SIGN: 0); - if (!Write (ea, SR)) break; + if (!Write (ea, SR)) + break; Write ((ea + 1) & eamask, MQ); break; @@ -1557,11 +1669,13 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 01734: /* PDX */ - if (tag) put_xr (tag, GET_DEC (AC)); /* AC decr -> xr */ + if (tag) /* AC decr -> xr */ + put_xr (tag, GET_DEC (AC)); break; case 01737: /* PDC */ - if (tag) put_xr (tag, NEG (GET_DEC (AC))); /* -AC decr -> xr */ + if (tag) /* -AC decr -> xr */ + put_xr (tag, NEG (GET_DEC (AC))); break; case 01754: /* PXD */ @@ -1573,12 +1687,14 @@ while (reason == SCPE_OK) { /* loop until error */ break; /* -xr -> AC decr */ case 01760: /* MSE */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; reason = op_mse (ea); break; case 01761: /* (CTSS) ext core */ - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; if (ea == 041) /* SEA? */ data_base = 0; else if (ea == 042) /* SEB? */ @@ -1605,24 +1721,29 @@ while (reason == SCPE_OK) { /* loop until error */ case 01773: /* RQL */ sc = (ea & SCMASK) % 36; - if (sc) MQ = ((MQ << sc) | (MQ >> (36 - sc))) & DMASK; + if (sc) + MQ = ((MQ << sc) | (MQ >> (36 - sc))) & DMASK; break; case 01774: /* AXC */ - if (tag) put_xr (tag, NEG (addr)); /* -IR addr -> xr */ + if (tag) /* -IR addr -> xr */ + put_xr (tag, NEG (addr)); break; /* IO instructions */ case 00022: case 00024: case 00026: /* TRCx */ case 01022: case 01024: case 01026: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = ((op & 077) - 00022) | ((op >> 9) & 01); - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (!BIT_TST (chtr_enab, CHTR_V_TRC + ch) && (ch_flags[ch] & CHF_TRC)) { PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ ch_flags[ch] = ch_flags[ch] & ~CHF_TRC; chtr_pend = chtr_eval (NULL); /* eval chan traps */ @@ -1630,13 +1751,16 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00027: case 01027: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = 6 + ((op >> 9) & 01); - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (!BIT_TST (chtr_enab, CHTR_V_TRC + ch) && (ch_flags[ch] & CHF_TRC)) { PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ ch_flags[ch] = ch_flags[ch] & ~CHF_TRC; chtr_pend = chtr_eval (NULL); /* eval chan traps */ @@ -1645,13 +1769,16 @@ while (reason == SCPE_OK) { /* loop until error */ case 00030: case 00031: case 00032: case 00033: /* TEFx */ case 01030: case 01031: case 01032: case 01033: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = ((op & 03) << 1) | ((op >> 9) & 01); - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (!BIT_TST (chtr_enab, CHTR_V_CME + ch) && (ch_flags[ch] & CHF_EOF)) { PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ ch_flags[ch] = ch_flags[ch] & ~CHF_EOF; chtr_pend = chtr_eval (NULL); /* eval chan traps */ @@ -1660,31 +1787,38 @@ while (reason == SCPE_OK) { /* loop until error */ case 00060: case 00061: case 00062: case 00063: /* TCOx */ case 00064: case 00065: case 00066: case 00067: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = op & 07; - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (ch_sta[ch] != CHXS_IDLE) { PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; case 01060: case 01061: case 01062: case 01063: /* TCNx */ case 01064: case 01065: case 01066: case 01067: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = op & 07; - if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC); + if (mode_ttrap) + WriteTA (TRAP_STD_SAV, oldPC); if (ch_sta[ch] == CHXS_IDLE) { PCQ_ENTRY; - if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */ + if (mode_ttrap) /* trap? */ + TrapXfr (TRAP_TRA_PC); else PC = ea; /* branch */ } break; case 00540: case 00541: case 00542: case 00543: /* RCHx */ case 01540: case 01541: case 01542: case 01543: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = ((op & 03) << 1) | ((op >> 9) & 01); reason = ch_op_start (ch, ea, TRUE); chtr_pend = chtr_eval (NULL); /* eval chan traps */ @@ -1692,7 +1826,8 @@ while (reason == SCPE_OK) { /* loop until error */ case 00544: case 00545: case 00546: case 00547: /* LCHx */ case 01544: case 01545: case 01546: case 01547: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = ((op & 03) << 1) | ((op >> 9) & 01); reason = ch_op_start (ch, ea, FALSE); chtr_pend = chtr_eval (NULL); /* eval chan traps */ @@ -1700,9 +1835,10 @@ while (reason == SCPE_OK) { /* loop until error */ case 00640: case 00641: case 00642: case 00643: /* SCHx */ case 01640: case 01641: case 01642: case 01643: - if (prot_trap (0)) break; /* user mode? */ + if (prot_trap (0)) /* user mode? */ + break; ch = ((op & 03) << 1) | ((op >> 9) & 01); - if ((reason = ch_op_store (ch, &SR)) == SCPE_OK) + if ((reason = ch_op_store (ch, &SR)) == SCPE_OK) Write (ea, SR); break; @@ -1714,63 +1850,72 @@ while (reason == SCPE_OK) { /* loop until error */ break; case 00762: /* RDS */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_ds (ch, CHSL_RDS, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 00764: /* BSR */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_nds (ch, CHSL_BSR, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 00766: /* WRS */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_ds (ch, CHSL_WRS, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 00770: /* WEF */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_nds (ch, CHSL_WEF, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 00772: /* REW */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_nds (ch, CHSL_REW, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 01764: /* BSF */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_nds (ch, CHSL_BSF, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 01772: /* RUN */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_nds (ch, CHSL_RUN, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; case 00776: /* SDN */ - if (prot_trap (0) || sel_trap (PC)) break; + if (prot_trap (0) || sel_trap (PC)) + break; ch = GET_U_CH (IR); reason = ch_op_nds (ch, CHSL_SDN, GET_U_UNIT (ea)); chtr_pend = chtr_eval (NULL); /* eval chan traps */ break; default: - if (stop_illop) reason = STOP_ILLEG; + if (stop_illop) + reason = STOP_ILLEG; break; } } /* end else */ @@ -1784,18 +1929,21 @@ while (reason == SCPE_OK) { /* loop until error */ t_stat r; for (i = 0; (i < HALT_IO_LIMIT) && !ch_qidle (); i++) { sim_interval = 0; - if (r = sim_process_event ()) return r; /* process events */ + if (r = sim_process_event ()) /* process events */ + return r; chtr_pend = chtr_eval (NULL); /* eval chan traps */ while (ch_req) { /* until no ch req */ for (j = 0; j < NUM_CHAN; j++) { /* loop thru channels */ if (ch_req & REQ_CH (j)) { /* channel request? */ - if (r = ch_proc (j)) return r; + if (r = ch_proc (j)) + return r; } chtr_pend = chtr_eval (NULL); } } /* end while ch_req */ } /* end for wait */ - if (chtr_pend) reason = 0; /* trap? cancel HALT */ + if (chtr_pend) /* trap? cancel HALT */ + reason = 0; } /* end if HALT */ } /* end if reason */ } /* end while */ @@ -1813,9 +1961,12 @@ tag = tag & INST_M_TAG; if (tag) { if (mode_multi) { uint32 r = 0; - if (tag & 1) r = r | XR[1]; - if (tag & 2) r = r | XR[2]; - if (tag & 4) r = r | XR[4]; + if (tag & 1) + r = r | XR[1]; + if (tag & 2) + r = r | XR[2]; + if (tag & 4) + r = r | XR[4]; return r & eamask; } return XR[tag] & eamask; @@ -1836,9 +1987,12 @@ tag = tag & INST_M_TAG; if (tag) { if (mode_multi) { uint32 r = 0; - if (tag & 1) r = r | XR[1]; - if (tag & 2) r = r | XR[2]; - if (tag & 4) r = r | XR[4]; + if (tag & 1) + r = r | XR[1]; + if (tag & 2) + r = r | XR[2]; + if (tag & 4) + r = r | XR[4]; put_xr (tag, r); return r & eamask; } @@ -1856,9 +2010,12 @@ dat = dat & eamask; if (tag) { if (mode_multi) { - if (tag & 1) XR[1] = dat; - if (tag & 2) XR[2] = dat; - if (tag & 4) XR[4] = dat; + if (tag & 1) + XR[1] = dat; + if (tag & 2) + XR[2] = dat; + if (tag & 4) + XR[4] = dat; } else XR[tag] = dat; } @@ -1876,8 +2033,10 @@ if (mode_ftrap) { return TRUE; } else { - if (spill & TRAP_F_AC) ind_ovf = 1; - if (spill & TRAP_F_MQ) ind_mqo = 1; + if (spill & TRAP_F_AC) + ind_ovf = 1; + if (spill & TRAP_F_MQ) + ind_mqo = 1; } return FALSE; } @@ -1901,8 +2060,10 @@ void WriteTAD (uint32 pa, uint32 addr, uint32 decr) { t_uint64 mem; -if (inst_base) decr |= TRAP_F_BINST; -if (data_base) decr |= TRAP_F_BDATA; +if (inst_base) + decr |= TRAP_F_BINST; +if (data_base) + decr |= TRAP_F_BDATA; mem = ReadP (pa) & ~(XMASK | AMASK); mem |= (((t_uint64) (decr & AMASK)) << INST_V_DEC) | ((t_uint64) (addr & AMASK)); @@ -2029,7 +2190,8 @@ mode_ctrap = 0; mode_strap = 0; mode_ftrap = 1; mode_storn = 0; -if (cpu_model & (I_94|I_CT)) mode_multi = 0; +if (cpu_model & (I_94|I_CT)) + mode_multi = 0; else mode_multi = 1; mode_user = 0; inst_base = 0; @@ -2040,10 +2202,13 @@ chtr_inht = chtr_inhi = 0; ht_pend = 0; SLT = 0; XR[0] = 0; -if (M == NULL) M = (t_uint64 *) calloc (MAXMEMSIZE, sizeof (t_uint64)); -if (M == NULL) return SCPE_MEM; +if (M == NULL) + M = (t_uint64 *) calloc (MAXMEMSIZE, sizeof (t_uint64)); +if (M == NULL) + return SCPE_MEM; pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -2053,10 +2218,13 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr ea, UNIT *uptr, int32 sw) { -if (vptr == NULL) return SCPE_ARG; -if ((sw & (SWMASK ('A') | SWMASK ('B')))? (ea > AMASK): (ea >= MEMSIZE)) return SCPE_NXM; +if (vptr == NULL) + return SCPE_ARG; +if ((sw & (SWMASK ('A') | SWMASK ('B')))? (ea > AMASK): (ea >= MEMSIZE)) + return SCPE_NXM; if ((sw & SWMASK ('B')) || - ((sw & SWMASK ('V')) && mode_user && inst_base)) ea = ea | BCORE_BASE; + ((sw & SWMASK ('V')) && mode_user && inst_base)) + ea = ea | BCORE_BASE; *vptr = M[ea] & DMASK; return SCPE_OK; } @@ -2065,8 +2233,10 @@ return SCPE_OK; t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw) { -if ((sw & (SWMASK ('A') | SWMASK ('B')))? (ea > AMASK): (ea >= MEMSIZE)) return SCPE_NXM; -if (sw & SWMASK ('B')) ea = ea | BCORE_BASE; +if ((sw & (SWMASK ('A') | SWMASK ('B')))? (ea > AMASK): (ea >= MEMSIZE)) + return SCPE_NXM; +if (sw & SWMASK ('B')) + ea = ea | BCORE_BASE; M[ea] = val & DMASK; return SCPE_OK; } @@ -2089,7 +2259,8 @@ else { uptr->capac = STDMEMSIZE; chuptr->flags |= UNIT_ATTABLE; } -if (!(cpu_model & I_94)) mode_multi = 1; +if (!(cpu_model & I_94)) + mode_multi = 1; return SCPE_OK; } @@ -2097,8 +2268,10 @@ return SCPE_OK; t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (cpu_model & I_CT) fputs ("CTSS", st); -else if (cpu_model & I_94) fputs ("7094", st); +if (cpu_model & I_CT) + fputs ("CTSS", st); +else if (cpu_model & I_94) + fputs ("7094", st); else fputs ("7090", st); return SCPE_OK; } @@ -2129,11 +2302,13 @@ if (pc & HIST_PC) { if (hst_ch & HIST_CH_I) { /* IO only? */ uint32 op = GET_OPC (ir); /* get opcode */ if ((ir & INST_T_DEC) || - !(inst_io_tab[op / 32] & (1u << (op & 037)))) return; + !(inst_io_tab[op / 32] & (1u << (op & 037)))) + return; } } hst_p = (hst_p + 1); /* next entry */ -if (hst_p >= hst_lnt) hst_p = 0; +if (hst_p >= hst_lnt) + hst_p = 0; hst[hst_p].pc = pc; hst[hst_p].ir = ir; hst[hst_p].ac = AC; @@ -2153,12 +2328,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -2167,10 +2344,13 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; - if (sim_switches & SWMASK ('I')) hst_ch = HIST_CH_I|HIST_CH_C; - else if (sim_switches & SWMASK ('C')) hst_ch = HIST_CH_C; + if (sim_switches & SWMASK ('I')) + hst_ch = HIST_CH_I|HIST_CH_C; + else if (sim_switches & SWMASK ('C')) + hst_ch = HIST_CH_C; else hst_ch = 0; } return SCPE_OK; @@ -2190,8 +2370,10 @@ sim_eval = ir; if (pc & HIST_PC) { /* instruction? */ fputs ("CPU ", st); fprintf (st, "%05o ", pc & AMASK); - if (rpt == 0) fprintf (st, " "); - else if (rpt < 1000000) fprintf (st, "%6d ", rpt); + if (rpt == 0) + fprintf (st, " "); + else if (rpt < 1000000) + fprintf (st, "%6d ", rpt); else fprintf (st, "%5dM ", rpt / 1000000); fprint_val (st, ac, 8, 38, PV_RZRO); fputc (' ', st); @@ -2199,7 +2381,8 @@ if (pc & HIST_PC) { /* instruction? */ fputc (' ', st); fprint_val (st, si, 8, 36, PV_RZRO); fputc (' ', st); - if (ir & INST_T_DEC) fprintf (st, " "); + if (ir & INST_T_DEC) + fprintf (st, " "); else fprintf (st, "%05o ", ea); if (fprint_sym (st, pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M')) > 0) { fputs ("(undefined) ", st); @@ -2210,9 +2393,9 @@ if (pc & HIST_PC) { /* instruction? */ fprint_val (st, opnd, 8, 36, PV_RZRO); fputc (']', st); } - fputc ('\n', st); /* end line */ - } /* end if instruction */ -else if (ch = HIST_CH (pc)) { /* channel? */ + fputc ('\n', st); /* end line */ + } /* end if instruction */ +else if (ch = HIST_CH (pc)) { /* channel? */ fprintf (st, "CH%c ", 'A' + ch - 1); fprintf (st, "%05o ", pc & AMASK); fputs (" ", st); @@ -2222,8 +2405,8 @@ else if (ch = HIST_CH (pc)) { /* channel? */ fputs ("(undefined) ", st); fprint_val (st, ir, 8, 36, PV_RZRO); } - fputc ('\n', st); /* end line */ - } /* end else channel */ + fputc ('\n', st); /* end line */ + } /* end else channel */ return SCPE_OK; } @@ -2236,14 +2419,17 @@ char *cptr = (char *) desc; t_stat r; InstHistory *h; -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +if (di < 0) + di = di + hst_lnt; fprintf (st, " PC repeat AC MQ SI EA IR\n\n"); for (k = 0; k < lnt; k++) { /* print specified */ h = &hst[(++di) % hst_lnt]; /* entry pointer */ diff --git a/I7094/i7094_cpu1.c b/I7094/i7094_cpu1.c index dc6dd0b2..18afca55 100644 --- a/I7094/i7094_cpu1.c +++ b/I7094/i7094_cpu1.c @@ -1,6 +1,6 @@ /* i7094_cpu1.c: IBM 7094 CPU complex instructions - Copyright (c) 2003-2006, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -72,12 +72,14 @@ t_uint64 mop = op & MMASK; AC = AC & AC_S; /* isolate AC sign */ if ((AC? 1: 0) ^ ((op & SIGN)? 1: 0)) { /* signs diff? sub */ - if (mac >= mop) AC = AC | (mac - mop); /* AC >= MQ */ + if (mac >= mop) /* AC >= MQ */ + AC = AC | (mac - mop); else AC = (AC ^ AC_S) | (mop - mac); /* <, sign change */ } else { AC = AC | ((mac + mop) & AC_MMASK); /* signs same, add */ - if ((AC ^ mac) & AC_P) ind_ovf = 1; /* P change? overflow */ + if ((AC ^ mac) & AC_P) /* P change? overflow */ + ind_ovf = 1; } return; } @@ -88,14 +90,16 @@ void op_mpy (t_uint64 ac, t_uint64 sr, uint32 sc) { uint32 sign; -if (sc == 0) return; /* sc = 0? nop */ +if (sc == 0) /* sc = 0? nop */ + return; sign = ((MQ & SIGN)? 1: 0) ^ ((sr & SIGN)? 1: 0); /* result sign */ ac = ac & AC_MMASK; /* clear AC sign */ sr = sr & MMASK; /* mpy magnitude */ MQ = MQ & MMASK; /* MQ magnitude */ if (sr && MQ) { /* mpy != 0? */ while (sc--) { /* for sc */ - if (MQ & 1) ac = (ac + sr) & AC_MMASK; /* MQ35? AC += mpy */ + if (MQ & 1) /* MQ35? AC += mpy */ + ac = (ac + sr) & AC_MMASK; MQ = (MQ >> 1) | ((ac & 1) << 34); /* AC'MQ >> 1 */ ac = ac >> 1; } @@ -115,11 +119,13 @@ t_bool op_div (t_uint64 sr, uint32 sc) { uint32 signa, signm; -if (sc == 0) return FALSE; /* sc = 0? nop */ +if (sc == 0) /* sc = 0? nop */ + return FALSE; signa = (AC & AC_S)? 1: 0; /* get signs */ signm = (sr & SIGN)? 1: 0; sr = sr & MMASK; /* get dvr magn */ -if ((AC & AC_MMASK) >= sr) return TRUE; /* |AC| >= |sr|? */ +if ((AC & AC_MMASK) >= sr) /* |AC| >= |sr|? */ + return TRUE; AC = AC & AC_MMASK; /* AC, MQ magn */ MQ = MQ & MMASK; while (sc--) { /* for sc */ @@ -130,8 +136,10 @@ while (sc--) { /* for sc */ MQ = MQ | 1; /* set quo bit */ } } -if (signa ^ signm) MQ = MQ | SIGN; /* quo neg? */ -if (signa) AC = AC | AC_S; /* rem neg? */ +if (signa ^ signm) /* quo neg? */ + MQ = MQ | SIGN; +if (signa) /* rem neg? */ + AC = AC | AC_S; return FALSE; /* div ok */ } @@ -145,7 +153,8 @@ if ((sc >= 35)? /* shift >= 35? */ ((AC & MMASK) != 0): /* test all bits for ovf */ (((AC & MMASK) >> (35 - sc)) != 0)) /* test only 35-sc bits */ ind_ovf = 1; -if (sc >= 37) AC = AC & AC_S; /* sc >= 37? result 0 */ +if (sc >= 37) /* sc >= 37? result 0 */ + AC = AC & AC_S; else AC = (AC & AC_S) | ((AC << sc) & AC_MMASK); /* shift, save sign */ return; } @@ -154,7 +163,8 @@ void op_ars (uint32 addr) { uint32 sc = addr & SCMASK; -if (sc >= 37) AC = AC & AC_S; /* sc >= 37? result 0 */ +if (sc >= 37) /* sc >= 37? result 0 */ + AC = AC & AC_S; else AC = (AC & AC_S) | ((AC & AC_MMASK) >> sc); /* shift, save sign */ return; } @@ -167,9 +177,11 @@ AC = AC & AC_MMASK; /* clear AC sign */ for (sc = addr & SCMASK; sc != 0; sc--) { /* for SC */ AC = ((AC << 1) & AC_MMASK) | ((MQ >> 34) & 1); /* AC'MQ << 1 */ MQ = (MQ & SIGN) | ((MQ << 1) & MMASK); /* preserve MQ sign */ - if (AC & AC_P) ind_ovf = 1; /* if P, overflow */ + if (AC & AC_P) /* if P, overflow */ + ind_ovf = 1; } -if (MQ & SIGN) AC = AC | AC_S; /* set ACS from MQS */ +if (MQ & SIGN) /* set ACS from MQS */ + AC = AC | AC_S; return; } @@ -194,7 +206,8 @@ if (sc != 0) { MQ = (mac >> (sc - 35)) & MMASK; /* MQ has AC only */ else MQ = 0; /* >72? MQ = 0 */ } -if (AC & AC_S) MQ = MQ | SIGN; /* set MQS from ACS */ +if (AC & AC_S) /* set MQS from ACS */ + MQ = MQ | SIGN; return; } @@ -206,7 +219,8 @@ for (sc = addr & SCMASK; sc != 0; sc--) { /* for SC */ AC = (AC & AC_S) | ((AC << 1) & AC_MMASK) | /* AC'MQ << 1 */ ((MQ >> 35) & 1); /* preserve AC sign */ MQ = (MQ << 1) & DMASK; - if (AC & AC_P) ind_ovf = 1; /* if P, overflow */ + if (AC & AC_P) /* if P, overflow */ + ind_ovf = 1; } return; } @@ -243,11 +257,13 @@ uint32 ch, spill; switch (addr) { case 00000: /* CLM */ - if (cpu_model & I_9X) AC = AC & AC_S; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + AC = AC & AC_S; break; case 00001: /* LBT */ - if ((AC & 1) != 0) PC = (PC + 1) & AMASK; + if ((AC & 1) != 0) + PC = (PC + 1) & AMASK; break; case 00002: /* CHS */ @@ -263,7 +279,8 @@ switch (addr) { break; case 00005: /* IOT */ - if (ind_ioc) ind_ioc = 0; + if (ind_ioc) + ind_ioc = 0; else PC = (PC + 1) & AMASK; break; @@ -272,7 +289,8 @@ switch (addr) { break; case 00007: /* ETM */ - if (cpu_model & I_9X) mode_ttrap = 1; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + mode_ttrap = 1; break; case 00010: /* RND */ @@ -283,12 +301,14 @@ switch (addr) { case 00011: /* FRN */ if (cpu_model & I_9X) { /* 709X only */ spill = op_frnd (); - if (spill) fp_trap (spill); + if (spill) + fp_trap (spill); } break; case 00012: /* DCT */ - if (ind_dvc) ind_dvc = 0; + if (ind_dvc) + ind_dvc = 0; else PC = (PC + 1) & AMASK; break; @@ -299,11 +319,13 @@ switch (addr) { break; case 00016: /* LMTM */ - if (cpu_model & I_94) mode_multi = 0; /* 709X only */ + if (cpu_model & I_94) /* 709X only */ + mode_multi = 0; break; case 00140: /* SLF */ - if (cpu_model & I_9X) SLT = 0; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + SLT = 0; break; case 00141: case 00142: case 00143: case 00144: /* SLN */ @@ -320,7 +342,8 @@ switch (addr) { case 01000: case 02000: case 03000: case 04000: /* BTT */ case 05000: case 06000: case 07000: case 10000: if (cpu_model & I_9X) { /* 709X only */ - if (sel_trap (PC)) break; /* sel trap? */ + if (sel_trap (PC)) /* sel trap? */ + break; ch = GET_U_CH (addr); /* get channel */ if (ch_flags[ch] & CHF_BOT) /* BOT? */ ch_flags[ch] &= ~CHF_BOT; /* clear */ @@ -351,11 +374,13 @@ uint32 t, ch; switch (addr) { case 00000: /* CLM */ - if (cpu_model & I_9X) AC = AC & AC_S; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + AC = AC & AC_S; break; case 00001: /* PBT */ - if ((AC & AC_P) != 0) PC = (PC + 1) & AMASK; + if ((AC & AC_P) != 0) + PC = (PC + 1) & AMASK; break; case 00002: /* EFTM */ @@ -366,31 +391,38 @@ switch (addr) { break; case 00003: /* SSM */ - if (cpu_model & I_9X) AC = AC | AC_S; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + AC = AC | AC_S; break; case 00004: /* LFTM */ - if (cpu_model & I_9X) mode_ftrap = 0; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + mode_ftrap = 0; break; case 00005: /* ESTM */ - if (cpu_model & I_9X) mode_strap = 1; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + mode_strap = 1; break; case 00006: /* ECTM */ - if (cpu_model & I_9X) mode_ctrap = 1; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + mode_ctrap = 1; break; case 00007: /* LTM */ - if (cpu_model & I_9X) mode_ttrap = 0; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + mode_ttrap = 0; break; case 00010: /* LSNM */ - if (cpu_model & I_9X) mode_storn = 0; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + mode_storn = 0; break; case 00012: /* RTT (704) */ - if (cpu_model & I_9X) sel_trap (PC); /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + sel_trap (PC); break; case 00016: /* EMTM */ @@ -398,14 +430,16 @@ switch (addr) { break; case 00140: /* SLF */ - if (cpu_model & I_9X) SLT = 0; /* 709X only */ + if (cpu_model & I_9X) /* 709X only */ + SLT = 0; break; case 00141: case 00142: case 00143: case 00144: /* SLT */ if (cpu_model & I_9X) { /* 709X only */ t = SLT & (1u << (00144 - addr)); SLT = SLT & ~t; - if (t != 0) PC = (PC + 1) & AMASK; + if (t != 0) + PC = (PC + 1) & AMASK; } break; @@ -418,7 +452,8 @@ switch (addr) { case 001000: case 002000: case 003000: case 004000: /* ETT */ case 005000: case 006000: case 007000: case 010000: - if (sel_trap (PC)) break; /* sel trap? */ + if (sel_trap (PC)) /* sel trap? */ + break; ch = GET_U_CH (addr); /* get channel */ if (ch_flags[ch] & CHF_EOT) /* EOT? */ ch_flags[ch] = ch_flags[ch] & ~CHF_EOT; /* clear */ @@ -448,7 +483,8 @@ MQ = 0; /* clear MQ */ fp_unpack (AC, 0, 1, &op1); /* unpack AC */ fp_unpack (sr, 0, 0, &op2); /* unpack sr */ if (op1.ch > op2.ch) { /* AC exp > SR exp? */ - if (AC & AC_P) op1.s = 1; /* AC P or's with S */ + if (AC & AC_P) /* AC P or's with S */ + op1.s = 1; t = op1; /* swap operands */ op1 = op2; op2 = t; @@ -456,7 +492,8 @@ if (op1.ch > op2.ch) { /* AC exp > SR exp? */ } diff = op2.ch - op1.ch; /* exp diff */ if (diff) { /* any shift? */ - if ((diff < 0) || (diff > 077)) op1.fr = 0; /* diff > 63? */ + if ((diff < 0) || (diff > 077)) /* diff > 63? */ + op1.fr = 0; else op1.fr = op1.fr >> diff; /* no, denormalize */ } if (op1.s ^ op2.s) { /* subtract? */ @@ -577,7 +614,8 @@ fp_unpack (sr, sr1, 0, &op2); /* unpack sr'sr1 */ if (op1.ch > op2.ch) { /* AC exp > SR exp? */ if (((op1.ch - op2.ch) > 0100) && (AC & B9)) ; /* early out */ else SI = FP_PACK36 (op1.s, op1.ch, FP_HIFRAC (op1.fr)); - if (AC & AC_P) op1.s = 1; /* AC P or's with S */ + if (AC & AC_P) /* AC P or's with S */ + op1.s = 1; t = op1; /* swap operands */ op1 = op2; op2 = t; @@ -590,7 +628,8 @@ else { /* AC <= SR */ } diff = op2.ch - op1.ch; /* exp diff */ if (diff) { /* any shift? */ - if ((diff < 0) || (diff > 077)) op1.fr = 0; /* diff > 63? */ + if ((diff < 0) || (diff > 077)) /* diff > 63? */ + op1.fr = 0; else op1.fr = op1.fr >> diff; /* no, denormalize */ } if (op1.s ^ op2.s) { /* subtract? */ @@ -659,7 +698,8 @@ if (op1.fr) { /* A'B != 0? */ SI = tx >> FP_N_FR; /* SI keeps B * C */ } else { - if (norm) SI = sr; /* early out */ + if (norm) /* early out */ + SI = sr; else SI = FP_PACK36 (op2.s, op2.ch, 0); } if (norm) { /* normalize? */ @@ -740,21 +780,25 @@ tr = tr << FP_N_FR; /* R << 27 */ tq1d = (tq1 * ((t_uint64) FP_LOFRAC (sr1))) & /* Q1 * D */ ~((t_uint64) FP_FMASK); /* top 27 bits */ csign = (tr < tq1d); /* correction sign */ -if (csign) trmq1d = tq1d - tr; /* |R|<|Q1*D|? compl */ +if (csign) /* |R|<|Q1*D|? compl */ + trmq1d = tq1d - tr; else trmq1d = tr - tq1d; /* no, subtr ok */ SI = FP_PACK36 (op1.s, op1.ch, tq1); /* SI has Q1 */ if (trmq1d >= (2 * op2.fr)) { /* |R-Q1*D| >= 2*|C|? */ - AC = FP_PACK38 (csign ^ ac_s, 0, FP_HIFRAC (trmq1d)); /* AC has R-Q1*D */ + AC = FP_PACK38 (csign ^ ac_s, 0, FP_HIFRAC (trmq1d)); /* AC has R-Q1*D */ MQ = (csign ^ ac_s)? SIGN: 0; /* MQ = sign only */ return TRAP_F_DVC; /* divide check */ } tq2 = fp_fracdiv (trmq1d, op2.fr, NULL); /* |R-Q1*D| / |C| */ -if (trmq1d >= op2.fr) tq2 &= ~((t_uint64) 1); /* can only gen 27b quo */ +if (trmq1d >= op2.fr) /* can only gen 27b quo */ + tq2 &= ~((t_uint64) 1); op1.fr = tq1 << FP_N_FR; /* shift Q1 into place */ -if (csign) op1.fr = op1.fr - tq2; /* sub or add Q2 */ +if (csign) /* sub or add Q2 */ + op1.fr = op1.fr - tq2; else op1.fr = op1.fr + tq2; fp_norm (&op1); /* normalize */ -if (op1.fr) mqch = op1.ch - FP_N_FR; /* non-zero? */ +if (op1.fr) /* non-zero? */ + mqch = op1.ch - FP_N_FR; else op1.ch = mqch = 0; /* clear AC, MQ exp */ return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */ } @@ -786,7 +830,8 @@ return spill; t_uint64 fp_fracdiv (t_uint64 dvd, t_uint64 dvr, t_uint64 *rem) { dvr = dvr >> FP_N_FR; -if (rem) *rem = dvd % dvr; +if (rem) + *rem = dvd % dvr; return (dvd / dvr); } @@ -795,7 +840,8 @@ return (dvd / dvr); void fp_norm (UFP *op) { op->fr = op->fr & FP_DFMASK; /* mask fraction */ -if (op->fr == 0) return; /* zero? */ +if (op->fr == 0) /* zero? */ + return; while ((op->fr & FP_FNORM) == 0) { /* until norm */ op->fr = op->fr << 1; /* lsh 1 */ op->ch--; /* decr exp */ @@ -828,10 +874,14 @@ uint32 spill; AC = FP_PACK38 (op->s, op->ch, FP_HIFRAC (op->fr)); /* pack AC */ MQ = FP_PACK36 (mqs, mqch, FP_LOFRAC (op->fr)); /* pack MQ */ -if (op->ch > FP_M_CH) spill = TRAP_F_OVF | TRAP_F_AC; /* check AC exp */ -else if (op->ch < 0) spill = TRAP_F_AC; +if (op->ch > FP_M_CH) /* check AC exp */ + spill = TRAP_F_OVF | TRAP_F_AC; +else if (op->ch < 0) + spill = TRAP_F_AC; else spill = 0; -if (mqch > FP_M_CH) spill |= (TRAP_F_OVF | TRAP_F_MQ); /* check MQ exp */ -else if (mqch < 0) spill |= TRAP_F_MQ; +if (mqch > FP_M_CH) /* check MQ exp */ + spill |= (TRAP_F_OVF | TRAP_F_MQ); +else if (mqch < 0) + spill |= TRAP_F_MQ; return spill; } diff --git a/I7094/i7094_dat.h b/I7094/i7094_dat.h index 4d86ecb2..b50b38c3 100644 --- a/I7094/i7094_dat.h +++ b/I7094/i7094_dat.h @@ -1,6 +1,6 @@ /* i7094_dat.h: IBM 7094 data conversion tables - Copyright (c) 2003-2006, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/I7094/i7094_defs.h b/I7094/i7094_defs.h index 8eff8762..633a75c7 100644 --- a/I7094/i7094_defs.h +++ b/I7094/i7094_defs.h @@ -1,6 +1,6 @@ /* i7094_defs.h: IBM 7094 simulator definitions - Copyright (c) 2003-2006, Robert M Supnik + Copyright (c) 2003-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/I7094/i7094_drm.c b/I7094/i7094_drm.c index 798b65ee..f8a15306 100644 --- a/I7094/i7094_drm.c +++ b/I7094/i7094_drm.c @@ -1,6 +1,6 @@ /* i7094_drm.c: 7289/7320A drum simulator - Copyright (c) 2005-2006, Robert M Supnik + Copyright (c) 2005-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -163,15 +163,18 @@ DEVICE drm_dev = { t_stat drm_chsel (uint32 ch, uint32 sel, uint32 unit) { drm_ch = ch; /* save channel */ -if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */ +if (sel & CHSL_NDS) /* nds? nop */ + return ch6_end_nds (ch); switch (sel) { /* case on cmd */ case CHSL_RDS: /* read */ case CHSL_WRS: /* write */ - if (drm_sta != DRM_IDLE) return ERR_STALL; /* busy? */ + if (drm_sta != DRM_IDLE) /* busy? */ + return ERR_STALL; drm_sta = DRM_1ST; /* initial state */ - if (sel == CHSL_WRS) drm_op = 1; /* set read/write */ + if (sel == CHSL_WRS) /* set read/write */ + drm_op = 1; else drm_op = 0; /* LCHx sends addr */ break; /* wait for addr */ @@ -201,9 +204,11 @@ if (drm_sta == DRM_1ST) { drm_da = DRM_GETDA (val); /* get drum addr */ cp = GET_POS (drm_time); /* current pos in sec */ dp = (drm_da & DRM_SCMASK) - cp; /* delta to desired pos */ - if (dp <= 0) dp = dp + DRM_NUMWDS; /* if neg, add rev */ + if (dp <= 0) /* if neg, add rev */ + dp = dp + DRM_NUMWDS; sim_activate (&drm_unit[u], dp * drm_time); /* schedule */ - if (drm_op) ch6_req_wr (ch, U_DRM); /* if write, get word */ + if (drm_op) /* if write, get word */ + ch6_req_wr (ch, U_DRM); drm_sta = DRM_DATA; drm_chob = 0; /* clr, inval buffer */ drm_chob_v = 0; @@ -236,12 +241,15 @@ switch (drm_sta) { /* case on state */ case DRM_DATA: /* data */ if (drm_op) { /* write? */ - if (drm_chob_v) drm_chob_v = 0; /* valid? clear */ + if (drm_chob_v) /* valid? clear */ + drm_chob_v = 0; else if (ch6_qconn (drm_ch, U_DRM)) /* no, chan conn? */ ind_ioc = 1; /* io check */ fbuf[drm_da] = drm_chob; /* get data */ - if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; - if (!drm_da_incr ()) ch6_req_wr (drm_ch, U_DRM); + if (drm_da >= uptr->hwmark) + uptr->hwmark = drm_da + 1; + if (!drm_da_incr ()) + ch6_req_wr (drm_ch, U_DRM); } else{ /* read */ ch6_req_rd (drm_ch, U_DRM, fbuf[drm_da], 0); /* send word to channel */ @@ -265,7 +273,8 @@ return SCPE_OK; t_bool drm_da_incr (void) { drm_da = drm_da + 1; -if (drm_da & DRM_SCMASK) return FALSE; +if (drm_da & DRM_SCMASK) + return FALSE; drm_sta = DRM_EOS; return TRUE; } @@ -281,6 +290,7 @@ drm_op = 0; drm_sta = DRM_IDLE; drm_chob = 0; drm_chob_v = 0; -for (i = 0; i < dptr->numunits; i++) sim_cancel (dptr->units + i); +for (i = 0; i < dptr->numunits; i++) + sim_cancel (dptr->units + i); return SCPE_OK; } diff --git a/I7094/i7094_dsk.c b/I7094/i7094_dsk.c index d0c2f7c9..710725f1 100644 --- a/I7094/i7094_dsk.c +++ b/I7094/i7094_dsk.c @@ -1,6 +1,6 @@ /* i7094_dsk.c: 7631 file control (disk/drum) simulator - Copyright (c) 2005-2006, Robert M Supnik + Copyright (c) 2005-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -434,7 +434,8 @@ t_stat dsk_chsel (uint32 ch, uint32 sel, uint32 unit) uint32 u; dsk_ch = ch; -if (dsk_sta != DSK_IDLE) dsk_uend (ch, DSKS_INVS); /* not idle? seq check */ +if (dsk_sta != DSK_IDLE) /* not idle? seq check */ + dsk_uend (ch, DSKS_INVS); switch (sel) { @@ -453,8 +454,10 @@ switch (sel) { if (dsk_mode == DSKC_WFMT) /* write format? */ return dsk_uend (ch, DSKS_INVS); /* sequence error */ case CHSL_WRS: /* write */ - if (dsk_mode == 0) dsk_uend (ch, DSKS_INVS); /* no mode? seq check */ - if (dsk_mode == DSKC_WFMT) sel = CHSL_FMT; /* format? fake sel */ + if (dsk_mode == 0) /* no mode? seq check */ + dsk_uend (ch, DSKS_INVS); + if (dsk_mode == DSKC_WFMT) /* format? fake sel */ + sel = CHSL_FMT; u = (dsk_acc * DSK_NUMDR) + dsk_mod; /* access unit number */ if (sim_is_active (&dsk_unit[u])) /* access in use? */ return dsk_uend (ch, DSKS_ACCN); /* access not ready */ @@ -473,7 +476,8 @@ return SCPE_OK; t_stat dsk_chwr (uint32 ch, t_uint64 val, uint32 stopf) { -if (stopf) dsk_stop = 1; /* stop? */ +if (stopf) /* stop? */ + dsk_stop = 1; else { val = val & DMASK; @@ -513,8 +517,10 @@ dsk_sta = DSK_IDLE; /* ctrl is idle */ for (i = 0; i < 8; i++) { /* get chars from cmd */ d = (uint32) (cmd >> (6 * (9 - i))) & BCD_MASK; - if (d == BCD_ZERO) d = 0; - else if (d == 0) d = BCD_ZERO; /* BCD zero cvt */ + if (d == BCD_ZERO) + d = 0; + else if (d == 0) /* BCD zero cvt */ + d = BCD_ZERO; bcd[i] = d; } @@ -640,11 +646,13 @@ switch (dsk_sta) { /* case on state */ return SCPE_OK; } dat = dsk_buf[dsk_rptr++]; /* get word */ - if (!dsk_stop) ch9_req_rd (dsk_ch, dat); /* send wd to chan */ + if (!dsk_stop) /* send wd to chan */ + ch9_req_rd (dsk_ch, dat); break; case CHSL_SNS|CHSL_3RD: /* 3rd state */ - if (dsk_qdone (dsk_ch)) return SCPE_OK; /* done? exit */ + if (dsk_qdone (dsk_ch)) /* done? exit */ + return SCPE_OK; dsk_sta = CHSL_SNS; /* repeat sequence */ break; } @@ -693,18 +701,22 @@ switch (dsk_sta) { /* case on state */ case CHSL_RDS|CHSL_2ND: /* read data transmit */ if (r = dsk_xfer_done (uaptr, dtyp)) { /* transfer done? */ - if (r != ERR_ENDRC) return r; /* error? */ + if (r != ERR_ENDRC) /* error? */ + return r; dsk_sta = CHSL_RDS|CHSL_3RD; /* next state */ sim_activate (uaptr, dsk_gtime); /* gap time */ return SCPE_OK; } rdat = dsk_buf[dsk_rptr++]; /* get word */ - if (dsk_rptr == T1STREC) dsk_rptr++; /* if THA, skip after HA */ - if (!dsk_stop) ch9_req_rd (dsk_ch, rdat); /* give to channel */ + if (dsk_rptr == T1STREC) /* if THA, skip after HA */ + dsk_rptr++; + if (!dsk_stop) /* give to channel */ + ch9_req_rd (dsk_ch, rdat); break; case CHSL_RDS|CHSL_3RD: /* read end rec/trk */ - if (dsk_qdone (dsk_ch)) return SCPE_OK; /* done? exit */ + if (dsk_qdone (dsk_ch)) /* done? exit */ + return SCPE_OK; dsk_sta = CHSL_RDS; /* repeat sequence */ break; @@ -719,28 +731,35 @@ switch (dsk_sta) { /* case on state */ break; case CHSL_WRS|CHSL_2ND: /* write data transmit */ - if (dsk_chob_v) dsk_chob_v = 0; /* valid? clear */ - else if (!dsk_stop) ch9_set_ioc (dsk_ch); /* no, no stop? io chk */ + if (dsk_chob_v) /* valid? clear */ + dsk_chob_v = 0; + else if (!dsk_stop) /* no, no stop? io chk */ + ch9_set_ioc (dsk_ch); if (dsk_wchk) { /* write check? */ if (dsk_buf[dsk_rptr++] != dsk_chob) /* data mismatch? */ return dsk_uend (dsk_ch, DSKS_CMPC); /* error */ } else dsk_buf[dsk_rptr++] = dsk_chob; /* write, store word */ - if (dsk_rptr == T1STREC) dsk_rptr++; /* if THA, skip after HA */ + if (dsk_rptr == T1STREC) /* if THA, skip after HA */ + dsk_rptr++; if (r = dsk_xfer_done (uaptr, dtyp)) { /* transfer done? */ - if (r != ERR_ENDRC) return r; /* error? */ + if (r != ERR_ENDRC) /* error? */ + return r; dsk_sta = CHSL_WRS|CHSL_3RD; /* next state */ sim_activate (uaptr, dsk_gtime); /* gap time */ return SCPE_OK; } - if (!dsk_stop) ch_req |= REQ_CH (dsk_ch); /* more to do */ + if (!dsk_stop) /* more to do */ + ch_req |= REQ_CH (dsk_ch); break; case CHSL_WRS|CHSL_3RD: /* write done */ if (!dsk_wchk) { /* if write */ - if (r = dsk_wr_trk (udptr, trk)) return r; /* write track; err? */ + if (r = dsk_wr_trk (udptr, trk)) /* write track; err? */ + return r; } - if (dsk_qdone (dsk_ch)) return SCPE_OK; /* done? exit */ + if (dsk_qdone (dsk_ch)) /* done? exit */ + return SCPE_OK; dsk_sta = CHSL_WRS; /* repeat sequence */ break; @@ -757,7 +776,8 @@ switch (dsk_sta) { /* case on state */ real 7320, 1301, 1302, or 2302. */ case CHSL_FMT: /* initialization */ - for (i = 0; i < DSK_BUFSIZ; i++) dsk_buf[i] = 0;/* clear track buf */ + for (i = 0; i < DSK_BUFSIZ; i++) /* clear track buf */ + dsk_buf[i] = 0; dsk_rbase = T1STREC; /* init record ptr */ dsk_rptr = 0; /* init format ptr */ dsk_fmt_cntr = 0; /* init counter */ @@ -771,7 +791,8 @@ switch (dsk_sta) { /* case on state */ if ((dtyp == TYPE_7320) || (dtyp == TYPE_1301)) format = fmt_thdr_7320; else format = fmt_thdr_1302; - if (!dsk_get_fmtc (dtyp, &fc)) return SCPE_OK; /* get fmt char; err? */ + if (!dsk_get_fmtc (dtyp, &fc)) /* get fmt char; err? */ + return SCPE_OK; if (fc != format[dsk_rptr++]) /* mismatch? */ return dsk_uend (dsk_ch, DSKS_FMTC); /* format check */ if (format[dsk_rptr] == 0) { /* end format? */ @@ -784,7 +805,8 @@ switch (dsk_sta) { /* case on state */ if ((dtyp == TYPE_7320) || (dtyp == TYPE_1301)) format = fmt_rhdr_7320; else format = fmt_rhdr_1302; - if (!dsk_get_fmtc (dtyp, &fc)) return SCPE_OK; /* get fmt char; err? */ + if (!dsk_get_fmtc (dtyp, &fc)) /* get fmt char; err? */ + return SCPE_OK; if (fc != format[dsk_rptr++]) /* mismatch? */ return dsk_uend (dsk_ch, DSKS_FMTC); /* format check */ if (format[dsk_rptr] == 0) { /* end format? */ @@ -794,8 +816,10 @@ switch (dsk_sta) { /* case on state */ break; case CHSL_FMT|CHSL_4TH: /* count record size */ - if (!dsk_get_fmtc (dtyp, &fc)) return SCPE_OK; /* get fmt char; err? */ - if (fc == BCD_ONE) dsk_rlim++; /* more record? */ + if (!dsk_get_fmtc (dtyp, &fc)) /* get fmt char; err? */ + return SCPE_OK; + if (fc == BCD_ONE) /* more record? */ + dsk_rlim++; else { uint32 rsiz = dsk_rlim / 6; /* rec size words */ if ((fc != BCD_TWO) || /* improper end? */ @@ -810,12 +834,14 @@ switch (dsk_sta) { /* case on state */ break; case CHSL_FMT|CHSL_5TH: /* record or track end */ - if (!dsk_get_fmtc (dtyp, &fc)) return SCPE_OK; /* get fmt char; err? */ + if (!dsk_get_fmtc (dtyp, &fc)) /* get fmt char; err? */ + return SCPE_OK; if (fc == BCD_TWO) { /* back to record header? */ dsk_rptr = 2; /* already done 2 chars */ dsk_sta = CHSL_FMT|CHSL_3RD; /* record header state */ } - else if (fc != BCD_ONE) dsk_uend (dsk_ch, DSKS_FMTC); /* format check */ + else if (fc != BCD_ONE) /* format check */ + dsk_uend (dsk_ch, DSKS_FMTC); else { if (!dsk_wchk) { /* actual write? */ trk = trk - (trk % dsk_tab[dtyp].trkpc); /* cyl start */ @@ -867,7 +893,8 @@ if (ferror (udptr->fileref)) { /* error? */ dsk_uend (dsk_ch, DSKS_DSKE); return SCPE_IOERR; } -for ( ; k < dsk_tab[dtyp].wdspt; k++) dsk_buf[k] = 0; /* zero fill */ +for ( ; k < dsk_tab[dtyp].wdspt; k++) /* zero fill */ + dsk_buf[k] = 0; dsk_rbase = T1STREC; /* record base */ rlnt = (uint32) dsk_buf[dsk_rbase + RLNT]; /* length */ dsk_rlim = dsk_rbase + rlnt + RDATA; /* end */ @@ -876,7 +903,8 @@ if ((rlnt == 0) || (dsk_rlim >= dsk_tab[dtyp].wdspt)) { /* invalid record? */ return STOP_INVFMT; } if (dsk_mode != DSKC_SREC) { /* not single record? */ - if (dsk_mode == DSKC_THA) dsk_rptr = 0; /* trk home addr? */ + if (dsk_mode == DSKC_THA) /* trk home addr? */ + dsk_rptr = 0; else { if (((dsk_rec << 24) ^ dsk_buf[THA2]) & HA2_MASK) { dsk_uend (dsk_ch, DSKS_NRCF); /* invalid HA2 */ @@ -919,7 +947,8 @@ t_stat dsk_xfer_done (UNIT *uaptr, uint32 dtyp) { uint32 rlnt; -if (dsk_rptr < dsk_rlim) return SCPE_OK; /* record done? */ +if (dsk_rptr < dsk_rlim) /* record done? */ + return SCPE_OK; if (dsk_stop || !ch9_qconn (dsk_ch) || /* stop or err disc or */ (dsk_mode == DSKC_SREC)) { /* single record? */ ch9_set_end (dsk_ch, 0); /* set end */ @@ -986,11 +1015,14 @@ t_bool dsk_get_fmtc (uint32 dtyp, uint8 *fc) uint32 cc = dsk_fmt_cntr % 6; if (cc == 0) { /* start of word? */ - if (dsk_chob_v) dsk_chob_v = 0; /* valid? clear */ - else if (!dsk_stop) ch9_set_ioc (dsk_ch); /* no, no stop? io chk */ + if (dsk_chob_v) /* valid? clear */ + dsk_chob_v = 0; + else if (!dsk_stop) /* no, no stop? io chk */ + ch9_set_ioc (dsk_ch); } *fc = ((uint8) (dsk_chob >> ((5 - cc) * 6))) & 077; /* get character */ -if ((cc == 5) && !dsk_stop) ch_req |= REQ_CH (dsk_ch); /* end of word? */ +if ((cc == 5) && !dsk_stop) /* end of word? */ + ch_req |= REQ_CH (dsk_ch); if (dsk_fmt_cntr++ >= dsk_tab[dtyp].fchpt) { /* track overflow? */ dsk_uend (dsk_ch, DSKS_FMTC); /* format check */ return FALSE; @@ -1004,9 +1036,12 @@ t_stat dsk_uend (uint32 ch, t_uint64 stat) { dsk_sns |= stat; dsk_sns &= ~(DSKS_PCHK|DSKS_DCHK|DSKS_EXCC); -if (dsk_sns & DSKS_PALL) dsk_sns |= DSKS_PCHK; -if (dsk_sns & DSKS_DALL) dsk_sns |= DSKS_DCHK; -if (dsk_sns & DSKS_EALL) dsk_sns |= DSKS_EXCC; +if (dsk_sns & DSKS_PALL) + dsk_sns |= DSKS_PCHK; +if (dsk_sns & DSKS_DALL) + dsk_sns |= DSKS_DCHK; +if (dsk_sns & DSKS_EALL) + dsk_sns |= DSKS_EXCC; ch9_set_end (ch, CHINT_UEND); ch_req |= REQ_CH (ch); dsk_sta = DSK_IDLE; @@ -1046,7 +1081,8 @@ dsk_stop = 0; dsk_fmt_cntr = 0; dsk_chob = 0; dsk_chob_v = 0; -for (i = 0; i < DSK_BUFSIZ; i++) dsk_buf[i] = 0; +for (i = 0; i < DSK_BUFSIZ; i++) + dsk_buf[i] = 0; for (i = 0; i <= (2 * DSK_NUMDR); i++) { uptr = dsk_dev.units + i; sim_cancel (uptr); @@ -1065,7 +1101,8 @@ t_stat r; uptr->capac = dsk_tab[dtyp].size; r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->TRK = 0; uptr->SKF = 0; uptr->flags &= ~(UNIT_INOP0|UNIT_INOP1); @@ -1080,11 +1117,13 @@ uint32 dtyp = GET_DTYPE (val); uint32 u = uptr - dsk_dev.units; UNIT *u1; -if (u & 1) return SCPE_ARG; +if (u & 1) + return SCPE_ARG; u1 = dsk_dev.units + u + 1; if ((uptr->flags & UNIT_ATT) || (u1->flags & UNIT_ATT)) return SCPE_ALATT; -if (val == TYPE_7320) u1->flags = (u1->flags & ~UNIT_DISABLE) | UNIT_DIS; +if (val == TYPE_7320) + u1->flags = (u1->flags & ~UNIT_DISABLE) | UNIT_DIS; else { u1->flags = (u1->flags & ~UNIT_TYPE) | val | UNIT_DISABLE; u1->capac = dsk_tab[dtyp].size; @@ -1107,31 +1146,38 @@ t_bool ctss; t_uint64 dbuf[DSK_BUFSIZ]; DEVICE *dptr; -if (uptr == NULL) return SCPE_IERR; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; +if (uptr == NULL) + return SCPE_IERR; +if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; dptr = find_dev_from_unit (uptr); u = uptr - dptr->units; -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dtyp = GET_DTYPE (uptr->flags); if ((dtyp == TYPE_7320) || (dtyp == TYPE_1301)) format = ctss_fmt_7320; else format = ctss_fmt_1302; for (a = 0, ctss = TRUE; a < dsk_tab[dtyp].accpm; a++) { - if (val) tlim = dsk_tab[dtyp].trkpa; + if (val) + tlim = dsk_tab[dtyp].trkpa; else tlim = 1; for (t = 0; t < tlim; t++) { da = DSK_DA (a, t, dtyp); /* get disk address */ sim_fseek (uptr->fileref, da, SEEK_SET); /* read track */ k = sim_fread (dbuf, sizeof (t_uint64), dsk_tab[dtyp].wdspt, uptr->fileref); - if (ferror (uptr->fileref)) return SCPE_IOERR; /* error? */ - for ( ; k < dsk_tab[dtyp].wdspt; k++) dbuf[k] = 0; + if (ferror (uptr->fileref)) /* error? */ + return SCPE_IOERR; + for ( ; k < dsk_tab[dtyp].wdspt; k++) + dbuf[k] = 0; rptr = T1STREC; rlnt = (uint32) dbuf[rptr + RLNT]; - if (dbuf[THA2] != CTSS_HA2) ctss = FALSE; + if (dbuf[THA2] != CTSS_HA2) + ctss = FALSE; if (rlnt == 0) { - if (a || t) fprintf (st, - "Unformatted track, unit = %d, access = %d, track = %d\n", u, a, t); + if (a || t) + fprintf (st, "Unformatted track, unit = %d, access = %d, track = %d\n", u, a, t); else fprintf (st, "Unit %d is unformatted\n", u); return SCPE_OK; } @@ -1144,29 +1190,35 @@ for (a = 0, ctss = TRUE; a < dsk_tab[dtyp].accpm; a++) { rlnt, u, a, t, rec); return SCPE_OK; } - if (rlnt > maxrsz) maxrsz = rlnt; - if (rlnt < minrsz) minrsz = rlnt; + if (rlnt > maxrsz) + maxrsz = rlnt; + if (rlnt < minrsz) + minrsz = rlnt; rptr = rlim; rlnt = (uint32) dbuf[rptr + RLNT]; } - if (format[ctptr] != 0) ctss = FALSE; - if (rec > maxrno) maxrno = rec; - if (rec < minrno) minrno = rec; + if (format[ctptr] != 0) + ctss = FALSE; + if (rec > maxrno) + maxrno = rec; + if (rec < minrno) + minrno = rec; } } -if (val == 0) return SCPE_OK; -if (ctss) fprintf (st, "CTSS format\n"); -else if ((minrno == maxrno) && (minrsz == maxrsz)) fprintf (st, - "Valid fixed format, records/track = %d, record size = %d\n", - minrno, minrsz); -else if (minrsz == maxrsz) fprintf (st, - "Valid variable format, records/track = %d-%d, record size = %d\n", - minrno, maxrno, minrsz); -else if (minrno == maxrno) fprintf (st, - "Valid variable format, records/track = %d, record sizes = %d-%d\n", - minrno, minrsz, maxrsz); -else fprintf (st, - "Valid variable format, records/track = %d-%d, record sizes = %d-%d\n", - minrno, maxrno, minrsz, maxrsz); +if (val == 0) + return SCPE_OK; +if (ctss) + fprintf (st, "CTSS format\n"); +else if ((minrno == maxrno) && (minrsz == maxrsz)) + fprintf (st, "Valid fixed format, records/track = %d, record size = %d\n", + minrno, minrsz); +else if (minrsz == maxrsz) + fprintf (st, "Valid variable format, records/track = %d-%d, record size = %d\n", + minrno, maxrno, minrsz); +else if (minrno == maxrno) + fprintf (st, "Valid variable format, records/track = %d, record sizes = %d-%d\n", + minrno, minrsz, maxrsz); +else fprintf (st, "Valid variable format, records/track = %d-%d, record sizes = %d-%d\n", + minrno, maxrno, minrsz, maxrsz); return SCPE_OK; } diff --git a/I7094/i7094_io.c b/I7094/i7094_io.c index 2bc725ba..655e7b7f 100644 --- a/I7094/i7094_io.c +++ b/I7094/i7094_io.c @@ -563,14 +563,20 @@ t_stat ch_op_ds (uint32 ch, uint32 ds, uint32 unit) { t_stat r; -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid arg? */ -if (ch_dev[ch].flags & DEV_DIS) return STOP_NXCHN; /* disabled? stop */ -if (ch_dev[ch].flags & DEV_7909) return STOP_7909; /* 7909? stop */ -if (ch_dso[ch]) return ERR_STALL; /* DS in use? */ -if (ch_ndso[ch] == CHSL_WEF) return ERR_STALL; /* NDS = WEF? */ +if (ch >= NUM_CHAN) /* invalid arg? */ + return STOP_NXCHN; +if (ch_dev[ch].flags & DEV_DIS) /* disabled? stop */ + return STOP_NXCHN; +if (ch_dev[ch].flags & DEV_7909) /* 7909? stop */ + return STOP_7909; +if (ch_dso[ch]) /* DS in use? */ + return ERR_STALL; +if (ch_ndso[ch] == CHSL_WEF) /* NDS = WEF? */ + return ERR_STALL; if (ch_sta[ch] == CHXS_IDLE) { /* chan idle? */ r = ch6_sel (ch, ds, unit, CH6S_DSW); /* select device */ - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; } ch_dso[ch] = ds; /* set command, unit */ ch_dsu[ch] = unit; @@ -593,15 +599,21 @@ t_stat ch_op_nds (uint32 ch, uint32 nds, uint32 unit) DEVICE *dptr; t_stat r; -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid arg? */ -if (ch_dev[ch].flags & DEV_DIS) return STOP_NXCHN; /* disabled? stop */ -if (ch_dev[ch].flags & DEV_7909) return STOP_7909; /* 7909? stop */ -if (ch_ndso[ch]) return ERR_STALL; /* NDS in use? */ +if (ch >= NUM_CHAN) /* invalid arg? */ + return STOP_NXCHN; +if (ch_dev[ch].flags & DEV_DIS) /* disabled? stop */ + return STOP_NXCHN; +if (ch_dev[ch].flags & DEV_7909) /* 7909? stop */ + return STOP_7909; +if (ch_ndso[ch]) /* NDS in use? */ + return ERR_STALL; if (ch_dso[ch] && (dptr = ch_find_dev (ch, ch_dsu[ch])) /* DS, cd or lpt? */ - && (dptr->flags & DEV_CDLP)) return ERR_STALL; + && (dptr->flags & DEV_CDLP)) + return ERR_STALL; if (ch_sta[ch] == CHXS_IDLE) { /* chan idle? */ r = ch6_sel (ch, nds, unit, CH6S_NDS); /* select device */ - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; } ch_ndso[ch] = nds; /* set command, unit */ ch_ndsu[ch] = unit; @@ -616,7 +628,8 @@ return SCPE_OK; t_stat ch6_end_ds (uint32 ch) { -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid arg? */ +if (ch >= NUM_CHAN) /* invalid arg? */ + return STOP_NXCHN; ch_dso[ch] = ch_dsu[ch] = 0; /* no data select */ if (ch_ndso[ch]) { /* stacked non-data sel? */ sim_activate (ch_dev[ch].units, 0); /* immediate poll */ @@ -633,7 +646,8 @@ return SCPE_OK; t_stat ch6_end_nds (uint32 ch) { -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid arg? */ +if (ch >= NUM_CHAN) /* invalid arg? */ + return STOP_NXCHN; ch_ndso[ch] = ch_ndsu[ch] = 0; /* no non-data select */ if (ch_dso[ch]) { /* stacked data sel? */ sim_activate (ch_dev[ch].units, 0); /* immediate poll */ @@ -651,12 +665,15 @@ DEVICE *dptr; DIB *dibp; t_stat r; -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid arg? */ +if (ch >= NUM_CHAN) /* invalid arg? */ + return STOP_NXCHN; dptr = ch_find_dev (ch, unit); /* find device */ -if (dptr == NULL) return STOP_NXDEV; /* invalid device? */ +if (dptr == NULL) /* invalid device? */ + return STOP_NXDEV; dibp = (DIB *) dptr->ctxt; r = dibp->chsel (ch, sel, unit); /* select device */ -if (r == SCPE_OK) ch_sta[ch] = sta; /* set status */ +if (r == SCPE_OK) /* set status */ + ch_sta[ch] = sta; return r; } @@ -667,7 +684,8 @@ t_stat ch6_svc (UNIT *uptr) uint32 ch = uptr - &ch_unit[0]; /* get channel */ t_stat r; -if (ch >= NUM_CHAN) return SCPE_IERR; /* invalid chan? */ +if (ch >= NUM_CHAN) /* invalid chan? */ + return SCPE_IERR; switch (ch_sta[ch]) { /* case on state */ case CH6S_PDS: /* polling for ds */ @@ -693,16 +711,22 @@ return r; DEVICE *ch_find_dev (uint32 ch, uint32 unit) { -if (ch >= NUM_CHAN) return NULL; /* invalid arg? */ -if (ch_dev[ch].flags & (DEV_7909|DEV_7289)) return ch2dev[ch]; +if (ch >= NUM_CHAN) /* invalid arg? */ + return NULL; +if (ch_dev[ch].flags & (DEV_7909|DEV_7289)) + return ch2dev[ch]; unit = unit & 0777; if (((unit >= U_MTBCD) && (unit <= (U_MTBCD + MT_NUMDR))) || ((unit >= U_MTBIN) && (unit <= (U_MTBIN + MT_NUMDR)))) return ch2dev[ch]; -if (ch != 0) return NULL; -if (unit == U_CDR) return &cdr_dev; -if (unit == U_CDP) return &cdp_dev; -if ((unit == U_LPBCD) || (unit == U_LPBIN)) return &lpt_dev; +if (ch != 0) + return NULL; +if (unit == U_CDR) + return &cdr_dev; +if (unit == U_CDP) + return &cdp_dev; +if ((unit == U_LPBCD) || (unit == U_LPBIN)) + return &lpt_dev; return NULL; } @@ -717,17 +741,21 @@ t_uint64 ir; t_stat r; clc = clc | data_base; /* add A/B select */ -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid argument? */ -if (ch_dev[ch].flags & DEV_DIS) return STOP_NXCHN; /* disabled? stop */ +if (ch >= NUM_CHAN) /* invalid argument? */ + return STOP_NXCHN; +if (ch_dev[ch].flags & DEV_DIS) /* disabled? stop */ + return STOP_NXCHN; if (ch_dev[ch].flags & DEV_7909) { /* 7909? */ - if (ch_sta[ch] != CHXS_IDLE) return ERR_STALL; /* must be idle */ + if (ch_sta[ch] != CHXS_IDLE) /* must be idle */ + return ERR_STALL; if (reset) { /* RDCx? */ ch_cnd[ch] = 0; /* clear conditions */ ch_clc[ch] = clc; /* set clc */ } else { /* SDCx */ if (BIT_TST (chtr_enab, CHTR_V_TWT + ch) && /* pending trap? */ - (ch_flags[ch] & CHF_TWT)) return ERR_STALL; + (ch_flags[ch] & CHF_TWT)) + return ERR_STALL; ch_clc[ch] = ch_ca[ch] & CHAMASK; /* finish WTR, TWT */ } ch_flags[ch] &= ~CHF_CLR_7909; /* clear flags, not IP */ @@ -737,7 +765,8 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909? */ } /* 7607, 7289 */ if (reset) { /* reset? */ - if (ch_sta[ch] == CHXS_DSX) ch_sta[ch] = CH6S_DSW; + if (ch_sta[ch] == CHXS_DSX) + ch_sta[ch] = CH6S_DSW; ch_flags[ch] &= ~(CHF_LDW|CHF_EOR|CHF_TRC|CHF_CMD); ch_idf[ch] = 0; } @@ -764,7 +793,8 @@ switch (ch_sta[ch]) { /* case on chan state */ if (ch_dev[ch].flags & DEV_7289) { /* drum channel? */ ir = ReadP (clc); /* read addr */ ch_clc[ch] = CHAINC (clc); /* incr chan pc */ - if (r = ch9_wr (ch, ir, 0)) return r; /* write to dev */ + if (r = ch9_wr (ch, ir, 0)) /* write to dev */ + return r; } else ch_clc[ch] = clc; /* set clc */ return ch6_new_cmd (ch, TRUE); /* start channel */ @@ -784,7 +814,8 @@ return SCPE_OK; t_stat ch_op_store (uint32 ch, t_uint64 *dat) { -if ((ch >= NUM_CHAN) || (ch_dev[ch].flags & DEV_DIS)) return STOP_NXCHN; +if ((ch >= NUM_CHAN) || (ch_dev[ch].flags & DEV_DIS)) + return STOP_NXCHN; if (ch_dev[ch].flags & DEV_7909) *dat = (((t_uint64) ch_ca[ch] & CHAMASK) << INST_V_DEC) | (((t_uint64) ch_clc[ch] & CHAMASK) << INST_V_ADDR); @@ -803,11 +834,13 @@ return SCPE_OK; t_stat ch_op_store_diag (uint32 ch, t_uint64 *dat) { -if ((ch >= NUM_CHAN) || (ch_dev[ch].flags & DEV_DIS)) return STOP_NXCHN; -if (ch_flags[ch] & DEV_7289) *dat = ind_ioc? SIGN: 0; -else if (ch_flags[ch] & DEV_7909) *dat = - (((t_uint64) (ch_lcc[ch] & CHF_M_LCC)) << CHF_V_LCC) | - (ch_flags[ch] & CHF_SDC_7909); +if ((ch >= NUM_CHAN) || (ch_dev[ch].flags & DEV_DIS)) + return STOP_NXCHN; +if (ch_flags[ch] & DEV_7289) + *dat = ind_ioc? SIGN: 0; +else if (ch_flags[ch] & DEV_7909) + *dat = (((t_uint64) (ch_lcc[ch] & CHF_M_LCC)) << CHF_V_LCC) | + (ch_flags[ch] & CHF_SDC_7909); else *dat = 0; return SCPE_OK; } @@ -821,18 +854,23 @@ t_stat ch_op_reset (uint32 ch, t_bool ch7909) { DEVICE *dptr; -if (ch >= NUM_CHAN) return STOP_NXCHN; /* invalid argument? */ -if (ch_dev[ch].flags & DEV_DIS) return SCPE_OK; /* disabled? ok */ +if (ch >= NUM_CHAN) /* invalid argument? */ + return STOP_NXCHN; +if (ch_dev[ch].flags & DEV_DIS) /* disabled? ok */ + return SCPE_OK; if (ch_dev[ch].flags & DEV_7909) { /* 7909? */ - if (!ch7909) return SCPE_OK; /* wrong reset is NOP */ + if (!ch7909) /* wrong reset is NOP */ + return SCPE_OK; dptr = ch2dev[ch]; /* get device */ } else { /* 7607, 7289 */ - if (ch7909) return STOP_NT7909; /* wrong reset is err */ + if (ch7909) /* wrong reset is err */ + return STOP_NT7909; dptr = ch_find_dev (ch, ch_ndsu[ch]); /* find device */ } ch_reset (&ch_dev[ch]); /* reset channel */ -if (dptr && dptr->reset) dptr->reset (dptr); /* reset device */ +if (dptr && dptr->reset) /* reset device */ + dptr->reset (dptr); return SCPE_OK; } @@ -847,9 +885,11 @@ t_stat ch_proc (uint32 ch) { t_stat r; -if (ch >= NUM_CHAN) return SCPE_IERR; /* bad channel? */ +if (ch >= NUM_CHAN) /* bad channel? */ + return SCPE_IERR; ch_req &= ~REQ_CH (ch); /* clear request */ -if (ch_dev[ch].flags & DEV_DIS) return SCPE_IERR; /* disabled? */ +if (ch_dev[ch].flags & DEV_DIS) /* disabled? */ + return SCPE_IERR; if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ t_uint64 sr; @@ -889,15 +929,18 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ case CH9_TCM: /* transfer on cond */ csel = CH9D_COND (ch_wc[ch]); mask = CH9D_MASK (ch_wc[ch]); - if (csel == 7) xfr = (mask == 0); /* C = 7? mask mbz */ + if (csel == 7) /* C = 7? mask mbz */ + xfr = (mask == 0); else { /* C = 0..6 */ - if (csel == 0) tval = ch_cnd[ch]; /* C = 0? test cond */ + if (csel == 0) /* C = 0? test cond */ + tval = ch_cnd[ch]; else tval = (uint32) (ch_ar[ch] >> (6 * (6 - csel))) & 077; if (ch_wc[ch] & CH9D_B11) xfr = ((tval & mask) == mask); else xfr = (tval == mask); } - if (xfr) ch_clc[ch] = ch_ca[ch] & CHAMASK; /* change CLC */ + if (xfr) /* change CLC */ + ch_clc[ch] = ch_ca[ch] & CHAMASK; break; case CH9_LIP: /* leave interrupt */ @@ -945,7 +988,8 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ break; case CH9_XMT: /* transmit */ - if (ch_wc[ch] == 0) break; + if (ch_wc[ch] == 0) + break; sr = ReadP (ch_clc[ch]); /* next word */ WriteP (ch_ca[ch], sr); ch_clc[ch] = CHAINC (ch_clc[ch]); /* incr pointers */ @@ -955,7 +999,8 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ return SCPE_OK; case CH9_SNS: /* sense */ - if (r = ch9_sel (ch, CHSL_SNS)) return r; /* send sense to dev */ + if (r = ch9_sel (ch, CHSL_SNS)) /* send sense to dev */ + return r; ch_flags[ch] |= CHF_PRD; /* prepare to read */ break; /* next command */ @@ -970,12 +1015,14 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ } ch_flags[ch] &= ~CHF_EOR; /* clear end */ if (ch_op[ch] == CH9_CTLR) { /* CTLR? */ - if (r = ch9_sel (ch, CHSL_RDS)) return r; /* send read sel */ + if (r = ch9_sel (ch, CHSL_RDS)) /* send read sel */ + return r; ch_flags[ch] |= CHF_PRD; /* prep to read */ ch_idf[ch] = 0; } else if (ch_op[ch] == CH9_CTLW) { /* CTLW? */ - if (r = ch9_sel (ch, CHSL_WRS)) return r; /* end write sel */ + if (r = ch9_sel (ch, CHSL_WRS)) /* end write sel */ + return r; ch_flags[ch] |= CHF_PWR; /* prep to write */ } break; @@ -984,7 +1031,8 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ if ((ch_wc[ch] == 0) || (ch_flags[ch] & CHF_EOR)) { /* wc == 0 or EOR? */ if (ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS)) { ch_flags[ch] &= ~(CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS); - if (r = ch9_wr (ch, 0, CH9DF_STOP)) return r; /* send stop */ + if (r = ch9_wr (ch, 0, CH9DF_STOP)) /* send stop */ + return r; } if (ch_flags[ch] & CHF_EOR) { /* EOR? */ ch_flags[ch] &= ~CHF_EOR; /* clear flag */ @@ -997,13 +1045,16 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ return ch9_wr_getw (ch); /* no, write */ case CH9_CPYP: /* anything to do? */ - if (ch_wc[ch] == 0) break; /* (new, wc = 0) next */ + if (ch_wc[ch] == 0) /* (new, wc = 0) next */ + break; if (ch_flags[ch] & CHF_EOR) /* end? */ ch_flags[ch] &= ~CHF_EOR; /* ignore */ else if (ch_flags[ch] & CHF_RDS) /* read? */ ch9_rd_putw (ch); - else if (r = ch9_wr_getw (ch)) return r; /* no, write */ - if (ch_wc[ch] == 0) break; /* done? get next */ + else if (r = ch9_wr_getw (ch)) /* no, write */ + return r; + if (ch_wc[ch] == 0) /* done? get next */ + break; return SCPE_OK; /* more to do */ default: @@ -1015,7 +1066,8 @@ if (ch_dev[ch].flags & DEV_7909) { /* 7909 */ else if (ch_flags[ch] & CHF_RDS) { /* 7607 read? */ - if (ch_sta[ch] != CHXS_DSX) return ch6_end_ds (ch); /* chan exec? no, disc */ + if (ch_sta[ch] != CHXS_DSX) /* chan exec? no, disc */ + return ch6_end_ds (ch); switch (ch_op[ch] & CH6_OPMASK) { /* switch on op */ case CH6_TCH: /* transfer */ @@ -1024,19 +1076,22 @@ else if (ch_flags[ch] & CHF_RDS) { /* 7607 read? */ case CH6_IOCD: /* IOCD */ if (ch_wc[ch]) { /* wc > 0? */ - if (ch6_rd_putw (ch)) return SCPE_OK; /* store; more? cont */ + if (ch6_rd_putw (ch)) /* store; more? cont */ + return SCPE_OK; } return ch6_end_ds (ch); /* no, disconnect */ case CH6_IOCP: /* IOCP */ if (ch_wc[ch]) { /* wc > 0? */ - if (ch6_rd_putw (ch)) return SCPE_OK; /* store; more? cont */ + if (ch6_rd_putw (ch)) /* store; more? cont */ + return SCPE_OK; } return ch6_new_cmd (ch, FALSE); /* unpack new cmd */ case CH6_IOCT: /* IOCT */ if (ch_wc[ch]) { /* wc > 0? */ - if (ch6_rd_putw (ch)) return SCPE_OK; /* store; more? cont */ + if (ch6_rd_putw (ch)) /* store; more? cont */ + return SCPE_OK; } return ch6_ioxt (ch); /* unstall or disc */ @@ -1095,7 +1150,8 @@ else if (ch_flags[ch] & CHF_RDS) { /* 7607 read? */ else { /* 7607 write */ - if (ch_sta[ch] != CHXS_DSX) return ch6_end_ds (ch); /* chan exec? no, disc */ + if (ch_sta[ch] != CHXS_DSX) /* chan exec? no, disc */ + return ch6_end_ds (ch); switch (ch_op[ch] & CH6_OPMASK) { /* switch on op */ case CH6_TCH: /* transfer */ @@ -1104,39 +1160,49 @@ else { /* 7607 write */ case CH6_IOCD: /* IOCD */ if (ch_wc[ch]) { /* wc > 0? */ - if (r = ch6_wr_getw (ch, TRUE)) return r; /* send wd to dev; err? */ - if (ch_wc[ch]) return SCPE_OK; /* more to do? */ + if (r = ch6_wr_getw (ch, TRUE)) /* send wd to dev; err? */ + return r; + if (ch_wc[ch]) /* more to do? */ + return SCPE_OK; } return ch6_end_ds (ch); /* disconnect */ case CH6_IOCP: /* IOCP */ case CH6_IOSP: /* IOSP */ if (ch_wc[ch]) { /* wc > 0? */ - if (r = ch6_wr_getw (ch, FALSE)) return r; /* send wd to dev; err? */ - if (ch_wc[ch]) return SCPE_OK; /* more to do? */ + if (r = ch6_wr_getw (ch, FALSE)) /* send wd to dev; err? */ + return r; + if (ch_wc[ch]) /* more to do? */ + return SCPE_OK; } return ch6_new_cmd (ch, FALSE); /* get next cmd */ case CH6_IOCT: /* IOCT */ case CH6_IOST: /* IOST */ if (ch_wc[ch]) { /* wc > 0? */ - if (r = ch6_wr_getw (ch, FALSE)) return r; /* send wd to dev; err? */ - if (ch_wc[ch]) return SCPE_OK; /* more to do? */ + if (r = ch6_wr_getw (ch, FALSE)) /* send wd to dev; err? */ + return r; + if (ch_wc[ch]) /* more to do? */ + return SCPE_OK; } return ch6_ioxt (ch); /* get next cmd */ case CH6_IORP: /* IORP */ if (!(ch_flags[ch] & CHF_EOR) && ch_wc[ch]) { /* not EOR? (cdp, lpt) */ - if (r = ch6_wr_getw (ch, TRUE)) return r; /* send wd to dev; err? */ - if (ch_wc[ch]) return SCPE_OK; /* more to do? */ + if (r = ch6_wr_getw (ch, TRUE)) /* send wd to dev; err? */ + return r; + if (ch_wc[ch]) /* more to do? */ + return SCPE_OK; } ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear EOR */ return ch6_new_cmd (ch, FALSE); /* get next cmd */ case CH6_IORT: /* IORT */ if (!(ch_flags[ch] & CHF_EOR) && ch_wc[ch]) { /* not EOR? (cdp, lpt) */ - if (r = ch6_wr_getw (ch, TRUE)) return r; /* send wd to dev; err? */ - if (ch_wc[ch]) return SCPE_OK; /* more to do? */ + if (r = ch6_wr_getw (ch, TRUE)) /* send wd to dev; err? */ + return r; + if (ch_wc[ch]) /* more to do? */ + return SCPE_OK; } ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear EOR */ return ch6_ioxt (ch); /* unstall or disc */ @@ -1153,7 +1219,8 @@ else { /* 7607 write */ t_bool ch6_rd_putw (uint32 ch) { -if (ch_idf[ch] & CH6DF_EOR) ch_flags[ch] |= CHF_EOR; /* eor from dev? */ +if (ch_idf[ch] & CH6DF_EOR) /* eor from dev? */ + ch_flags[ch] |= CHF_EOR; else ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* set/clr chan eor */ ch_idf[ch] = 0; /* clear eor, valid */ if (ch_wc[ch]) { /* wc > 0? */ @@ -1181,7 +1248,8 @@ if (ch_wc[ch]) { ch_wc[ch] = ch_wc[ch] - 1; } else ch_ar[ch] = 0; -if (eorz && (ch_wc[ch] == 0)) eorfl = 1; /* eor on wc = 0? */ +if (eorz && (ch_wc[ch] == 0)) /* eor on wc = 0? */ + eorfl = 1; else eorfl = 0; dptr = ch_find_dev (ch, ch_dsu[ch]); /* find device */ if (dptr && /* valid device? */ @@ -1217,13 +1285,15 @@ if ((ir & CHI_IND) && (ch_wc[ch] || /* indirect? */ t_uint64 sr = ReadP (ch_ca[ch] & AMASK); /* read indirect */ ch_ca[ch] = ((uint32) sr) & ((cpu_model & I_CT)? PAMASK: AMASK); } -if (hst_ch) cpu_ent_hist (ch_clc[ch] | ((ch + 1) << HIST_V_CH), ch_ca[ch], ir, 0); +if (hst_ch) + cpu_ent_hist (ch_clc[ch] | ((ch + 1) << HIST_V_CH), ch_ca[ch], ir, 0); ch_clc[ch] = (ch_clc[ch] + 1) & AMASK; /* incr chan pc */ switch (op) { /* case on opcode */ case CH6_IOCD: /* IOCD */ - if (ch_wc[ch] == 0) ch6_end_ds (ch); /* wc 0? end now */ + if (ch_wc[ch] == 0) /* wc 0? end now */ + ch6_end_ds (ch); break; case CH6_IOST: /* IOST */ @@ -1231,7 +1301,8 @@ switch (op) { /* case on opcode */ ch_req |= REQ_CH (ch); case CH6_IOCT: /* IOCT */ if (ch_wc[ch] == 0) { /* wc 0? */ - if (ch_ld) ch6_end_ds (ch); /* load? end now */ + if (ch_ld) /* load? end now */ + ch6_end_ds (ch); else ch_req |= REQ_CH (ch); /* else immed ch req */ } break; @@ -1240,7 +1311,8 @@ switch (op) { /* case on opcode */ if (ch_flags[ch] & CHF_EOR) /* EOR set? immed ch req */ ch_req |= REQ_CH (ch); case CH6_IOCP: /* IOCP */ - if (ch_wc[ch] == 0) ch_req |= REQ_CH (ch); /* wc 0? immed ch req */ + if (ch_wc[ch] == 0) /* wc 0? immed ch req */ + ch_req |= REQ_CH (ch); break; case CH6_IORT: /* IORT */ @@ -1286,13 +1358,16 @@ uint32 i, op; if (ch_wc[ch] == 0) { /* wc = 0? */ uint32 ccnt = 5; /* allow 5 for CPU */ for (i = 0; i < NUM_CHAN; i++) { /* test channels */ - if (ch_sta[ch] != CHXS_DSX) continue; /* idle? skip */ + if (ch_sta[ch] != CHXS_DSX) /* idle? skip */ + continue; op = ch_op[ch] & ~1; /* get op */ ccnt++; /* 1 per active ch */ if ((op == CH6_IOCP) || (op == CH6_IORP) || /* 1 per proceed */ - (op == CH6_IOSP)) ccnt++; + (op == CH6_IOSP)) + ccnt++; } - if (ccnt <= 11) return; /* <= 11? ok */ + if (ccnt <= 11) /* <= 11? ok */ + return; } ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear eor */ return; @@ -1305,9 +1380,11 @@ return; t_stat ch6_req_rd (uint32 ch, uint32 unit, t_uint64 val, uint32 fl) { if (ch6_qconn (ch, unit)) { /* ch conn to caller? */ - if (ch_idf[ch] & CH6DF_VLD) ind_ioc = 1; /* overrun? */ + if (ch_idf[ch] & CH6DF_VLD) /* overrun? */ + ind_ioc = 1; ch_idf[ch] = CH6DF_VLD; /* set ar valid */ - if (fl) ch_idf[ch] |= CH6DF_EOR; /* set eor if requested */ + if (fl) /* set eor if requested */ + ch_idf[ch] |= CH6DF_EOR; ch_req |= REQ_CH (ch); /* request chan */ ch_flags[ch] |= CHF_RDS; ch_ar[ch] = val & DMASK; /* save data */ @@ -1353,7 +1430,8 @@ return 0; t_bool ch6_qconn (uint32 ch, uint32 unit) { if ((ch < NUM_CHAN) && /* valid chan */ - (ch_dsu[ch] == unit)) return TRUE; /* for right unit? */ + (ch_dsu[ch] == unit)) /* for right unit? */ + return TRUE; return FALSE; } @@ -1392,9 +1470,11 @@ t_stat ch9_sel (uint32 ch, uint32 sel) DEVICE *dptr = ch2dev[ch]; DIB *dibp; -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp && dibp->chsel) return dibp->chsel (ch, sel, 0); +if (dibp && dibp->chsel) + return dibp->chsel (ch, sel, 0); return SCPE_IERR; } @@ -1405,9 +1485,11 @@ t_stat ch9_wr (uint32 ch, t_uint64 dat, uint32 fl) DEVICE *dptr = ch2dev[ch]; DIB *dibp; -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp && dibp->write) return dibp->write (ch, dat, fl); +if (dibp && dibp->write) + return dibp->write (ch, dat, fl); return SCPE_IERR; } @@ -1470,7 +1552,8 @@ switch (ch_op[ch]) { /* check initial cond */ if (ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS)) ch9_eval_int (ch, CHINT_SEQC); /* not during data */ ch_flags[ch] &= ~CHF_EOR; - if (ch_wc[ch] & CH9D_NST) ch_req |= REQ_CH (ch); /* N set? proc in chan */ + if (ch_wc[ch] & CH9D_NST) /* N set? proc in chan */ + ch_req |= REQ_CH (ch); else return ch9_sel (ch, CHSL_CTL); /* sel, dev sets ch_req! */ break; @@ -1485,8 +1568,10 @@ switch (ch_op[ch]) { /* check initial cond */ case CH9_CPYP: if ((ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS)) == 0) ch9_eval_int (ch, CHINT_SEQC); /* not unless data */ - if (ch_flags[ch] & CHF_PRD) ch_flags[ch] |= CHF_RDS; - else if (ch_flags[ch] & CHF_PWR) ch_flags[ch] |= CHF_WRS; + if (ch_flags[ch] & CHF_PRD) + ch_flags[ch] |= CHF_RDS; + else if (ch_flags[ch] & CHF_PWR) + ch_flags[ch] |= CHF_WRS; ch_flags[ch] &= ~(CHF_EOR|CHF_PRD|CHF_PWR); if ((ch_op[ch] == CH9_CPYP) && (ch_wc[ch] == 0)) ch_req |= REQ_CH (ch); /* CPYP x,,0? */ @@ -1515,7 +1600,8 @@ return SCPE_OK; t_stat ch9_req_rd (uint32 ch, t_uint64 val) { if (ch < NUM_CHAN) { /* valid chan? */ - if (ch_idf[ch] & CH9DF_VLD) ch9_set_ioc (ch); /* prev still valid? io chk */ + if (ch_idf[ch] & CH9DF_VLD) /* prev still valid? io chk */ + ch9_set_ioc (ch); ch_idf[ch] = CH9DF_VLD; /* set ar valid */ ch_req |= REQ_CH (ch); /* request chan */ ch_ar[ch] = val & DMASK; /* save data */ @@ -1527,7 +1613,8 @@ return SCPE_OK; void ch9_set_atn (uint32 ch) { -if (ch < NUM_CHAN) ch9_eval_int (ch, CHINT_ATN1); +if (ch < NUM_CHAN) + ch9_eval_int (ch, CHINT_ATN1); return; } @@ -1557,7 +1644,8 @@ return; t_bool ch9_qconn (uint32 ch) { -if ((ch < NUM_CHAN) && (ch_sta[ch] == CHXS_DSX)) return TRUE; +if ((ch < NUM_CHAN) && (ch_sta[ch] == CHXS_DSX)) + return TRUE; return FALSE; } @@ -1600,7 +1688,8 @@ t_bool ch_qidle (void) uint32 i; for (i = 0; i < NUM_CHAN; i++) { - if (ch_sta[i] != CHXS_IDLE) return FALSE; + if (ch_sta[i] != CHXS_IDLE) + return FALSE; } return TRUE; } @@ -1645,7 +1734,8 @@ if (!chtr_inht && !chtr_inhi && chtr_enab) { } /* end if BIT_TST */ } /* end for */ } /* end if !chtr_inht */ -if (decr) *decr = 0; +if (decr) + *decr = 0; return 0; } @@ -1655,7 +1745,8 @@ t_stat ch_reset (DEVICE *dptr) { uint32 ch = dptr - &ch_dev[0]; /* get channel */ -if (ch == CH_A) ch2dev[ch] = &mt_dev[0]; /* channel A fixed */ +if (ch == CH_A) /* channel A fixed */ + ch2dev[ch] = &mt_dev[0]; ch_sta[ch] = 0; ch_flags[ch] = 0; ch_idf[ch] = 0; @@ -1682,9 +1773,12 @@ t_stat ch_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -if (dptr->flags & DEV_7909) fputs ("7909", st); -else if (dptr->flags & DEV_7289) fputs ("7289", st); +if (dptr == NULL) + return SCPE_IERR; +if (dptr->flags & DEV_7909) + fputs ("7909", st); +else if (dptr->flags & DEV_7289) + fputs ("7289", st); else fputs ("7607", st); return SCPE_OK; } @@ -1698,15 +1792,19 @@ char gbuf[CBUFSIZE]; uint32 i, ch; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; ch = dptr - &ch_dev[0]; -if ((ch == 0) || !(dptr->flags & DEV_DIS)) return SCPE_ARG; -if (cptr == NULL) cptr = "TAPE"; +if ((ch == 0) || !(dptr->flags & DEV_DIS)) + return SCPE_ARG; +if (cptr == NULL) + cptr = "TAPE"; get_glyph (cptr, gbuf, 0); for (i = 0; dev_table[i].name; i++) { if (strcmp (dev_table[i].name, gbuf) == 0) { dptr1 = ch_map_flags (ch, dev_table[i].flags); - if (!dptr1 || !(dptr1->flags & DEV_DIS)) return SCPE_ARG; + if (!dptr1 || !(dptr1->flags & DEV_DIS)) + return SCPE_ARG; dptr->flags &= ~(DEV_DIS|DEV_7909|DEV_7289|DEV_7750|DEV_7631); dptr->flags |= dev_table[i].flags; dptr1->flags &= ~DEV_DIS; @@ -1721,10 +1819,14 @@ return SCPE_ARG; DEVICE *ch_map_flags (uint32 ch, int32 fl) { -if (fl & DEV_7289) return &drm_dev; -if (!(fl & DEV_7909)) return &mt_dev[ch]; -if (fl & DEV_7631) return &dsk_dev; -if (fl & DEV_7750) return &com_dev; +if (fl & DEV_7289) + return &drm_dev; +if (!(fl & DEV_7909)) + return &mt_dev[ch]; +if (fl & DEV_7631) + return &dsk_dev; +if (fl & DEV_7750) + return &com_dev; return NULL; } @@ -1735,7 +1837,8 @@ void ch_set_map (void) uint32 i; for (i = 0; i < NUM_CHAN; i++) { - if (ch_dev[i].flags & DEV_DIS) ch2dev[i] = NULL; + if (ch_dev[i].flags & DEV_DIS) + ch2dev[i] = NULL; else ch2dev[i] = ch_map_flags (i, ch_dev[i].flags); } return; @@ -1750,15 +1853,19 @@ UNIT *uptr1; uint32 i, ch; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; ch = dptr - &ch_dev[0]; -if ((ch == 0) || (dptr->flags & DEV_DIS) || (cptr != NULL)) return SCPE_ARG; +if ((ch == 0) || (dptr->flags & DEV_DIS) || (cptr != NULL)) + return SCPE_ARG; dptr1 = ch2dev[ch]; -if (dptr1 == NULL) return SCPE_IERR; +if (dptr1 == NULL) + return SCPE_IERR; if (dptr1->units) { for (i = 0; i < dptr1->numunits; i++) { uptr1 = dptr1->units + i; - if (dptr1->detach) dptr1->detach (uptr1); + if (dptr1->detach) + dptr1->detach (uptr1); else detach_unit (uptr1); } } diff --git a/I7094/i7094_lp.c b/I7094/i7094_lp.c index f8b7c0c9..9f7f8ef2 100644 --- a/I7094/i7094_lp.c +++ b/I7094/i7094_lp.c @@ -1,6 +1,6 @@ /* i7094_lp.c: IBM 716 line printer simulator - Copyright (c) 2003-2007, Robert M. Supnik + Copyright (c) 2003-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -185,7 +185,8 @@ DEVICE lpt_dev = { t_stat lpt_chsel (uint32 ch, uint32 sel, uint32 unit) { -if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */ +if (sel & CHSL_NDS) /* nds? nop */ + return ch6_end_nds (ch); switch (sel) { /* case on cmd */ @@ -219,7 +220,8 @@ uint32 u = (lpt_cmd & CMD_BIN)? U_LPBIN: U_LPBCD; /* reconstruct unit */ lpt_chob = val & DMASK; /* store data */ lpt_chob_v = 1; /* set valid */ -if (lpt_sta == ECS_DATA) return SCPE_OK; +if (lpt_sta == ECS_DATA) + return SCPE_OK; if (lpt_sta == LPS_DATA) { lpt_bbuf[lpt_bptr++] = lpt_chob; /* store data */ if (eorfl || /* end record, or */ @@ -248,9 +250,11 @@ switch (lpt_sta) { /* case on state */ lpt_bbuf[i] = 0; for (i = 0; i < LPT_ECHLNT; i++) /* clear echo buffer */ lpt_ebuf[i] = 0; - if (lpt_cmd & CMD_BIN) lpt_bptr = LPB_1ROW; /* set buffer ptr */ + if (lpt_cmd & CMD_BIN) /* set buffer ptr */ + lpt_bptr = LPB_1ROW; else lpt_bptr = LPB_9ROW; - if (lpt_cmd & CMD_ECHO) lpt_sta = ECS_DATA; /* set data state */ + if (lpt_cmd & CMD_ECHO) /* set data state */ + lpt_sta = ECS_DATA; else lpt_sta = LPS_DATA; ch6_req_wr (CH_A, u); /* request channel */ lpt_chob = 0; /* clr, inval buffer */ @@ -261,7 +265,8 @@ switch (lpt_sta) { /* case on state */ case LPS_DATA: /* print data state */ if (!ch6_qconn (CH_A, u)) /* disconnect? */ return lpt_end_line (uptr); /* line is done */ - if (lpt_chob_v) lpt_chob_v = 0; /* valid? clear */ + if (lpt_chob_v) /* valid? clear */ + lpt_chob_v = 0; else ind_ioc = 1; /* no, io check */ ch6_req_wr (CH_A, u); /* request chan again */ sim_activate (uptr, (lpt_bptr & 1)? lpt_tleft: lpt_tright); @@ -284,7 +289,8 @@ switch (lpt_sta) { /* case on state */ sim_activate (uptr, lpt_tleft); /* short timer */ } else { /* print cycle */ - if (lpt_chob_v) lpt_chob_v = 0; /* valid? clear */ + if (lpt_chob_v) /* valid? clear */ + lpt_chob_v = 0; else ind_ioc = 1; /* no, io check */ lpt_bbuf[map] = lpt_chob; /* store in buffer */ sim_activate (uptr, (lpt_bptr & 1)? lpt_tleft: lpt_tright); @@ -320,7 +326,8 @@ for (col = 0; col < 72; col++) { /* proc 72 columns */ dat = bit_masks[35 - (col % 36)]; /* mask for column */ for (row = 0; row < 12; row++) { /* proc 12 rows */ bufw = (row * 2) + (col / 36); /* index to buffer */ - if (lpt_bbuf[bufw] & dat) colbin |= col_masks[row]; + if (lpt_bbuf[bufw] & dat) + colbin |= col_masks[row]; } bcd = colbin_to_bcd (colbin); /* column bin -> BCD */ lpt_cbuf[col] = pch[bcd]; /* -> ASCII */ @@ -339,7 +346,8 @@ if (uptr->flags & UNIT_ATT) { /* file? */ } } else if (uptr->flags & UNIT_CONS) { /* print to console? */ - for (i = 0; lpt_cbuf[i] != 0; i++) sim_putchar (lpt_cbuf[i]); + for (i = 0; lpt_cbuf[i] != 0; i++) + sim_putchar (lpt_cbuf[i]); sim_putchar ('\r'); sim_putchar ('\n'); } @@ -356,8 +364,10 @@ t_stat lpt_reset (DEVICE *dptr) { uint32 i; -for (i = 0; i < LPT_BINLNT; i++) lpt_bbuf[i] = 0; /* clear bin buf */ -for (i = 0; i < LPT_ECHLNT; i++) lpt_ebuf[i] = 0; /* clear echo buf */ +for (i = 0; i < LPT_BINLNT; i++) /* clear bin buf */ + lpt_bbuf[i] = 0; +for (i = 0; i < LPT_ECHLNT; i++) /* clear echo buf */ + lpt_ebuf[i] = 0; lpt_sta = 0; /* clear state */ lpt_cmd = 0; /* clear modes */ lpt_bptr = 0; /* clear buf ptr */ diff --git a/I7094/i7094_mt.c b/I7094/i7094_mt.c index 6c0d2ce8..6c8f9cf4 100644 --- a/I7094/i7094_mt.c +++ b/I7094/i7094_mt.c @@ -1,6 +1,6 @@ /* i7094_mt.c: IBM 7094 magnetic tape simulator - Copyright (c) 2003-2006, Robert M Supnik + Copyright (c) 2003-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -447,14 +447,18 @@ uint32 u = unit & 017; if ((ch >= NUM_CHAN) || (cmd == 0) || (cmd >= CHSL_NUM)) return SCPE_IERR; /* invalid arg? */ -if (mt_dev[ch].flags & DEV_DIS) return STOP_NXDEV; /* disabled? */ -if ((u == 0) || (u > MT_NUMDR)) return STOP_NXDEV; /* valid unit? */ +if (mt_dev[ch].flags & DEV_DIS) /* disabled? */ + return STOP_NXDEV; +if ((u == 0) || (u > MT_NUMDR)) /* valid unit? */ + return STOP_NXDEV; uptr = mt_dev[ch].units + u; /* get unit ptr */ -if (uptr->flags & UNIT_DIS) return STOP_NXDEV; /* disabled? */ +if (uptr->flags & UNIT_DIS) /* disabled? */ + return STOP_NXDEV; if (mt_unit[ch] || sim_is_active (uptr)) /* ctrl or unit busy? */ return ERR_STALL; /* stall */ if (QCHRONO (ch, u)) { /* Chronolog clock? */ - if (cmd != CHSL_RDS) return STOP_ILLIOP; /* only reads */ + if (cmd != CHSL_RDS) /* only reads */ + return STOP_ILLIOP; sim_activate (uptr, mt_tword); /* responds quickly */ } else { /* real tape */ @@ -462,8 +466,9 @@ else { /* real tape */ return SCPE_UNATT; if (sim_tape_wrp (uptr) && mt_will_wrt[cmd]) /* unit wrp && write? */ return STOP_WRP; - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d %s, pos = %d\n", mt_dev[ch].name, u, sel_name[cmd], uptr->pos); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d %s, pos = %d\n", + mt_dev[ch].name, u, sel_name[cmd], uptr->pos); switch (cmd) { /* case on cmd */ @@ -504,10 +509,12 @@ int32 k, u; uint8 by, *xb; UNIT *uptr; -if (ch >= NUM_CHAN) return SCPE_IERR; /* invalid chan? */ +if (ch >= NUM_CHAN) /* invalid chan? */ + return SCPE_IERR; xb = mtxb[ch]; /* get xfer buf */ u = mt_unit[ch] & 017; -if ((xb == NULL) || (u > MT_NUMDR)) return SCPE_IERR; /* invalid args? */ +if ((xb == NULL) || (u > MT_NUMDR)) /* invalid args? */ + return SCPE_IERR; uptr = mt_dev[ch].units + u; /* get unit */ mt_chob[ch] = val & DMASK; /* save word from chan */ mt_chob_v[ch] = 1; /* set valid */ @@ -518,14 +525,19 @@ if (uptr->UST == (CHSL_WRS|CHSL_2ND)) { /* data write? */ k = k - 6) { by = (uint8) ((val >> k) & 077); /* get byte */ if ((mt_unit[ch] & 020) == 0) { /* BCD? */ - if (by == 0) by = BCD_ZERO; /* cvt bin 0 */ - else if (by & 020) by = by ^ 040; /* invert zones */ - if (!odd_par[by]) by = by | 0100; /* even parity */ + if (by == 0) /* cvt bin 0 */ + by = BCD_ZERO; + else if (by & 020) /* invert zones */ + by = by ^ 040; + if (!odd_par[by]) /* even parity */ + by = by | 0100; } - else if (odd_par[by]) by = by | 0100; /* bin, odd par */ + else if (odd_par[by]) /* bin, odd par */ + by = by | 0100; xb[mt_bptr[ch]++] = by; /* put in buffer */ } - if (eorfl) return mt_rec_end (uptr); /* EOR? write rec */ + if (eorfl) + return mt_rec_end (uptr); /* EOR? write rec */ return SCPE_OK; } return SCPE_IERR; @@ -541,7 +553,8 @@ t_uint64 dat; t_mtrlnt bc; t_stat r; -if (xb == NULL) return SCPE_IERR; /* valid buffer? */ +if (xb == NULL) /* valid buffer? */ + return SCPE_IERR; u = uptr - mt_dev[ch].units; switch (uptr->UST) { /* case on state */ @@ -550,14 +563,17 @@ switch (uptr->UST) { /* case on state */ bc = chrono_rd (xb, MT_MAXFR); /* read clock */ else { /* real tape */ r = sim_tape_rdrecf (uptr, xb, &bc, MT_MAXFR); /* read record */ - if (r = mt_map_err (uptr, r)) return r; /* map status */ - if (mt_unit[ch] == 0) return SCPE_OK; /* disconnected? */ + if (r = mt_map_err (uptr, r)) /* map status */ + return r; + if (mt_unit[ch] == 0) /* disconnected? */ + return SCPE_OK; } /* end else Chrono */ if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */ mt_unit[ch] = 0; /* clr ctrl busy */ return SCPE_OK; } - for (i = bc; i < (bc + 6); i++) xb[i] = 0; /* extra 0's */ + for (i = bc; i < (bc + 6); i++) /* extra 0's */ + xb[i] = 0; mt_bptr[ch] = 0; /* set ptr, lnt */ mt_blnt[ch] = bc; uptr->UST = CHSL_RDS|CHSL_2ND; /* next state */ @@ -568,8 +584,10 @@ switch (uptr->UST) { /* case on state */ for (i = 0, dat = 0; i < 6; i++) { /* proc 6 bytes */ by = xb[mt_bptr[ch]++] & 077; /* get next byte */ if ((mt_unit[ch] & 020) == 0) { /* BCD? */ - if (by == BCD_ZERO) by = 0; /* cvt BCD 0 */ - else if (by & 020) by = by ^ 040; /* invert zones */ + if (by == BCD_ZERO) /* cvt BCD 0 */ + by = 0; + else if (by & 020) /* invert zones */ + by = by ^ 040; } dat = (dat << 6) | ((t_uint64) by); } @@ -590,9 +608,10 @@ switch (uptr->UST) { /* case on state */ sim_activate (uptr, mt_tshort); /* sched next record */ } else mt_unit[ch] = 0; /* clr ctrl busy */ - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d RDS complete, pos = %d, %s\n", - mt_dev[ch].name, u, uptr->pos, mt_unit[ch]? "continuing": "disconnecting"); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d RDS complete, pos = %d, %s\n", + mt_dev[ch].name, u, uptr->pos, + mt_unit[ch]? "continuing": "disconnecting"); return SCPE_OK; case CHSL_WRS: /* write start */ @@ -611,7 +630,8 @@ switch (uptr->UST) { /* case on state */ case CHSL_WRS|CHSL_2ND: /* write word */ if (!ch6_qconn (ch, mt_unit[ch])) /* disconnected? */ return mt_rec_end (uptr); /* write record */ - if (mt_chob_v[ch]) mt_chob_v[ch] = 0; /* valid? clear */ + if (mt_chob_v[ch]) /* valid? clear */ + mt_chob_v[ch] = 0; else ind_ioc = 1; /* no, io check */ ch6_req_wr (ch, mt_unit[ch]); /* request channel */ sim_activate (uptr, mt_tword); /* next word */ @@ -623,35 +643,41 @@ switch (uptr->UST) { /* case on state */ sim_activate (uptr, mt_tshort); /* sched next record */ } else mt_unit[ch] = 0; /* clr ctrl busy */ - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d WRS complete, pos = %d, %s\n", - mt_dev[ch].name, u, uptr->pos, mt_unit[ch]? "continuing": "disconnecting"); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d WRS complete, pos = %d, %s\n", + mt_dev[ch].name, u, uptr->pos, + mt_unit[ch]? "continuing": "disconnecting"); return SCPE_OK; case CHSL_BSR: /* backspace rec */ r = sim_tape_sprecr (uptr, &bc); /* space backwards */ mt_unit[ch] = 0; /* clr ctrl busy */ ch6_end_nds (ch); /* disconnect */ - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d BSR complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos); - if (r == MTSE_TMK) return SCPE_OK; /* allow tape mark */ + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d BSR complete, pos = %d\n", + mt_dev[ch].name, u, uptr->pos); + if (r == MTSE_TMK) /* allow tape mark */ + return SCPE_OK; return mt_map_err (uptr, r); case CHSL_BSF: /* backspace file */ while ((r = sim_tape_sprecr (uptr, &bc)) == MTSE_OK) ; mt_unit[ch] = 0; /* clr ctrl busy */ ch6_end_nds (ch); /* disconnect */ - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d BSF complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos); - if (r == MTSE_TMK) return SCPE_OK; /* allow tape mark */ + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d BSF complete, pos = %d\n", + mt_dev[ch].name, u, uptr->pos); + if (r == MTSE_TMK) /* allow tape mark */ + return SCPE_OK; return mt_map_err (uptr, r); /* map others */ case CHSL_WEF: /* write eof */ r = sim_tape_wrtmk (uptr); /* write tape mark */ mt_unit[ch] = 0; /* clr ctrl busy */ ch6_end_nds (ch); /* disconnect */ - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d WEF complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d WEF complete, pos = %d\n", + mt_dev[ch].name, u, uptr->pos); return mt_map_err (uptr, r); case CHSL_REW: case CHSL_RUN: /* rewind, unload */ @@ -663,14 +689,16 @@ switch (uptr->UST) { /* case on state */ case CHSL_REW | CHSL_2ND: sim_tape_rewind (uptr); - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d REW complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d REW complete, pos = %d\n", + mt_dev[ch].name, u, uptr->pos); return SCPE_OK; case CHSL_RUN | CHSL_2ND: sim_tape_detach (uptr); - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d RUN complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d RUN complete, pos = %d\n", + mt_dev[ch].name, u, uptr->pos); return SCPE_OK; case CHSL_SDN: @@ -679,8 +707,9 @@ switch (uptr->UST) { /* case on state */ else uptr->flags = uptr->flags | MTUF_LDN; mt_unit[ch] = 0; /* clr ctrl busy */ ch6_end_nds (ch); /* disconnect */ - if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d SDN complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos); + if (DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d SDN complete, pos = %d\n", + mt_dev[ch].name, u, uptr->pos); return SCPE_OK; default: @@ -699,9 +728,11 @@ uint8 *xb = mtxb[ch]; t_stat r; if (mt_bptr[ch]) { /* any data? */ - if (xb == NULL) return SCPE_IERR; + if (xb == NULL) + return SCPE_IERR; r = sim_tape_wrrecf (uptr, xb, mt_bptr[ch]); /* write record */ - if (r = mt_map_err (uptr, r)) return r; /* map error */ + if (r = mt_map_err (uptr, r)) /* map error */ + return r; } uptr->UST = CHSL_WRS|CHSL_3RD; /* next state */ sim_cancel (uptr); /* cancel current */ @@ -717,8 +748,9 @@ uint32 ch = uptr->UCH; uint32 u = mt_unit[ch]; uint32 up = uptr - mt_dev[ch].units; -if ((st != MTSE_OK) && DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb, - ">>%s%d status = %s, pos = %d\n", mt_dev[ch].name, up, tape_stat[st], uptr->pos); +if ((st != MTSE_OK) && DEBUG_PRS (mt_dev[ch])) + fprintf (sim_deb, ">>%s%d status = %s, pos = %d\n", + mt_dev[ch].name, up, tape_stat[st], uptr->pos); switch (st) { @@ -773,10 +805,13 @@ uint32 j; REG *rptr; UNIT *uptr; -if (mtxb[ch] == NULL) mtxb[ch] = (uint8 *) calloc (MT_MAXFR + 6, sizeof (uint8)); -if (mtxb[ch] == NULL) return SCPE_MEM; /* allocate buffer */ +if (mtxb[ch] == NULL) + mtxb[ch] = (uint8 *) calloc (MT_MAXFR + 6, sizeof (uint8)); +if (mtxb[ch] == NULL) /* allocate buffer */ + return SCPE_MEM; rptr = find_reg ("BUF", NULL, dptr); /* update reg ptr */ -if (rptr == NULL) return SCPE_IERR; +if (rptr == NULL) + return SCPE_IERR; rptr->loc = (void *) mtxb[ch]; mt_unit[ch] = 0; /* clear busy */ mt_bptr[ch] = 0; /* clear buf ptrs */ diff --git a/I7094/i7094_sys.c b/I7094/i7094_sys.c index ae473a49..1d36e3bc 100644 --- a/I7094/i7094_sys.c +++ b/I7094/i7094_sys.c @@ -1,6 +1,6 @@ /* i7094_sys.c: IBM 7094 simulator interface - Copyright (c) 2003-2006, Robert M Supnik + Copyright (c) 2003-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -571,9 +571,11 @@ DEVICE *dptr; t_uint64 inst; inst = val[0]; -if (uptr == NULL) uptr = &cpu_unit; +if (uptr == NULL) + uptr = &cpu_unit; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; if (sw & SWMASK ('C')) { /* character? */ c = (uint32) (inst & 077); @@ -588,15 +590,18 @@ if (sw & SWMASK ('S')) { /* string? */ return SCPE_OK; } if (!(sw & (SWMASK ('M')|SWMASK ('I')|SWMASK ('N'))) || /* M, N or I? */ - (dptr->dwidth != 36)) return SCPE_ARG; + (dptr->dwidth != 36)) + return SCPE_ARG; /* Instruction decode */ fld[0] = ((uint32) inst & 0777777); fld[1] = GET_TAG (inst); /* get 3 fields */ fld[2] = GET_DEC (inst); -if (sw & SWMASK ('I')) inst |= IFAKE_7607; /* decode as 7607? */ -if (sw & SWMASK ('N')) inst |= IFAKE_7909; /* decode as 7909? */ +if (sw & SWMASK ('I')) /* decode as 7607? */ + inst |= IFAKE_7607; +if (sw & SWMASK ('N')) /* decode as 7909? */ + inst |= IFAKE_7909; for (i = 0; opc_v[i] > 0; i++) { /* loop thru ops */ j = (int32) ((opc_v[i] >> I_V_FL) & I_M_FL); /* get class */ @@ -604,18 +609,22 @@ for (i = 0; opc_v[i] > 0; i++) { /* loop thru ops */ if (inst & ind_test[j]) /* indirect? */ fprintf (of, "%s*", opcode[i]); else fprintf (of, "%s", opcode[i]); /* opcode */ - for (k = 0; k < 3; k++) fld[k] = fld[k] & fld_max[j][k]; + for (k = 0; k < 3; k++) + fld[k] = fld[k] & fld_max[j][k]; for (k = 0; k < 3; k++) { /* loop thru fields */ fmt = fld_fmt[j][k]; /* get format */ - if (fmt == INST_P_XIT) return SCPE_OK; + if (fmt == INST_P_XIT) + return SCPE_OK; switch (fmt) { /* case on format */ case INST_P_PNT: /* print nz, else term */ for (l = k, c = 0; l < 3; l++) c |= fld[k]; - if (c == 0) return SCPE_OK; + if (c == 0) + return SCPE_OK; case INST_P_PNZ: /* print non-zero */ fputc (k? ',': ' ', of); - if (fld[k]) fprintf (of, "%-o", fld[k]); + if (fld[k]) + fprintf (of, "%-o", fld[k]); break; case INST_P_PRA: /* print always */ fputc (k? ',': ' ', of); @@ -639,10 +648,12 @@ return SCPE_ARG; uint32 cvt_code_to_ascii (uint32 c, int32 sw) { if (sw & SWMASK ('B')) { - if (sw & SWMASK ('A')) return bcd_to_ascii_a[c]; + if (sw & SWMASK ('A')) + return bcd_to_ascii_a[c]; else return bcd_to_ascii_h[c]; } -else if (sw & SWMASK ('A')) return nine_to_ascii_a[c]; +else if (sw & SWMASK ('A')) + return nine_to_ascii_a[c]; else return nine_to_ascii_h[c]; } @@ -668,15 +679,18 @@ char gbuf[CBUFSIZE]; while (isspace (*cptr)) cptr++; if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = (t_value) cvt_ascii_to_code (cptr[0] & 0177, sw); return SCPE_OK; } if ((sw & SWMASK ('S')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; for (i = 0; i < 6; i++) { c = cptr[0] & 0177; - if (c) val[0] = (val[0] << 6) | ((t_value) cvt_ascii_to_code (c, sw)); + if (c) + val[0] = (val[0] << 6) | ((t_value) cvt_ascii_to_code (c, sw)); else { val[0] = val[0] << (6 * (6 - i)); break; @@ -693,24 +707,30 @@ if (gbuf[j - 1] == '*') { /* indirect? */ } else ind = FALSE; for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; +if (opcode[i] == NULL) + return SCPE_ARG; j = (uint32) ((opc_v[i] >> I_V_FL) & I_M_FL); /* get class */ val[0] = opc_v[i] & DMASK; if (ind) { - if (ind_test[j]) val[0] |= ind_test[j]; + if (ind_test[j]) + val[0] |= ind_test[j]; else return SCPE_ARG; } -for (i = 0; i < 3; i++) fld[i] = 0; /* clear inputs */ +for (i = 0; i < 3; i++) /* clear inputs */ + fld[i] = 0; for (i = 0; (i < 3) && *cptr; i++) { /* parse inputs */ - if (i < 2) cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if (i < 2) /* get glyph */ + cptr = get_glyph (cptr, gbuf, ','); else cptr = get_glyph (cptr, gbuf, 0); if (gbuf[0]) { /* anything? */ fld[i] = get_uint (gbuf, 8, fld_max[j][i], &r); - if ((r != SCPE_OK) || (fld_max[j][i] == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (fld_max[j][i] == 0)) + return SCPE_ARG; } } -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; val[0] = val[0] | fld[0] | (fld[1] << INST_V_TAG) | (fld[2] << INST_V_DEC); return SCPE_OK; @@ -722,6 +742,7 @@ return SCPE_OK; uint32 cvt_ascii_to_code (uint32 c, int32 sw) { -if (sw & SWMASK ('B')) return ascii_to_bcd[c]; +if (sw & SWMASK ('B')) + return ascii_to_bcd[c]; else return ascii_to_nine[c]; } diff --git a/Interdata/id16_cpu.c b/Interdata/id16_cpu.c index b24128fe..fdf38ae5 100644 --- a/Interdata/id16_cpu.c +++ b/Interdata/id16_cpu.c @@ -1,6 +1,6 @@ /* id16_cpu.c: Interdata 16b CPU simulator - Copyright (c) 2000-2007, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -176,11 +176,15 @@ typedef struct { #define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP) #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; \ +#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; \ +#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)) @@ -553,7 +557,8 @@ t_stat reason; /* Restore register state */ -if (devtab_init ()) return SCPE_STOP; /* check conflicts */ +if (devtab_init ()) /* check conflicts */ + return SCPE_STOP; pawidth = PAWIDTH16; /* default width */ if (cpu_unit.flags & UNIT_816E) { /* 8/16E? */ dec_flgs = 0; /* all instr ok */ @@ -599,7 +604,8 @@ while (reason == 0) { /* loop until halted */ int32 sr, st; if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; int_eval (); } @@ -614,7 +620,8 @@ while (reason == 0) { /* loop until halted */ 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; + 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 */ } @@ -669,7 +676,8 @@ while (reason == 0) { /* loop until halted */ ityp = drom & OP_MASK; if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ - if (stop_inst) reason = STOP_RSRV; /* stop or */ + if (stop_inst) /* stop or */ + reason = STOP_RSRV; else cc = swap_psw (ILOPSW, cc); /* swap PSW */ continue; } @@ -692,21 +700,24 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (r2) /* index calculation */ + ea = (ir2 + R[r2]) & VAMASK; opnd = ea; /* operand is ea */ 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 */ + if (r2) /* index calculation */ + ea = (ir2 + R[r2]) & VAMASK; opnd = ReadB (ea); /* fetch operand */ 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 */ + if (r2) /* index calculation */ + ea = (ir2 + R[r2]) & VAMASK; opnd = ReadH (ea); /* fetch operand */ break; @@ -723,7 +734,8 @@ while (reason == 0) { /* loop until halted */ hst[hst_p].ea = ea; hst[hst_p].opnd = opnd; hst_p = hst_p + 1; - if (hst_p >= hst_lnt) hst_p = 0; + if (hst_p >= hst_lnt) + hst_p = 0; } PC = (PC + 2) & VAMASK; /* increment PC */ @@ -884,15 +896,18 @@ while (reason == 0) { /* loop until halted */ 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; + if (R[r1] < opnd) /* set C if borrow */ + cc = cc | CC_C; + 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 */ + if (t < opnd) /* set C if borrow */ + cc = cc | CC_C; break; /* Shift instructions */ @@ -902,7 +917,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = rslt; /* store result */ break; @@ -912,14 +928,16 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd && (rslt & 0x10000)) /* set C if shft out */ + cc = cc | CC_C; 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; + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = rslt; /* store result */ break; @@ -928,14 +946,16 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd && (rslt & SIGN16)) /* set C if shft out */ + cc = cc | CC_C; 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 */ + if (opnd) /* result */ + rslt = (t >> opnd) | (t << (32 - opnd)); else rslt = t; /* no shift */ CC_GL_32 (rslt); /* set G,L 32b */ R[r1] = (rslt >> 16) & DMASK16; /* hi result */ @@ -946,7 +966,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd) /* result */ + rslt = (t << opnd) | (t >> (32 - opnd)); else rslt = t; /* no shift */ CC_GL_32 (rslt); /* set G,L 32b */ R[r1] = (rslt >> 16) & DMASK16; /* hi result */ @@ -959,7 +980,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((t >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = (rslt >> 16) & DMASK16; /* hi result */ R[r1p1] = rslt & DMASK16; /* lo result */ break; @@ -970,7 +992,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((t << (opnd - 1)) & SIGN32)) + cc = cc | CC_C; R[r1] = (rslt >> 16) & DMASK16; /* hi result */ R[r1p1] = rslt & DMASK16; /* lo result */ break; @@ -981,7 +1004,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((t >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = (rslt >> 16) & DMASK16; /* hi result */ R[r1p1] = rslt & DMASK16; /* lo result */ break; @@ -992,7 +1016,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((t << opnd) & SIGN32)) + cc = cc | CC_C; R[r1] = (rslt >> 16) & DMASK16; /* hi result */ R[r1p1] = rslt & DMASK16; /* lo result */ break; @@ -1005,16 +1030,20 @@ while (reason == 0) { /* loop until halted */ 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; + if (rslt < opnd) /* set C if carry */ + cc = cc | CC_C; + 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; + if (rslt < opnd) /* set C if carry */ + cc = cc | CC_C; + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) + cc = cc | CC_V; WriteH (ea, rslt); /* store in memory */ break; @@ -1024,8 +1053,10 @@ while (reason == 0) { /* loop until halted */ 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; + if (R[r1] < opnd) /* set C if borrow */ + cc = cc | CC_C; + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) + cc = cc | CC_V; R[r1] = rslt; break; @@ -1034,8 +1065,10 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (sr < st) /* < sets C, L */ + cc = CC_C | CC_L; + else if (sr > st) /* > sets G */ + cc = CC_G; else cc = 0; if (((R[r1] ^ opnd) & (~opnd ^ (sr - st))) & SIGN16) cc = cc | CC_V; @@ -1082,8 +1115,10 @@ while (reason == 0) { /* loop until halted */ 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; + if (t > DMASK16) /* set C if carry */ + cc = cc | CC_C; + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) + cc = cc | CC_V; R[r1] = rslt; /* store result */ break; @@ -1092,8 +1127,10 @@ while (reason == 0) { /* loop until halted */ 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; + if (t > DMASK16) /* set C if borrow */ + cc = cc | CC_C; + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) + cc = cc | CC_V; R[r1] = rslt; /* store result */ break; @@ -1220,19 +1257,22 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (PSW & PSW_SQI) /* test for q */ + cc = testsysq (cc); 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 */ + if (PSW & PSW_SQI) /* test for q */ + cc = testsysq (cc); break; case 0x73: /* LPS - RXH */ cc = newPSW (opnd); /* load new PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + if (PSW & PSW_SQI) /* test for q */ + cc = testsysq (cc); break; case 0x64: /* ATL - RX */ @@ -1258,7 +1298,8 @@ while (reason == 0) { /* loop until halted */ 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> */ + if (R[r1] & SIGN16) /* S1? clr map<0> */ + map = map & ~0x8; else { map = 0; /* else 1:1 map */ R[r1] = R[r1] | SIGN16; /* set sign */ @@ -1330,7 +1371,8 @@ case 0xDE: /* OC - RX */ t = 0; /* read zero */ cc = CC_V; /* set V */ } - if (OP_TYPE (op) != OP_RR) WriteB (ea, t); /* RX or RR? */ + if (OP_TYPE (op) != OP_RR) /* RX or RR? */ + WriteB (ea, t); else R[r2] = t & DMASK8; int_eval (); /* re-eval intr */ break; @@ -1352,7 +1394,8 @@ case 0xDE: /* OC - RX */ t = 0; /* read zero */ cc = CC_V; /* set V */ } - if (OP_TYPE (op) != OP_RR) WriteH (ea, t); /* RX or RR? */ + if (OP_TYPE (op) != OP_RR) /* RX or RR? */ + WriteH (ea, t); else R[r2] = t; int_eval (); /* re-eval intr */ break; @@ -1369,7 +1412,8 @@ case 0xDE: /* OC - RX */ 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? */ + if (OP_TYPE (op) != OP_RR) /* RR or RX? */ + WriteB (ea, t); else R[r2] = t & DMASK8; cc = t & 0xF; int_eval (); /* re-eval intr */ @@ -1392,7 +1436,8 @@ case 0xDE: /* OC - RX */ if (OP_TYPE (op) != OP_RR) lim = ReadH ((ea + 2) & VAMASK); else lim = R[(r2 + 1) & 0xF]; - if (opnd > lim) cc = 0; /* start > end? */ + if (opnd > lim) /* start > end? */ + cc = 0; else { /* no, start I/O */ dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ blk_io.dfl = dev; /* set status block */ @@ -1411,7 +1456,8 @@ case 0xDE: /* OC - RX */ if (OP_TYPE (op) != OP_RR) lim = ReadH ((ea + 2) & VAMASK); else lim = R[(r2 + 1) & 0xF]; - if (opnd > lim) cc = 0; /* start > end? */ + if (opnd > lim) /* start > end? */ + cc = 0; else { /* no, start I/O */ dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ blk_io.dfl = dev | BL_RD; /* set status block */ @@ -1427,7 +1473,8 @@ case 0xDE: /* OC - 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? */ + if (AL_BUF > ea) /* start > end? */ + cc = 0; else { /* no, start I/O */ dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ dev_tab[dev] (dev, IO_OC, t); /* start dev */ @@ -1456,7 +1503,8 @@ uint32 newPSW (uint32 val) { PSW = val & psw_mask; /* store PSW */ int_eval (); /* update intreq */ -if (PSW & PSW_WAIT) qevent = qevent | EV_WAIT; /* wait state? */ +if (PSW & PSW_WAIT) /* wait state? */ + qevent = qevent | EV_WAIT; else qevent = qevent & ~EV_WAIT; if (cpu_unit.flags & UNIT_816E) { /* mapping enabled? */ uint32 map = PSW_GETMAP (PSW); /* get new map */ @@ -1464,7 +1512,8 @@ if (cpu_unit.flags & UNIT_816E) { /* mapping enabled? */ 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 */ +if (PSW & PSW_AIO) /* PSW<4> controls */ + SET_ENB (v_DS); else CLR_ENB (v_DS); /* DS interrupts */ return PSW & CC_MASK; } @@ -1477,7 +1526,8 @@ WriteH (loc, BUILD_PSW (cc)); /* write PSW, PC */ WriteH (loc + 2, PC); cc = newPSW (ReadH (loc + 4)); /* read PSW, PC */ PC = ReadH (loc + 6); -if (PSW & PSW_SQI) cc = testsysq (cc); /* sys q int enb? */ +if (PSW & PSW_SQI) /* sys q int enb? */ + cc = testsysq (cc); return cc; /* return CC */ } @@ -1506,18 +1556,21 @@ 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? */ +if (usd >= slt) /* list full? */ + return CC_V; 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 */ + if (t >= slt) /* wrap if necc */ + t = 0; 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 */ + if (wra == 0) /* wrap if necc */ + wra = (slt - 1) & DMASK8; else wra = wra - 1; /* dec top */ WriteB ((ea + Q16_TOP) & VAMASK, wra); /* rewrite top */ } @@ -1532,23 +1585,27 @@ 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? */ +if (usd == 0) /* empty? */ + return CC_V; 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 */ + if (rda == 0) /* wrap if necc */ + rda = (slt - 1) & DMASK8; 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 */ + if (t >= slt) /* wrap if necc */ + t = 0; 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) /* set cc's */ + return CC_G; else return 0; } @@ -1574,8 +1631,10 @@ do { } 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 (DEV_ACC (dev)) /* select dev */ + dev_tab[dev] (dev, IO_ADR, 0); + if (ccw & CCW16_NOP) /* NOP? exit */ + break; if (ccw & CCW16_INIT) { /* init set? */ ccw = ccw & ~CCW16_INIT; /* clr init */ WriteH (vec, ccw); /* rewrite */ @@ -1593,7 +1652,8 @@ do { 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 */ + if (ba) /* nz? exit */ + break; } /* end if dmt */ else if (fnc != CCW16_NUL) { /* rd or wr? */ if (DEV_ACC (dev)) /* dev exist? */ @@ -1605,7 +1665,8 @@ do { } else { /* ok, do xfer */ bpi = CCW16_BPI (ccw); /* get bytes/int */ - if (bpi == 0) bpi = 16; /* max 16B */ + if (bpi == 0) /* max 16B */ + bpi = 16; ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get start */ for (i = 0; i < bpi; i++) { /* do # bytes */ if (fnc == CCW16_RD) { /* chan read? */ @@ -1623,7 +1684,8 @@ do { 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 */ + (by != trm))) /* exit */ + break; ccw = ccw | CCW16_NOP; /* nop CCW */ WriteH (vec, ccw); /* rewrite CCW */ } /* end else sta */ @@ -1644,7 +1706,8 @@ do { 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? */ + if (ccw & CCW16_CON) /* cont? */ + rpt = TRUE; } } while (rpt); @@ -1664,7 +1727,8 @@ int t; switch (op) { case IO_ADR: /* select */ - if (!drmod) drpos = srpos = 0; /* norm mode? clr */ + if (!drmod) /* norm mode? clr */ + drpos = srpos = 0; return BY; /* byte only */ case IO_OC: /* command */ @@ -1673,13 +1737,15 @@ switch (op) { drmod = 1; drpos = srpos = 0; /* init cntrs */ } - else if (op == 0x80) drmod = 0; /* x80 = norm */ + else if (op == 0x80) /* x80 = norm */ + drmod = 0; break; case IO_WD: /* write */ if (drpos < 4) DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8)); - else if (drpos == 4) DRX = dat; + else if (drpos == 4) + DRX = dat; drpos = (drpos + 1) & ((cpu_unit.flags & (UNIT_716 | UNIT_816))? 7: 3); break; @@ -1746,9 +1812,9 @@ void WriteB (uint32 loc, uint32 val) uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; val = val & DMASK8; -if (MEM_ADDR_OK (pa)) M[pa >> 1] = ((pa & 1)? - ((M[pa >> 1] & ~DMASK8) | val): - ((M[pa >> 1] & DMASK8) | (val << 8))); +if (MEM_ADDR_OK (pa)) + M[pa >> 1] = ((pa & 1)? ((M[pa >> 1] & ~DMASK8) | val): + ((M[pa >> 1] & DMASK8) | (val << 8))); return; } @@ -1756,7 +1822,8 @@ void WriteH (uint32 loc, uint32 val) { uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; -if (MEM_ADDR_OK (pa)) M[pa >> 1] = val & DMASK16; +if (MEM_ADDR_OK (pa)) + M[pa >> 1] = val & DMASK16; return; } @@ -1774,8 +1841,10 @@ 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; +if (MEM_ADDR_OK (pa)) + M[pa >> 1] = (val >> 16) & DMASK16; +if (MEM_ADDR_OK (pa1)) + M[pa1 >> 1] = val & DMASK16; return; } @@ -1814,10 +1883,13 @@ 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 = (uint16 *) calloc (MAXMEMSIZE16E >> 1, sizeof (uint16)); -if (M == NULL) return SCPE_MEM; +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 */ -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; return SCPE_OK; } @@ -1827,11 +1899,14 @@ 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; + 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); +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = IOReadH (addr); return SCPE_OK; } @@ -1840,10 +1915,12 @@ 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; + if (addr > VAMASK) + return SCPE_NXM; addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } -if (addr >= MEMSIZE) return SCPE_NXM; +if (addr >= MEMSIZE) + return SCPE_NXM; IOWriteH (addr, val); return SCPE_OK; } @@ -1857,12 +1934,14 @@ uint32 i; if ((val <= 0) || ((val & 0xFFF) != 0) || (((uint32) val) > ((uptr->flags & UNIT_816E)? MAXMEMSIZE16E: MAXMEMSIZE16))) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1]; + return SCPE_ARG; +for (i = val; i < MEMSIZE; i = i + 2) + mc = mc | M[i >> 1]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) + M[i >> 1] = 0; return SCPE_OK; } @@ -1874,7 +1953,8 @@ uint32 i; if (!(val & UNIT_816E) && (MEMSIZE > MAXMEMSIZE16)) { MEMSIZE = MAXMEMSIZE16; - for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; + for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) + M[i >> 1] = 0; printf ("Reducing memory to 64KB\n"); } return SCPE_OK; @@ -1886,7 +1966,8 @@ t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) { if ((uptr->flags & (UNIT_716 | UNIT_816 | UNIT_816E)) == 0) return SCPE_NOFNC; -if (PSW & PSW_AIO) SET_INT (v_DS); +if (PSW & PSW_AIO) + SET_INT (v_DS); return SCPE_OK; } @@ -1898,12 +1979,14 @@ uint32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].vld = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -1912,7 +1995,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -1930,21 +2014,25 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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); + if (OP_TYPE (op) >= OP_RX) + fprintf (st, "%04X ", h->ea); else fprintf (st, " "); sim_eval[0] = h->ir1; sim_eval[1] = h->ir2; diff --git a/Interdata/id16_dboot.c b/Interdata/id16_dboot.c index 06ea5ac1..a4a38fec 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-2006, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -343,7 +343,8 @@ for (i = typ = 0; dboot_tab[i].name != NULL; i++) { break; } } -if (typ == 0) return SCPE_NOFNC; +if (typ == 0) + return SCPE_NOFNC; IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */ diff --git a/Interdata/id16_sys.c b/Interdata/id16_sys.c index 97ae6550..9489d0c6 100644 --- a/Interdata/id16_sys.c +++ b/Interdata/id16_sys.c @@ -100,7 +100,8 @@ const char *sim_stop_messages[] = { t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) { -if (flag) return pt_dump (fileref, cptr, fnam); +if (flag) + return pt_dump (fileref, cptr, fnam); return lp_load (fileref, cptr, fnam); } @@ -284,29 +285,38 @@ int32 bflag, c1, c2, rdx; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if (uptr == NULL) /* anon = CPU */ + uptr = &cpu_unit; dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth < 16) bflag = 1; /* 8b dev? */ +if (dptr == NULL) + return SCPE_IERR; +if (dptr->dwidth < 16) /* 8b dev? */ + bflag = 1; else bflag = 0; /* assume 16b */ -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; +if (sw & SWMASK ('D')) /* get radix */ + rdx = 10; +else if (sw & SWMASK ('O')) + rdx = 8; +else if (sw & SWMASK ('H')) + rdx = 16; else rdx = dptr->dradix; if (sw & SWMASK ('A')) { /* ASCII char? */ - if (bflag) c1 = val[0] & 0x7F; + if (bflag) + c1 = val[0] & 0x7F; else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */ fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); return 0; } if (sw & SWMASK ('B')) { /* byte? */ - if (bflag) c1 = val[0] & 0xFF; + if (bflag) + c1 = val[0] & 0xFF; else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */ fprint_val (of, c1, rdx, 8, PV_RZRO); return 0; } -if (bflag) return SCPE_ARG; /* 16b only */ +if (bflag) /* 16b only */ + return SCPE_ARG; if (sw & SWMASK ('C')) { /* string? */ c1 = (val[0] >> 8) & 0x7F; @@ -321,7 +331,8 @@ if (sw & SWMASK ('F')) { /* fullword? */ } if (sw & SWMASK ('M')) { /* inst format? */ r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; + if (r <= 0) + return r; } fprint_val (of, val[0], rdx, 16, PV_RZRO); @@ -392,7 +403,8 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ break; } /* end case */ - if (r2) fprintf (of, "(R%d)", r2); + if (r2) + fprintf (of, "(R%d)", r2); return -3; } /* end if */ } /* end for */ @@ -415,19 +427,24 @@ int32 reg; if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */ cptr++; /* skip */ - if (rtype == R_M) return -1; /* cant be mask */ + if (rtype == R_M) /* cant be mask */ + return -1; } 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; + 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 if ((*cptr >= 'a') && (*cptr <= 'f')) + reg = (*cptr - 'a') + 10; +else if ((*cptr >= 'A') && (*cptr <= 'F')) + reg = (*cptr - 'A') + 10; else return -1; -if ((rtype == R_F) && (reg & 1)) return -1; +if ((rtype == R_F) && (reg & 1)) + return -1; *optr = cptr + 1; return reg; } @@ -450,7 +467,8 @@ int32 sign = 1; if (*cptr == '.') { /* relative? */ cptr++; *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ + if (*cptr == '+') /* .+? */ + cptr++; else if (*cptr == '-') { /* .-? */ sign = -1; cptr++; @@ -460,7 +478,8 @@ if (*cptr == '.') { /* relative? */ else *ea = 0; errno = 0; *ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); -if (errno || (cptr == *tptr)) return SCPE_ARG; +if (errno || (cptr == *tptr)) + return SCPE_ARG; return SCPE_OK; } @@ -472,19 +491,27 @@ int32 bflag, by, rdx, num; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if (uptr == NULL) /* anon = CPU */ + uptr = &cpu_unit; dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth < 16) bflag = 1; /* 8b device? */ +if (dptr == NULL) + return SCPE_IERR; +if (dptr->dwidth < 16) /* 8b dev? */ + bflag = 1; else bflag = 0; /* assume 16b */ -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; +if (sw & SWMASK ('D')) /* get radix */ + rdx = 10; +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 (bflag) val[0] = (t_value) cptr[0]; + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; + if (bflag) + val[0] = (t_value) cptr[0]; else val[0] = (addr & 1)? (val[0] & ~0xFF) | ((t_value) cptr[0]): (val[0] & 0xFF) | (((t_value) cptr[0]) << 8); @@ -492,32 +519,39 @@ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ } if (sw & SWMASK ('B')) { /* byte? */ by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */ - if (r != SCPE_OK) return SCPE_ARG; - if (bflag) val[0] = by; + if (r != SCPE_OK) + return SCPE_ARG; + if (bflag) + val[0] = by; else val[0] = (addr & 1)? (val[0] & ~0xFF) | by: (val[0] & 0xFF) | (by << 8); return 0; } -if (bflag) return SCPE_ARG; /* 16b only */ +if (bflag) /* 16b only */ + return SCPE_ARG; if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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; + 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 */ -if (r <= 0) return r; +if (r <= 0) + return r; val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; return -1; } @@ -542,19 +576,22 @@ char *tptr, gbuf[CBUFSIZE]; 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; +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? */ + return SCPE_ARG; + if (*tptr != 0) /* all done? */ + 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 */ +if (*cptr) /* should be end */ + return SCPE_ARG; switch (j) { /* case on class */ case I_V_FF: case I_V_SI: /* flt-flt, sh imm */ @@ -562,7 +599,8 @@ switch (j) { /* case on class */ 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? */ + if (*tptr != 0) /* all done? */ + return SCPE_ARG; inst = inst | r2; /* or in R2 */ break; @@ -570,14 +608,17 @@ switch (j) { /* case on class */ 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 ((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; + if (*tptr++ != ')') + return SCPE_ARG; inst = inst | r2; /* or in R2 */ } - if (*tptr != 0) return SCPE_ARG; + if (*tptr != 0) + return SCPE_ARG; val[0] = inst; val[1] = t; return -3; diff --git a/Interdata/id32_cpu.c b/Interdata/id32_cpu.c index 455f2efa..969b954b 100644 --- a/Interdata/id32_cpu.c +++ b/Interdata/id32_cpu.c @@ -1,6 +1,6 @@ /* id32_cpu.c: Interdata 32b CPU simulator - Copyright (c) 2000-2007, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -197,11 +197,15 @@ typedef struct { ((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; \ +#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; \ +#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) @@ -614,7 +618,8 @@ int abortval; /* Restore register state */ -if (devtab_init ()) return SCPE_STOP; /* check conflicts */ +if (devtab_init ()) /* check conflicts */ + return SCPE_STOP; if (cpu_unit.flags & (UNIT_DPFP | UNIT_832)) { fp_in_hwre = 1; /* fp in hwre */ dec_flgs = 0; /* all instr ok */ @@ -623,7 +628,8 @@ else { fp_in_hwre = 0; /* fp in ucode */ dec_flgs = OP_DPF; /* sp only */ } -if (cpu_unit.flags & UNIT_8RS) psw_reg_mask = 7; /* 8 register sets */ +if (cpu_unit.flags & UNIT_8RS) /* 8 register sets */ + psw_reg_mask = 7; else psw_reg_mask = 1; /* 2 register sets */ int_eval (); /* eval interrupts */ cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */ @@ -642,7 +648,8 @@ reason = 0; 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 */ + if (cpu_unit.flags & UNIT_832) /* 832? restore PC */ + PC = oPC; } /* Event handling */ @@ -657,7 +664,8 @@ while (reason == 0) { /* loop until halted */ int32 sr, st; if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; int_eval (); } @@ -679,7 +687,8 @@ while (reason == 0) { /* loop until halted */ 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; + 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 */ } @@ -731,7 +740,8 @@ while (reason == 0) { /* loop until halted */ ityp = drom & OP_MASK; /* instruction type */ if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ - if (stop_inst) reason = STOP_RSRV; /* stop or */ + if (stop_inst) /* stop or */ + reason = STOP_RSRV; else cc = exception (ILOPSW, cc, 0); /* exception */ continue; } @@ -755,7 +765,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (r2) /* index calculation */ + opnd = (opnd + R[r2]) & DMASK32; PC = (PC + 4) & VAMASK; /* increment PC */ break; @@ -763,7 +774,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (r2) /* index calculation */ + opnd = (opnd + R[r2]) & DMASK32; PC = (PC + 6) & VAMASK; /* increment PC */ break; @@ -782,17 +794,21 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (rx2) /* index calc 2 */ + ea = ea + R[rx2]; PC = (PC + 6) & VAMASK; /* increment PC */ } - if (r2) ea = ea + R[r2]; /* index calculation */ + if (r2) /* index calculation */ + ea = ea + R[r2]; ea = ea & VAMASK; - if (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */ + if (ityp == OP_RXF) /* get fw operand? */ + opnd = ReadF (ea, VR); 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 if (ityp == OP_RXB) /* get byte opnd? */ + opnd = ReadB (ea, VR); else opnd = ea; /* just address */ break; @@ -809,9 +825,11 @@ while (reason == 0) { /* loop until halted */ hst[hst_p].ea = ea; hst[hst_p].opnd = opnd; hst_p = hst_p + 1; - if (hst_p >= hst_lnt) hst_p = 0; + if (hst_p >= hst_lnt) + hst_p = 0; } - if (qevent & EV_MAC) continue; /* MAC abort on fetch? */ + if (qevent & EV_MAC) /* MAC abort on fetch? */ + continue; switch (op) { /* case on opcode */ /* Load/store instructions */ @@ -1007,22 +1025,26 @@ while (reason == 0) { /* loop until halted */ 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; + if (R[r1] < opnd) /* set C if borrow */ + cc = cc | CC_C; + 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 */ + if (t < opnd) /* set C if borrow */ + cc = cc | CC_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 */ + if (R[r1] != opnd) /* wont fit? set V */ + cc = cc | CC_V; cc = cc | t; /* restore C */ break; @@ -1033,7 +1055,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && (((R[r1] & DMASK16) >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */ break; @@ -1042,7 +1065,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd && (rslt & 0x10000)) /* set C if shft out */ + cc = cc | CC_C; R[r1] = (R[r1] & ~DMASK16) | (rslt & DMASK16); /* store result */ break; @@ -1050,7 +1074,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */ break; @@ -1059,7 +1084,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd && (rslt & SIGN16)) /* set C if shft out */ + cc = cc | CC_C; break; case 0xEC: /* SRL - RI1 */ @@ -1067,7 +1093,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = rslt; /* store result */ break; @@ -1076,7 +1103,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((R[r1] << (opnd - 1)) & SIGN32)) + cc = cc | CC_C; R[r1] = rslt; /* store result */ break; @@ -1084,7 +1112,8 @@ while (reason == 0) { /* loop until halted */ 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; + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) + cc = cc | CC_C; R[r1] = rslt; /* store result */ break; @@ -1093,20 +1122,21 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd && (rslt & SIGN32)) /* set C if shft out */ + cc = cc | CC_C; 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 */ + if (opnd) /* if cnt > 0 */ + R[r1] = (R[r1] >> opnd) | ((R[r1] << (32 - opnd)) & DMASK32); 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 */ + if (opnd) + R[r1] = ((R[r1] << opnd) & DMASK32) | (R[r1] >> (32 - opnd)); CC_GL_32 (R[r1]); /* set G,L */ break; @@ -1116,7 +1146,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd & t) /* test bit */ + cc = CC_G; else cc = 0; break; @@ -1125,7 +1156,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd & t) /* test bit */ + cc = CC_G; else cc = 0; break; @@ -1134,7 +1166,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd & t) /* test bit */ + cc = CC_G; else cc = 0; break; @@ -1143,7 +1176,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (opnd & t) /* test bit */ + cc = CC_G; else cc = 0; break; @@ -1157,8 +1191,10 @@ while (reason == 0) { /* loop until halted */ 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; + if (rslt < opnd) /* set C if carry */ + cc = cc | CC_C; + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) + cc = cc | CC_V; R[r1] = rslt; break; @@ -1166,16 +1202,20 @@ while (reason == 0) { /* loop until halted */ 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; + if (rslt < opnd) /* set C if carry */ + cc = cc | CC_C; + 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; + if (rslt < (opnd & DMASK16)) /* set C if carry */ + cc = cc | CC_C; + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) + cc = cc | CC_V; break; case 0x0B: /* SR - RR */ @@ -1186,8 +1226,10 @@ while (reason == 0) { /* loop until halted */ 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; + if (R[r1] < opnd) /* set C if borrow */ + cc = cc | CC_C; + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) + cc = cc | CC_V; R[r1] = rslt; break; @@ -1219,7 +1261,8 @@ while (reason == 0) { /* loop until halted */ t = 0; /* no cout */ if (mpy & 1) { /* cond add */ rslt = (rslt + mpc) & DMASK32; - if (rslt < mpc) t = SIGN32; + if (rslt < mpc) + t = SIGN32; } rlo = (rlo >> 1) | ((rslt & 1) << 31); /* shift result */ rslt = (rslt >> 1) | t; @@ -1271,8 +1314,10 @@ while (reason == 0) { /* loop until halted */ 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 (quos & SIGN32) /* res -? neg quo */ + t = NEG (t); + if (R[r1] & SIGN32) /* adj rem sign */ + rslt = NEG (rslt); if (t && ((t ^ quos) & SIGN32)) { /* res sign wrong? */ if (PSW & PSW_AFI) /* if enabled, */ cc = exception (AFIPSW, cc, 0); /* exception */ @@ -1409,7 +1454,8 @@ while (reason == 0) { /* loop until halted */ case 0xE3: /* SCP - RXH */ opnd = opnd & DMASK16; /* zero ext operand */ - if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */ + if (opnd & CCW32_B1) /* point to buf */ + t = ea + CCB32_B1C; else t = ea + CCB32_B0C; sr = ReadH (t & VAMASK, VR); /* get count */ sr = SEXT16 (sr); /* sign extend */ @@ -1430,27 +1476,30 @@ while (reason == 0) { /* loop until halted */ 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); + 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 */ + if (PSW & PSW_SQI) /* test for q */ + cc = testsysq (cc); 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); + 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 */ + if (PSW & PSW_SQI) /* test for q */ + cc = testsysq (cc); 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 */ + if (PSW & PSW_SQI) /* test for q */ + cc = testsysq (cc); break; case 0x64: /* ATL - RX */ @@ -1467,7 +1516,8 @@ while (reason == 0) { /* loop until halted */ opnd = opnd & DMASK16; /* zero ext opnd */ t = (R[r1] & 0x3F) ^ opnd; for (i = 0; i < 6; i++) { - if (t & 1) t = (t >> 1) ^ 0x0F01; + if (t & 1) + t = (t >> 1) ^ 0x0F01; else t = t >> 1; } WriteH (ea, t, VW); @@ -1477,7 +1527,8 @@ while (reason == 0) { /* loop until halted */ opnd = opnd & DMASK16; /* zero ext opnd */ t = (R[r1] & 0xFF) ^ opnd; for (i = 0; i < 8; i++) { - if (t & 1) t = (t >> 1) ^ 0xA001; + if (t & 1) + t = (t >> 1) ^ 0xA001; else t = t >> 1; } WriteH (ea, t, VW); @@ -1486,7 +1537,8 @@ while (reason == 0) { /* loop until halted */ 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? */ + if (rslt & SIGN16) /* direct xlate? */ + R[r1] = rslt & DMASK8; else { PCQ_ENTRY; /* branch */ PC = rslt << 1; @@ -1550,7 +1602,8 @@ while (reason == 0) { /* loop until halted */ t = 0; cc = CC_V; } - if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */ + if (OP_TYPE (op) != OP_RR) /* RX or RR? */ + WriteB (ea, t, VW); else R[r2] = t & DMASK8; int_eval (); /* re-eval intr */ break; @@ -1572,7 +1625,8 @@ while (reason == 0) { /* loop until halted */ t = 0; cc = CC_V; } - if (OP_TYPE (op) != OP_RR) WriteH (ea, t, VW); /* RX or RR? */ + if (OP_TYPE (op) != OP_RR) /* RX or RR? */ + WriteH (ea, t, VW); else R[r2] = t & DMASK16; int_eval (); /* re-eval intr */ break; @@ -1585,7 +1639,8 @@ while (reason == 0) { /* loop until halted */ 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? */ + if (OP_TYPE (op) != OP_RR) /* RX or RR? */ + WriteB (ea, t, VW); else R[r2] = t & DMASK8; cc = t & 0xF; int_eval (); /* re-eval intr */ @@ -1608,7 +1663,8 @@ while (reason == 0) { /* loop until halted */ 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? */ + if (opnd > lim) /* start > end? */ + cc = 0; else { /* no, start I/O */ dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ blk_io.dfl = dev; /* set status block */ @@ -1627,7 +1683,8 @@ while (reason == 0) { /* loop until halted */ 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? */ + if (opnd > lim) /* start > end? */ + cc = 0; else { /* no, start I/O */ dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ blk_io.dfl = dev | BL_RD; /* set status block */ @@ -1643,7 +1700,8 @@ while (reason == 0) { /* loop until halted */ 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? */ + if (AL_BUF > ea) /* start > end? */ + cc = 0; else { /* no, start I/O */ dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ dev_tab[dev] (dev, IO_OC, t); /* start dev */ @@ -1676,9 +1734,11 @@ 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? */ +if (PSW & PSW_WAIT) /* wait state? */ + qevent = qevent | EV_WAIT; else qevent = qevent & ~EV_WAIT; -if (PSW & PSW_EXI) SET_ENB (v_DS); /* enable/disable */ +if (PSW & PSW_EXI) /* enable/disable */ + SET_ENB (v_DS); else CLR_ENB (v_DS); /* console intr */ return PSW & CC_MASK; } @@ -1700,9 +1760,9 @@ 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); +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 */ } @@ -1715,7 +1775,8 @@ 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 */ + if (cpu_unit.flags & UNIT_832) /* R13 = sys q addr */ + R[13] = qb; else GREG[13] = qb; } return cc; @@ -1730,18 +1791,21 @@ 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? */ +if (usd >= slt) /* list full? */ + return CC_V; 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 */ + if (t >= slt) /* wrap if necc */ + t = 0; 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 */ + 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 */ } @@ -1758,23 +1822,27 @@ 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? */ +if (usd == 0) /* empty? */ + return CC_V; 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 */ + if (rda == 0) /* wrap if necc */ + rda = (slt - 1) & DMASK16; 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 */ + if (t >= slt) /* wrap if necc */ + t = 0; 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; +if (usd) + return CC_G; else return 0; } @@ -1792,9 +1860,9 @@ 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 (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 */ @@ -1853,7 +1921,8 @@ if (ccw & CCW32_FST) { /* fast mode? */ } /* end if bufc <= 0 */ } /* end fast */ else { /* slow mode */ - if (ccw & CCW32_B1) ccwb = ccwa + CCB32_B1C; /* which buf? */ + if (ccw & CCW32_B1) /* which buf? */ + ccwb = ccwa + CCB32_B1C; else ccwb = ccwa + CCB32_B0C; t = ReadH (ccwb, VR); /* get count */ bufc = SEXT16 (t); /* sign ext */ @@ -1894,7 +1963,8 @@ else { /* slow mode */ t = t ^ by; /* start LRC */ if (ccw & CCW32_CRC) { /* CRC? */ for (i = 0; i < 8; i++) { - if (t & 1) t = (t >> 1) ^ 0xA001; + if (t & 1) + t = (t >> 1) ^ 0xA001; else t = t >> 1; } } @@ -1922,7 +1992,8 @@ int t; switch (op) { case IO_ADR: /* select */ - if (!drmod) drpos = srpos = 0; /* norm mode? clr */ + if (!drmod) /* norm mode? clr */ + drpos = srpos = 0; return BY; /* byte only */ case IO_OC: /* command */ @@ -1931,13 +2002,15 @@ switch (op) { drmod = 1; drpos = srpos = 0; /* init cntrs */ } - else if (op == 0x80) drmod = 0; /* x80 = norm */ + else if (op == 0x80) /* x80 = norm */ + drmod = 0; break; case IO_WD: /* write */ if (drpos < 4) DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8)); - else if (drpos == 4) DRX = dat; + else if (drpos == 4) + DRX = dat; drpos = (drpos + 1) & 0x7; break; @@ -1996,11 +2069,15 @@ 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? */ +if (off >= lim) /* limit viol? */ + return CC_C; +if ((mapr & SR_PRS) == 0) /* not present? */ + return CC_V; *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? */ +if (mapr & (SR_WRP | SR_WPI)) /* write prot? */ + return CC_G; +if (mapr & SR_EXP) /* exec prot? */ + return CC_L; return 0; /* ok */ } @@ -2030,7 +2107,8 @@ if ((PSW & PSW_REL) == 0) { /* reloc off? */ } else val = M[loc >> 2]; /* get mem word */ } -else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ +else if (rel == 0) /* phys ref? */ + val = M[loc >> 2]; else { uint32 pa = Reloc (loc, rel); /* relocate */ val = M[pa >> 2]; @@ -2049,7 +2127,8 @@ if ((PSW & PSW_REL) == 0) { /* reloc off? */ } else val = M[loc >> 2]; /* get mem word */ } -else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ +else if (rel == 0) /* phys ref? */ + val = M[loc >> 2]; else { uint32 pa = Reloc (loc, rel); /* relocate */ val = M[pa >> 2]; @@ -2068,7 +2147,8 @@ if ((PSW & PSW_REL) == 0) { /* reloc off? */ } else val = M[loc >> 2]; /* get mem word */ } -else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ +else if (rel == 0) /* phys ref? */ + val = M[loc >> 2]; else { uint32 pa = Reloc (loc, rel); /* relocate */ val = M[pa >> 2]; @@ -2093,9 +2173,10 @@ if ((PSW & PSW_REL) == 0) { /* reloc off? */ } } } -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); +else if (rel != 0) /* !phys? relocate */ + pa = Reloc (loc, rel); +if (MEM_ADDR_OK (pa)) + M[pa >> 2] = (M[pa >> 2] & ~(DMASK8 << sc)) | (val << sc); return; } @@ -2116,10 +2197,11 @@ if ((PSW & PSW_REL) == 0) { /* reloc off? */ } } } -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)); +else if (rel != 0) /* !phys? relocate */ + pa = Reloc (loc, rel); +if (MEM_ADDR_OK (pa)) + M[pa >> 2] = (loc & 2)? ((M[pa >> 2] & ~DMASK16) | val): + ((M[pa >> 2] & DMASK16) | (val << 16)); return; } @@ -2143,8 +2225,10 @@ if ((PSW & PSW_REL) == 0) { /* reloc off? */ } } } -else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ -if (MEM_ADDR_OK (pa)) M[pa >> 2] = val & DMASK32; +else if (rel != 0) /* !phys? relocate */ + pa = Reloc (loc, rel); +if (MEM_ADDR_OK (pa)) + M[pa >> 2] = val & DMASK32; return; } @@ -2190,10 +2274,13 @@ 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 = (uint32 *) calloc (MAXMEMSIZE32 >> 2, sizeof (uint32)); -if (M == NULL) return SCPE_MEM; +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 */ -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; return SCPE_OK; } @@ -2204,10 +2291,13 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) { int32 cc = RelocT (addr, MAC_BASE, P, &addr); - if (cc & (CC_C | CC_V)) return SCPE_NXM; + if (cc & (CC_C | CC_V)) + return SCPE_NXM; } -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = IOReadH (addr); +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = IOReadH (addr); return SCPE_OK; } @@ -2217,9 +2307,11 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) { int32 cc = RelocT (addr, MAC_BASE, P, &addr); - if (cc & (CC_C | CC_V)) return SCPE_NXM; + if (cc & (CC_C | CC_V)) + return SCPE_NXM; } -if (addr >= MEMSIZE) return SCPE_NXM; +if (addr >= MEMSIZE) + return SCPE_NXM; IOWriteH (addr, val); return SCPE_OK; } @@ -2233,11 +2325,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE32) || ((val & 0xFFFF) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2]; +for (i = val; i < MEMSIZE; i = i + 4) + mc = mc | M[i >> 2]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE32; i = i + 4) M[i >> 2] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE32; i = i + 4) + M[i >> 2] = 0; return SCPE_OK; } @@ -2250,8 +2344,10 @@ REG *rptr; int32 i; rptr = find_reg ("R0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < 16; i++, rptr++) rptr->loc = (void *) (rbase + i); +if (rptr == NULL) + return; +for (i = 0; i < 16; i++, rptr++) + rptr->loc = (void *) (rbase + i); return; } @@ -2259,7 +2355,8 @@ return; t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (PSW & PSW_EXI) SET_INT (v_DS); +if (PSW & PSW_EXI) + SET_INT (v_DS); return SCPE_OK; } @@ -2271,12 +2368,14 @@ uint32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -2285,7 +2384,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -2303,21 +2403,25 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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); + if (OP_TYPE (op) >= OP_RX) + fprintf (st, "%06X ", h->ea); else fprintf (st, " "); sim_eval[0] = h->ir1; sim_eval[1] = h->ir2; diff --git a/Interdata/id32_dboot.c b/Interdata/id32_dboot.c index 28871b25..081a3c4b 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-2006, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -299,7 +299,8 @@ 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].sw == 0) || + (dboot_tab[i].sw & sim_switches)) && (dboot_tab[i].cap == cap)) { typ = dboot_tab[i].dtype; off = dboot_tab[i].offset; @@ -307,7 +308,8 @@ for (i = typ = 0; dboot_tab[i].name != NULL; i++) { break; } } -if (typ == 0) return SCPE_NOFNC; +if (typ == 0) + return SCPE_NOFNC; IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */ diff --git a/Interdata/id32_sys.c b/Interdata/id32_sys.c index 3c50c677..7f85fa83 100644 --- a/Interdata/id32_sys.c +++ b/Interdata/id32_sys.c @@ -104,7 +104,8 @@ const char *sim_stop_messages[] = { t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) { -if (flag) return pt_dump (fileref, cptr, fnam); +if (flag) + return pt_dump (fileref, cptr, fnam); return lp_load (fileref, cptr, fnam); } @@ -306,19 +307,23 @@ uint32 rx2; if ((ea1 & 0xC000) == 0) { /* RX1 */ fprintf (of, "%-X", ea1); - if (rx) fprintf (of, "(R%d)", rx); + 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); + 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); +if (rx && !rx2) + fprintf (of, "(R%d)", rx); +if (rx2) + fprintf (of, "(R%d,R%d)", rx, rx2); return -5; } @@ -342,29 +347,38 @@ int32 bflag, c1, c2, rdx; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if (uptr == NULL) /* anon = CPU */ + uptr = &cpu_unit; dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth < 16) bflag = 1; /* 8b dev? */ +if (dptr == NULL) + return SCPE_IERR; +if (dptr->dwidth < 16) /* 8b dev? */ + bflag = 1; else bflag = 0; /* assume 16b */ -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; +if (sw & SWMASK ('D')) /* get radix */ + rdx = 10; +else if (sw & SWMASK ('O')) + rdx = 8; +else if (sw & SWMASK ('H')) + rdx = 16; else rdx = dptr->dradix; if (sw & SWMASK ('A')) { /* ASCII char? */ - if (bflag) c1 = val[0] & 0x7F; + if (bflag) + c1 = val[0] & 0x7F; else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */ fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); return 0; } if (sw & SWMASK ('B')) { /* byte? */ - if (bflag) c1 = val[0] & 0xFF; + if (bflag) + c1 = val[0] & 0xFF; else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */ fprint_val (of, c1, rdx, 8, PV_RZRO); return 0; } -if (bflag) return SCPE_ARG; /* 16b only */ +if (bflag) /* 16b only */ + return SCPE_ARG; if (sw & SWMASK ('C')) { /* string? */ c1 = (val[0] >> 8) & 0x7F; @@ -379,7 +393,8 @@ if (sw & SWMASK ('W')) { /* halfword? */ } if (sw & SWMASK ('M')) { /* inst format? */ r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; + if (r <= 0) + return r; } fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO); @@ -430,7 +445,7 @@ for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */ fprintf (of, "%-X,", r1); case I_V_SX: /* ext short branch */ fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - r2 - r2))); + (addr + r2 + r2): (addr - r2 - r2))); return -1; case I_V_R: /* register */ @@ -439,12 +454,14 @@ for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */ case I_V_RI: /* reg-immed */ fprintf (of, "R%d,%-X", r1, ea1); - if (r2) fprintf (of, "(R%d)", r2); + 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); + if (r2) + fprintf (of, "(R%d)", r2); return -5; case I_V_MX: /* mask-memory */ @@ -479,19 +496,24 @@ int32 reg; if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */ cptr++; /* skip */ - if (rtype == R_M) return -1; /* cant be mask */ + if (rtype == R_M) /* cant be mask */ + return -1; } 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; + 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 if ((*cptr >= 'a') && (*cptr <= 'f')) + reg = (*cptr - 'a') + 10; +else if ((*cptr >= 'A') && (*cptr <= 'F')) + reg = (*cptr - 'A') + 10; else return -1; -if ((rtype == R_F) && (reg & 1)) return -1; +if ((rtype == R_F) && (reg & 1)) + return -1; *optr = cptr + 1; return reg; } @@ -514,14 +536,17 @@ int32 idx; errno = 0; *imm = strtoul (cptr, &tptr, 16); /* get immed */ -if (errno || (*imm > max) || (cptr == tptr)) return SCPE_ARG; +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; + if (*tptr++ != ')') + return SCPE_ARG; *inst = *inst | idx; } -if (*tptr != 0) return SCPE_ARG; +if (*tptr != 0) + return SCPE_ARG; return SCPE_OK; } @@ -543,7 +568,8 @@ int32 sign = 1; if (*cptr == '.') { /* relative? */ cptr++; *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ + if (*cptr == '+') /* .+? */ + cptr++; else if (*cptr == '-') { /* .-? */ sign = -1; cptr++; @@ -553,7 +579,8 @@ if (*cptr == '.') { /* relative? */ else *ea = 0; errno = 0; *ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); -if (errno || (cptr == *tptr)) return SCPE_ARG; +if (errno || (cptr == *tptr)) + return SCPE_ARG; return SCPE_OK; } @@ -565,19 +592,27 @@ int32 bflag, by, rdx, num; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if (uptr == NULL) /* anon = CPU */ + uptr = &cpu_unit; dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth < 16) bflag = 1; /* 8b device? */ +if (dptr == NULL) + return SCPE_IERR; +if (dptr->dwidth < 16) /* 8b dev? */ + bflag = 1; else bflag = 0; /* assume 16b */ -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; +if (sw & SWMASK ('D')) /* get radix */ + rdx = 10; +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 (bflag) val[0] = (t_value) cptr[0]; + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; + if (bflag) + val[0] = (t_value) cptr[0]; else val[0] = (addr & 1)? (val[0] & ~0xFF) | ((t_value) cptr[0]): (val[0] & 0xFF) | (((t_value) cptr[0]) << 8); @@ -585,30 +620,36 @@ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ } if (sw & SWMASK ('B')) { /* byte? */ by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */ - if (r != SCPE_OK) return SCPE_ARG; + if (r != SCPE_OK) + return SCPE_ARG; if (bflag) val[0] = by; else val[0] = (addr & 1)? (val[0] & ~0xFF) | by: (val[0] & 0xFF) | (by << 8); return 0; } -if (bflag) return SCPE_ARG; /* 16b only */ +if (bflag) /* 16b only */ + return SCPE_ARG; if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1]; return -1; } if (sw & SWMASK ('W')) { /* halfword? */ val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */ - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; return -1; } r = parse_sym_m (cptr, addr, val); /* try to parse inst */ -if (r <= 0) return r; +if (r <= 0) + return r; num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; val[0] = (num >> 16) & DMASK16; val[1] = num & DMASK16; return -3; @@ -636,27 +677,31 @@ char *tptr, gbuf[CBUFSIZE]; vp = 0; cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; +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; + 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 */ +if (*cptr) /* should be end */ + return SCPE_ARG; 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; + return SCPE_ARG; + if (*tptr != 0) + return SCPE_ARG; inst = inst | r2; /* or in R2 */ break; @@ -664,7 +709,8 @@ switch (j) { /* case on class */ 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? */ + if (r != SCPE_OK) /* error? */ + return SCPE_ARG; rx2 = 0; /* assume no 2nd */ if (*tptr == '(') { /* index? */ if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0) @@ -674,9 +720,11 @@ switch (j) { /* case on class */ if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0) return SCPE_ARG; } - if (*tptr++ != ')') return SCPE_ARG; /* all done? */ + if (*tptr++ != ')') /* all done? */ + return SCPE_ARG; } - if (*tptr != 0) return SCPE_ARG; + if (*tptr != 0) + return SCPE_ARG; val[0] = inst; /* store inst */ if (rx2 == 0) { /* no 2nd? */ if (t < 0x4000) { /* RX1? */ @@ -697,14 +745,16 @@ switch (j) { /* case on class */ case I_V_RI: /* 16b immediate */ r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */ - if (r != SCPE_OK) return r; + 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; + if (r != SCPE_OK) + return r; val[0] = inst; val[1] = (t >> 16) & DMASK16; val[2] = t & DMASK16; diff --git a/Interdata/id_dp.c b/Interdata/id_dp.c index 8a216ee7..a62bf33f 100644 --- a/Interdata/id_dp.c +++ b/Interdata/id_dp.c @@ -1,6 +1,6 @@ /* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator - Copyright (c) 2001-2005, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -276,7 +276,8 @@ switch (op) { /* case IO op */ 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 */ + if (dp_sta & STC_IDL) /* idle? hdsc */ + dp_hdsc = dat & HS_MASK; else { /* data xfer */ dp_sta = dp_sta | STA_BSY; /* set busy */ dp_db = dat & 0xFF; /* store data */ @@ -285,7 +286,8 @@ switch (op) { /* case IO op */ case IO_SS: /* status */ t = dp_sta & STC_MASK; /* get status */ - if (t & SETC_EX) t = t | STA_EX; /* test for EX */ + if (t & SETC_EX) /* test for EX */ + t = t | STA_EX; return t; case IO_OC: /* command */ @@ -298,15 +300,19 @@ switch (op) { /* case IO op */ } 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; + 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 */ + if (dp_cmd == CMC_WR) /* write: bsy=0 else */ + dp_sta = 0; 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? */ + if (dp_svun & o_DPF) /* upper platter? */ + dp_plat = 1; else dp_plat = 0; /* no, lower */ - if (good_cmd[f]) sim_activate (uptr, dp_rtime); /* legal? sched */ + if (good_cmd[f]) /* legal? sched */ + sim_activate (uptr, dp_rtime); break; } @@ -321,18 +327,21 @@ int32 diff; uint32 t, u; UNIT *uptr; -if (dev == dp_dib.dno) return dpc (dev, op, dat); /* controller? */ +if (dev == dp_dib.dno) /* controller? */ + return dpc (dev, op, dat); 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 */ + if (dp_sta & STC_IDL) /* idle? save unit */ + dp_svun = dev; 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 (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 */ @@ -344,19 +353,25 @@ switch (op) { /* case IO op */ ((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 */ + if (t & SETD_EX) /* test for ex */ + t = t | STA_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); + 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 */ + if (dat & CMD_SK) /* seek? get cyl */ + t = dp_cyl; + else if (dat & CMD_RST) /* rest? cyl 0 */ + t = 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 */ + if (diff < 0) /* ABS cyl diff */ + diff = -diff; + else if (diff == 0) /* must be nz */ + diff = 1; uptr->STD = STD_MOV; /* stat = moving */ uptr->CYL = t; /* put on cyl */ sim_activate (uptr, diff * dp_stime); /* schedule */ @@ -383,12 +398,14 @@ 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 ((uptr->flags & UNIT_ATT) == 0) /* offl? hangs */ + return SCPE_OK; 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 */ + if (dpd_arm[u]) /* req intr */ + SET_INT (v_DPC + u + 1); return SCPE_OK; } @@ -400,8 +417,10 @@ switch (dp_cmd & 0x7) { /* case on func */ 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? */ + if (dp_dter (uptr, dp_1st)) /* check xfr err */ + return SCPE_OK; + if (r = dp_rds (uptr)) /* read sec, err? */ + return r; 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? */ @@ -415,10 +434,12 @@ switch (dp_cmd & 0x7) { /* case on func */ 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 */ + if (dp_dter (uptr, dp_1st)) /* check xfr err */ + return SCPE_OK; 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? */ + if (r = dp_wds (uptr)) /* write sec, err? */ + return r; dp_1st = 0; if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */ sim_activate (uptr, dp_rtime); /* reschedule */ @@ -441,7 +462,8 @@ 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 */ +for ( ; i < DP_NUMBY; i++) /* fill with 0's */ + dpxb[i] = 0; if (ferror (uptr->fileref)) { /* error? */ perror ("DP I/O error"); clearerr (uptr->fileref); @@ -482,7 +504,8 @@ if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ 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; + if (dp_cyl == 0) + uptr->CYL = 0; else { dp_done (STC_ACF); /* error, done */ return TRUE; @@ -498,7 +521,8 @@ if (!first && (sc == 0) && (hd == 0)) { /* cyl overflow? */ } 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? */ +if ((sc + 1) < DP_NUMSC) /* end of track? */ + dp_hdsc = dp_hdsc + 1; else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK; /* sec 0, nxt srf */ return FALSE; } @@ -509,7 +533,8 @@ 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 */ +if (flg) /* if err, stop ch */ + sch_stop (dp_dib.sch); return; } @@ -548,10 +573,13 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; uptr->CYL = 0; -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; +if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; +if ((p = ftell (uptr->fileref)) == 0) + return SCPE_OK; for (i = 0; drv_tab[i].surf != 0; i++) { if (p <= drv_tab[i].size) { uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); @@ -568,8 +596,10 @@ 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)) /* attached? */ + return SCPE_OK; +if (dpd_arm[u]) /* if arm, intr */ + SET_INT (v_DPC + u + 1); return detach_unit (uptr); } @@ -577,7 +607,8 @@ return detach_unit (uptr); t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = drv_tab[GET_DTYPE (val)].size; return SCPE_OK; } diff --git a/Interdata/id_fd.c b/Interdata/id_fd.c index f99f2a4c..12654c9c 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-2005, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -214,8 +214,10 @@ switch (op) { /* case IO op */ 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_sta & (STA_IDL | STA_BSY)) /* idle, busy? */ + return fd_db; + if (fd_bptr < FD_NUMBY) /* get byte */ + fd_db = fdxb[fd_bptr++]; if (fd_bptr >= FD_NUMBY) { /* buf end? */ if (ctab[fnc] & C_RD) { /* disk read? */ sched_seek (uptr, uptr->LRN + 1); /* sched read */ @@ -234,7 +236,7 @@ switch (op) { /* case IO op */ break; } if (fd_bptr < FD_NUMBY) /* if room, */ - fdxb[fd_bptr++] = fd_db = dat; /* store byte */ + 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 */ @@ -248,8 +250,10 @@ switch (op) { /* case IO op */ 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 */ + if ((uptr->flags & UNIT_ATT) == 0) + t = t | STA_DU; + if (t & SET_EX) /* test for ex */ + t = t | STA_EX; return t; case IO_OC: /* command */ @@ -260,7 +264,8 @@ switch (op) { /* case IO op */ 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 (sim_is_active (uptr)) /* busy? cont */ + break; 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 */ @@ -275,14 +280,17 @@ switch (op) { /* case IO op */ 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 */ + if (fnc == FNC_BOOT) /* boot? fixed sec */ + t = LRN_BOOT; + else if (fd_wdv) /* valid data? use */ + t = fd_lrn; 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? */ + if (ctab[fnc] & C_RD) /* seek now? */ + sched_seek (uptr, t); else sim_activate (uptr, fd_ctime); /* start cmd */ } break; @@ -313,8 +321,10 @@ switch (fnc) { /* case on function */ 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? */ + if (uptr->FNC & FNC_STOPPING) /* stopped? */ + break; + if (fd_dte (uptr, FALSE)) /* xfr error? */ + return SCPE_OK; da = GET_DA (uptr->LRN); /* get disk addr */ for (i = 0; i < FD_NUMBY; i++) /* read sector */ fdxb[i] = fbuf[da + i]; @@ -329,7 +339,8 @@ switch (fnc) { /* case on function */ break; case FNC_WR: case FNC_DEL: /* write block */ - if (fd_dte (uptr, TRUE)) return SCPE_OK; /* xfr error? */ + if (fd_dte (uptr, TRUE)) /* xfr error? */ + return SCPE_OK; if (fd_bptr) { /* any transfer? */ da = GET_DA (uptr->LRN); /* get disk addr */ for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */ @@ -345,7 +356,7 @@ switch (fnc) { /* case on function */ } break; - case FNC_RSTA: /* read status */ + 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? */ @@ -354,11 +365,13 @@ switch (fnc) { /* case on function */ 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; + for (i = 0; i < ES_SIZE; i++) /* copy to buf */ + fdxb[i] = fd_es[u][i]; + for (i = ES_SIZE; i < FD_NUMBY; i++) + fdxb[i] = 0; break; - case FNC_RDID: /* read ID */ + 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; @@ -387,7 +400,8 @@ if (uptr->FNC & FNC_STOPPING) { /* stopping? */ 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 (fd_arm) /* if armed, int */ + SET_INT (v_FD); return SCPE_OK; } @@ -397,8 +411,10 @@ void sched_seek (UNIT *uptr, int32 newlrn) { int32 diff = newlrn - uptr->LRN; /* LRN diff */ -if (diff < 0) diff = -diff; /* ABS */ -if (diff < 10) diff = 10; /* MIN 10 */ +if (diff < 0) /* ABS */ + diff = -diff; +if (diff < 10) + diff = 10; /* MIN 10 */ sim_activate (uptr, diff * fd_stime); /* schedule */ return; } @@ -408,7 +424,8 @@ 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 */ +if (fd_arm) /* if armed, int */ + SET_INT (v_FD); fd_es[u][0] = fd_es[u][0] | nes0; /* set ext state */ fd_es[u][1] = fd_es[u][1] | nes1; return; @@ -444,7 +461,8 @@ uint32 i, wrk; for (i = 0; i < cnt; i++) { wrk = crc ^ dat; crc = (crc << 1) & DMASK16; - if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16; + if (wrk & SIGN16) + crc = ((crc ^ 0x1020) + 1) & DMASK16; dat = (dat << 1) & DMASK16; } return crc; @@ -498,7 +516,8 @@ 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? */ +if (decrom[0xD5] & dec_flgs) /* AL defined? */ + return SCPE_NOFNC; 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 */ diff --git a/Interdata/id_fp.c b/Interdata/id_fp.c index b6ba1f18..b9cf028a 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-2005, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -218,7 +218,8 @@ uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */ struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */ uint32 cc; -if (R[r2] == 0) cc = 0; /* zero arg? */ +if (R[r2] == 0) /* zero arg? */ + cc = 0; else if (R[r2] & SIGN16) { /* neg arg? */ res.sign = FP_M_SIGN; /* set sign */ res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */ @@ -264,8 +265,10 @@ 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 */ +if (op & 1) /* if sub, inv sign2 */ + fop2.sign = fop2.sign ^ 1; +if (fop1.h == 0) /* if op1 = 0, res = op2 */ + fop1 = fop2; else if (fop2.h != 0) { /* if op2 = 0, no add */ if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */ ((fop1.exp == fop2.exp) && @@ -277,13 +280,15 @@ else if (fop2.h != 0) { /* if op2 = 0, no add */ } 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? */ + if (ediff >= 14) /* diff too big? */ + fop2.h = fop2.l = 0; 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? */ + if (ediff >= 6) /* diff too big? */ + fop2.h = 0; else if (ediff) /* any difference? */ fop2.h = fop2.h >> (ediff * 4); /* shift frac */ } @@ -328,7 +333,8 @@ if (fop1.h && fop2.h) { /* if both != 0 */ 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 */ + if (fop2.h & 1) /* add hi only */ + res.h = res.h + fop1.h; FR_RSH_K (res, 1); /* shift dp res */ fop2.h = fop2.h >> 1; } @@ -336,13 +342,17 @@ if (fop1.h && fop2.h) { /* if both != 0 */ 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); } + 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); } + if (fop2.h & 1) { + FR_ADD (res, fop1); + } FR_RSH_K (res, 1); fop2.h = fop2.h >> 1; } @@ -364,7 +374,8 @@ 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 (fop2.h == 0) /* div by zero? */ + return CC_C | CC_V; if (fop1.h) { /* dvd != 0? */ quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */ quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */ @@ -388,7 +399,8 @@ if (fop1.h) { /* dvd != 0? */ } if (!OP_DPFP (op)) { /* single? */ quo.h = quo.l; /* move quotient */ - if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND; + if (fop1.h >= (fop2.h << 3)) + quo.l = FP_ROUND; else quo.l = 0; } /* don't need to normalize */ } /* end if fop1.h */ @@ -429,7 +441,8 @@ 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 */ + if (OP_DPFP (op)) /* dp? get lo */ + fop->l = ReadF (ea + 4, VR); else fop->l = 0; /* sp, lo = 0 */ } else { @@ -515,7 +528,8 @@ 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 */ +if (fop->exp < 0) /* undf? clean 0 */ + fop->h = fop->l = 0; else { fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */ fop->l = 0xFFFFFFFF; diff --git a/Interdata/id_idc.c b/Interdata/id_idc.c index baf00dd6..e2ac7003 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-2006, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -375,7 +375,8 @@ switch (op) { /* case IO op */ case IO_SS: /* status */ t = idc_sta & STC_MASK; /* get status */ - if (t & SETC_EX) t = t | STA_EX; /* test for EX */ + if (t & SETC_EX) /* test for EX */ + t = t | STA_EX; return t; case IO_OC: /* command */ @@ -437,13 +438,15 @@ uint32 id (uint32 dev, uint32 op, uint32 dat) uint32 t, u, f; UNIT *uptr; -if (dev == idc_dib.dno) return idc (dev, op, dat); /* controller? */ +if (dev == idc_dib.dno) /* controller? */ + return idc (dev, op, dat); 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 */ + if (idc_sta & STC_IDL) /* idle? save unit */ + idc_svun = u; return BY; /* byte only */ case IO_RD: /* read data */ @@ -463,7 +466,8 @@ switch (op) { /* case IO op */ (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 */ + if (t & SETD_EX) /* test for ex */ + t = t | STA_EX; return t; case IO_OC: /* command */ @@ -475,7 +479,8 @@ switch (op) { /* case IO op */ if ((f == 0) || /* if nop, */ (f == CMDX_MASK) || /* 0x30, */ !(idc_sta & STC_IDL) || /* !idle, */ - sim_is_active (uptr)) break; /* unit busy, ignore */ + sim_is_active (uptr)) /* unit busy, ignore */ + break; uptr->FNC = f | CMC_DRV; /* save cmd */ idc_sta = idc_sta & ~STC_IDL; /* clr idle */ sim_activate (uptr, idc_ctime); /* schedule */ @@ -509,7 +514,8 @@ if (uptr->FNC & CMC_DRV) { /* drive cmd? */ 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 ((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? */ @@ -527,7 +533,8 @@ if (uptr->FNC & CMC_DRV) { /* drive cmd? */ sim_activate (uptr, idc_ctime); } else if (f >= CMDF_SCY) { /* tag? */ - if (f & CMDF_SHD) uptr->HD = idd_db & HD_MASK; + 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 */ @@ -535,7 +542,8 @@ if (uptr->FNC & CMC_DRV) { /* drive cmd? */ } } else if (f & (CMD_SK | CMD_RST)) { /* seek? */ - if (f == CMD_RST) idd_dcy[u] = 0; /* restore? */ + if (f == CMD_RST) /* restore? */ + idd_dcy[u] = 0; 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 */ @@ -544,8 +552,10 @@ if (uptr->FNC & CMC_DRV) { /* drive cmd? */ 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 */ + if (diff < 0) /* ABS cyl diff */ + diff = -diff; + else if (diff == 0) /* must be nz */ + diff = 1; sim_activate (uptr, diff * idc_stime); } } @@ -564,10 +574,12 @@ switch (uptr->FNC & CMC_MASK) { /* case on func */ #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? */ + if (idc_dter (uptr, idc_1st)) /* dte? done */ + return SCPE_OK; + if (r = idc_rds (uptr)) /* read sec, err? */ + return r; idc_1st = 0; - t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */ + 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; @@ -577,12 +589,14 @@ switch (uptr->FNC & CMC_MASK) { /* case on func */ idc_sta = idc_sta | STC_DTE; /* cant work */ break; - case CMC_WR: /* write */ + 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 */ + if (idc_dter (uptr, idc_1st)) /* dte? done */ + return SCPE_OK; 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? */ + if (r = idc_wds (uptr)) /* write sec, err? */ + return r; idc_1st = 0; if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ sim_activate (uptr, idc_rtime); /* reschedule */ @@ -649,7 +663,8 @@ if (ferror (uptr->fileref)) { /* error? */ idc_done (STC_DTE); return SCPE_IOERR; } -for ( ; i < IDC_NUMBY; i++) idcxb[i] = 0; /* fill with 0's */ +for ( ; i < IDC_NUMBY; i++) /* fill with 0's */ + idcxb[i] = 0; return SCPE_OK; } @@ -704,7 +719,8 @@ if (hd >= drv_tab[dtype].surf) { /* bad head? */ 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; +if (idc_sec == 0) + uptr->HD = uptr->HD + 1; return FALSE; } @@ -713,10 +729,12 @@ 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 */ +if (idc_arm) /* if armed, intr */ + SET_INT (v_IDC); 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 */ +if (flg) /* if err, stop sch */ + sch_stop (idc_dib.sch); return; } @@ -760,10 +778,13 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; uptr->CYL = 0; -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; +if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; +if ((p = ftell (uptr->fileref)) == 0) + return SCPE_OK; for (i = 0; drv_tab[i].surf != 0; i++) { if (p <= drv_tab[i].size) { uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); @@ -778,7 +799,8 @@ return SCPE_OK; t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = drv_tab[GET_DTYPE (val)].size; return SCPE_OK; } diff --git a/Interdata/id_io.c b/Interdata/id_io.c index b415f80c..98ce4a1d 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-2006, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -84,6 +84,7 @@ 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_nchan (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc); /* Selector channel data structures @@ -113,8 +114,8 @@ REG sch_reg[] = { }; MTAB sch_mod[] = { - { MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS", - &sch_set_nchan, NULL, &sch_reg[0] }, + { MTAB_XTD|MTAB_VDV, 0, "channels", "CHANNELS", + &sch_set_nchan, &sch_show_nchan, NULL }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL, NULL, &sch_show_reg, NULL }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL, @@ -166,14 +167,16 @@ switch (op) { /* case IO op */ case IO_WD: /* write data */ if (pawidth != PAWIDTH32) { /* 16b? max 4 */ - if (sch_wdc[ch] >= 4) break; /* stop at 4 */ + if (sch_wdc[ch] >= 4) /* stop at 4 */ + break; 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] >= 6) /* stop at 6 */ + break; 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; @@ -186,11 +189,14 @@ switch (op) { /* case IO op */ 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 */ + if (sch_cmd[ch] & SCHC_GO) /* test busy */ + return STA_BSY; + if (sch_cmd[ch] & SCHC_SSTA) /* test sch sta */ + return 0; else { sdv = sch_sdv[ch]; /* get dev */ - if (dev_tab[sdv] == 0) return CC_V; /* not there? */ + if (dev_tab[sdv] == 0) /* not there? */ + return CC_V; 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 */ @@ -232,7 +238,8 @@ t_bool sch_blk (uint32 dev) { uint32 ch = sch_tab[dev] - 1; -if ((ch < sch_max) && (sch_cmd[ch] & SCHC_GO)) return TRUE; +if ((ch < sch_max) && (sch_cmd[ch] & SCHC_GO)) + return TRUE; return FALSE; } @@ -240,7 +247,8 @@ return FALSE; void sch_adr (uint32 ch, uint32 dev) { -if (ch < sch_max) sch_sdv[ch] = dev; +if (ch < sch_max) + sch_sdv[ch] = dev; return; } @@ -250,7 +258,8 @@ 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? */ + (sch_sdv[ch] == dev)) /* set for dev? */ + return TRUE; return FALSE; /* no */ } @@ -260,7 +269,8 @@ 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; +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 */ @@ -280,7 +290,8 @@ 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; +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 */ @@ -339,18 +350,22 @@ DIB *dibp; uint32 i, newmax; t_stat r; -if (cptr == NULL) return SCPE_ARG; +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 ((r != SCPE_OK) || (newmax == sch_max)) /* err or no chg? */ + return r; +if (newmax == 0) /* must be > 0 */ + return SCPE_ARG; 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); + dibp->dno, dibp->sch); + if (sim_log) + fprintf (sim_log, "Device %02X uses channel %d\n", + dibp->dno, dibp->sch); return SCPE_OK; } } @@ -360,12 +375,22 @@ sch_reset_ch (sch_max); /* reset chan */ return SCPE_OK; } +/* Show number of channels */ + +t_stat sch_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "channels=%d", sch_max); +return SCPE_OK; +} + /* Show channel registers */ t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc) { -if (val < 0) return SCPE_IERR; -if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val); +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]); @@ -383,7 +408,8 @@ void sch_ini (t_bool dtpl) { uint32 i; -for (i = 0; i < sch_max; i++) sch_tplte[i] = i; +for (i = 0; i < sch_max; i++) + sch_tplte[i] = i; sch_tplte[sch_max] = TPL_END; return; } @@ -453,9 +479,12 @@ return armdis; int32 io_2b (int32 val, int32 pos, int32 old) { int32 t = (val >> pos) & 3; -if (t == 0) return old; -if (t == 1) return 1; -if (t == 2) return 0; +if (t == 0) + return old; +if (t == 1) + return 1; +if (t == 2) + return 0; return old ^1; } @@ -465,9 +494,12 @@ uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf) { uint32 i; -if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0; -if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc; -for (i = 0; i < cnt; i++) buf[i] = IOReadB (loc + i); +if (!MEM_ADDR_OK (loc) || (cnt == 0)) + return 0; +if (!MEM_ADDR_OK (loc + cnt - 1)) + cnt = MEMSIZE - loc; +for (i = 0; i < cnt; i++) + buf[i] = IOReadB (loc + i); return cnt; } @@ -475,9 +507,12 @@ uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf) { uint32 i; -if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0; -if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc; -for (i = 0; i < cnt; i++) IOWriteB (loc + i, buf[i]); +if (!MEM_ADDR_OK (loc) || (cnt == 0)) + return 0; +if (!MEM_ADDR_OK (loc + cnt - 1)) + cnt = MEMSIZE - loc; +for (i = 0; i < cnt; i++) + IOWriteB (loc + i, buf[i]); return cnt; } @@ -490,14 +525,19 @@ DIB *dibp; uint32 newch; t_stat r; -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; +if (cptr == NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR; +if ((dibp == NULL) || (dibp->sch < 0)) + return SCPE_IERR; newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; dibp->sch = newch; /* store */ return SCPE_OK; } @@ -509,11 +549,14 @@ t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR; +if ((dibp == NULL) || (dibp->sch < 0)) + return SCPE_IERR; fprintf (st, "selch=%X", dibp->sch); return SCPE_OK; } @@ -527,15 +570,21 @@ DIB *dibp; uint32 newdev; t_stat r; -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; +if (cptr == NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dno)) return r; -if (newdev == 0) return SCPE_ARG; /* must be > 0 */ +if ((r != SCPE_OK) || (newdev == dibp->dno)) + return r; +if (newdev == 0) /* must be > 0 */ + return SCPE_ARG; dibp->dno = newdev; /* store */ return SCPE_OK; } @@ -547,11 +596,14 @@ t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->dno == 0)) return SCPE_IERR; +if ((dibp == NULL) || (dibp->dno == 0)) + return SCPE_IERR; fprintf (st, "devno=%02X", dibp->dno); return SCPE_OK; } @@ -571,35 +623,43 @@ for (i = 0; i < DEVNO; i++) { dev_tab[i] = NULL; sch_tab[i] = 0; } -for (i = 0; i < (INTSZ * 32); i++) int_tab[i] = 0; -for (i = 0; i < (DEVNO / 32); i++) dmap[i] = 0; +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? */ + if ((dibp == NULL) || (dptr->flags & DEV_DIS)) /* exist, enabled? */ + continue; dno = dibp->dno; /* get device num */ - if (dibp->ini) dibp->ini (TRUE); /* gen dno template */ + if (dibp->ini) /* gen dno template */ + dibp->ini (TRUE); tplte = dibp->tplte; /* get template */ - if (tplte == NULL) tplte = dflt_tplte; /* none? use default */ + if (tplte == NULL) /* none? use default */ + tplte = dflt_tplte; 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); + 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; + if (dibp->sch >= 0) + sch_tab[t] = dibp->sch + 1; dev_tab[t] = dibp->iot; } - if (dibp->ini) dibp->ini (FALSE); /* gen int template */ + if (dibp->ini) /* gen int template */ + dibp->ini (FALSE); tplte = dibp->tplte; /* get template */ - if (tplte == NULL) tplte = dflt_tplte; /* none? use default */ + if (tplte == NULL) /* none? use default */ + tplte = dflt_tplte; for (j = dibp->irq; *tplte != TPL_END; j++, tplte++) int_tab[j] = (dno + *tplte) & DEV_MAX; } /* end for i */ diff --git a/Interdata/id_lp.c b/Interdata/id_lp.c index cb74d437..e1136a42 100644 --- a/Interdata/id_lp.c +++ b/Interdata/id_lp.c @@ -163,7 +163,8 @@ int32 t; t_stat r = SCPE_OK; lpt_sta = 0; /* clear busy */ -if (lpt_arm) SET_INT (v_LPT); /* armed? intr */ +if (lpt_arm) /* armed? intr */ + SET_INT (v_LPT); if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); t = uptr->buf; /* get character */ @@ -171,9 +172,12 @@ if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? * lpt_spnd = 0; if (lpt_bufout (uptr) != SCPE_OK) /* print */ return SCPE_IOERR; - 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 */ + if ((t == 1) || (t == LF)) /* single space */ + lpt_spc (uptr, 1); + else if (t == VT) /* VT->VFU */ + r = lpt_vfu (uptr, VT_VFU - 1); + else if (t == 0xC) /* FF->VFU */ + r = lpt_vfu (uptr, FF_VFU - 1); 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)) @@ -193,7 +197,8 @@ else if (t == CR) { /* CR? */ else if (t >= 0x20) { /* printable? */ if ((uptr->flags & UNIT_UC) && islower (t)) /* UC only? */ t = toupper (t); - if (lpt_bptr < LPT_WIDTH) lpxb[lpt_bptr++] = t; + if (lpt_bptr < LPT_WIDTH) + lpxb[lpt_bptr++] = t; } return r; } @@ -218,7 +223,8 @@ if (lpxb[0]) { /* any char left? */ } } lpt_bptr = 0; /* reset buffer */ -for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; +for (i = 0; i < LPT_WIDTH; i++) + lpxb[i] = ' '; lpxb[LPT_WIDTH] = 0; return r; } @@ -235,7 +241,8 @@ if ((ch == (FF_VFU - 1)) && VFUP (ch, lpt_vfut[0])) { /* top of form? */ 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); + for (j = 0; j < i; j++) + fputc ('\n', uptr->fileref); return SCPE_OK; } } @@ -246,9 +253,11 @@ t_stat lpt_spc (UNIT *uptr, int32 cnt) { int32 i; -if (cnt == 0) fputc ('\r', uptr->fileref); +if (cnt == 0) + fputc ('\r', uptr->fileref); else { - for (i = 0; i < cnt; i++) fputc ('\n', uptr->fileref); + for (i = 0; i < cnt; i++) + fputc ('\n', uptr->fileref); lpt_vfup = (lpt_vfup + cnt) % lpt_vful; } return SCPE_OK; @@ -263,7 +272,8 @@ 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 */ +for (i = 0; i < LPT_WIDTH; i++) /* clr buf */ + lpxb[i] = ' '; lpxb[LPT_WIDTH] = 0; CLR_INT (v_LPT); /* clearr int */ CLR_ENB (v_LPT); /* disable int */ @@ -288,30 +298,36 @@ uint32 rpt; t_stat r; char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; -if (*cptr != 0) return SCPE_ARG; +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; + 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; + 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; + if (ptr >= VFU_LNT) + return SCPE_FMT; vfubuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; +if (ptr == 0) + return SCPE_FMT; lpt_vful = ptr; lpt_vfup = 0; -for (rpt = 0; rpt < lpt_vful; rpt++) lpt_vfut[rpt] = vfubuf[rpt]; +for (rpt = 0; rpt < lpt_vful; rpt++) + lpt_vfut[rpt] = vfubuf[rpt]; return SCPE_OK; } diff --git a/Interdata/id_mt.c b/Interdata/id_mt.c index d08ccd19..fce949fa 100644 --- a/Interdata/id_mt.c +++ b/Interdata/id_mt.c @@ -1,6 +1,6 @@ /* id_mt.c: Interdata magnetic tape simulator - Copyright (c) 2001-2006, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -186,7 +186,8 @@ switch (op) { /* case IO op */ return BY; /* byte only */ case IO_RD: /* read data */ - if (mt_xfr) mt_sta = mt_sta | STA_BSY; /* xfr? set busy */ + if (mt_xfr) /* xfr? set busy */ + mt_sta = mt_sta | STA_BSY; return mt_db; /* return data */ case IO_WD: /* write data */ @@ -204,7 +205,8 @@ switch (op) { /* case IO op */ 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 */ + if (t & SET_EX) /* test for ex */ + t = t | STA_EX; return t; case IO_OC: /* command */ @@ -217,7 +219,8 @@ switch (op) { /* case IO op */ 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 */ + sim_tape_wrp (uptr))) /* and protected */ + break; 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? */ @@ -228,7 +231,8 @@ switch (op) { /* case IO op */ 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 */ + if ((f == MTC_WR) || (f == MTC_REW)) /* write, rew: bsy=0 */ + mt_sta = 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? */ @@ -271,7 +275,8 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ 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 */ + if (mt_arm[u]) /* interrupt */ + SET_INT (v_MT + u); return IORETURN (mt_stopioe, SCPE_UNATT); } @@ -279,14 +284,16 @@ if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */ uptr->UCMD = 0; /* clr cmd */ uptr->UST = uptr->UST | STA_NMTN; /* set nmtn */ mt_xfr = 0; /* clr xfr */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); sim_activate (uptr, mt_rtime); /* schedule */ return SCPE_OK; } @@ -299,7 +306,8 @@ switch (uptr->UCMD) { /* case on function */ 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 */ + if (mt_arm[u]) /* interrupt */ + SET_INT (v_MT + u); return SCPE_OK; /* For read, busy = 1 => buffer empty @@ -313,7 +321,8 @@ switch (uptr->UCMD) { /* case on function */ 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? */ + if (st == MTSE_RECE) /* rec in err? */ + mt_sta = mt_sta | STA_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 */ @@ -335,7 +344,8 @@ switch (uptr->UCMD) { /* case on function */ 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); sim_activate (uptr, mt_wtime); /* reschedule */ return SCPE_OK; } @@ -351,7 +361,8 @@ switch (uptr->UCMD) { /* case on function */ 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); sim_activate (uptr, mt_wtime); /* reschedule */ return SCPE_OK; } @@ -366,14 +377,16 @@ switch (uptr->UCMD) { /* case on function */ 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); } else r = mt_map_err (uptr, st); /* map error */ break; @@ -382,7 +395,8 @@ switch (uptr->UCMD) { /* case on function */ 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); } else r = mt_map_err (uptr, st); /* map error */ break; @@ -416,12 +430,14 @@ switch (st) { 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 */ + if (mt_arm[u]) /* set intr */ + SET_INT (v_MT + u); break; case MTSE_IOERR: /* IO error */ mt_sta = mt_sta | STA_ERR; /* set err */ - if (mt_stopioe) return SCPE_IOERR; + if (mt_stopioe) + return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ @@ -473,9 +489,11 @@ int32 u = uptr - mt_dev.units; t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->UST = STA_EOT; -if (mt_arm[u]) SET_INT (v_MT + u); +if (mt_arm[u]) + SET_INT (v_MT + u); return r; } @@ -486,10 +504,13 @@ t_stat mt_detach (UNIT* uptr) int32 u = uptr - mt_dev.units; t_stat r; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +if (!(uptr->flags & UNIT_ATT)) + return SCPE_OK; r = sim_tape_detach (uptr); -if (r != SCPE_OK) return r; -if (mt_arm[u]) SET_INT (v_MT + u); +if (r != SCPE_OK) + return r; +if (mt_arm[u]) + SET_INT (v_MT + u); uptr->UST = 0; return SCPE_OK; } @@ -511,7 +532,8 @@ extern uint16 decrom[]; extern DIB sch_dib; uint32 sch_dev; -if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */ +if (decrom[0xD5] & dec_flgs) /* AL defined? */ + return SCPE_NOFNC; 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 */ diff --git a/Interdata/id_pas.c b/Interdata/id_pas.c index ae6b7095..15ccf7e3 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-2007, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ pas Programmable asynchronous line adapter(s) + 19-Nov-08 RMS Revised for common TMXR show routines 18-Jun-07 RMS Added UNIT_IDLE flag 18-Oct-06 RMS Synced PASLA to clock 22-Nov-05 RMS Revised for new terminal processing routines @@ -111,8 +112,6 @@ t_stat paso_svc (UNIT *uptr); t_stat pas_reset (DEVICE *dptr); t_stat pas_attach (UNIT *uptr, char *cptr); t_stat pas_detach (UNIT *uptr); -t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc); int32 pas_par (int32 cmd, int32 c); t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); void pas_reset_ln (int32 i); @@ -129,8 +128,6 @@ DIB pas_dib = { d_PAS, -1, v_PAS, pas_tplte, &pas, &pas_ini }; UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE|UNIT_IDLE, 0), 0 }; -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) }, @@ -146,17 +143,18 @@ REG pas_reg[] = { }; 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 }, + &tmxr_dscln, NULL, (void *) &pas_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &pas_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &pas_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &pas_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &pas_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &pas_desc }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &pas_vlines, &tmxr_show_lines, (void *) &pas_desc }, { 0 } }; @@ -273,10 +271,12 @@ switch (op) { /* case IO op */ } else { t = pas_sta[ln] & STA_RCV; /* get static */ - if (!pas_rchp[ln]) t = t | STA_BSY; /* no char? busy */ + if (!pas_rchp[ln]) /* no char? busy */ + t = t | STA_BSY; 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 */ + if (t & SET_EX) /* test for ex */ + t = t | STA_EX; } return t; @@ -296,7 +296,8 @@ switch (op) { /* case IO op */ 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); + if (pas_rarm[ln]) + SET_INT (v_PAS + ln + ln); } } break; @@ -315,7 +316,8 @@ t_stat pasi_svc (UNIT *uptr) { int32 ln, c, out; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; sim_activate (uptr, lfc_poll); /* continue poll */ ln = tmxr_poll_conn (&pas_desc); /* look for connect */ if (ln >= 0) { /* got one? */ @@ -323,7 +325,8 @@ if (ln >= 0) { /* got one? */ ((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 */ + if (pas_rarm[ln]) /* interrupt */ + SET_INT (v_PAS + ln + ln); pas_ldsc[ln].rcve = 1; /* rcv enabled */ } tmxr_poll_rx (&pas_desc); /* poll for input */ @@ -331,8 +334,10 @@ 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 (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 */ @@ -347,7 +352,8 @@ for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */ if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) { TMLN *lp = &pas_ldsc[ln]; /* get line */ out = sim_tt_outcvt (out, TT_GET_MODE (pasl_unit[ln].flags)); - if (out >= 0) tmxr_putc_ln (lp, out); /* output char */ + if (out >= 0) /* output char */ + tmxr_putc_ln (lp, out); tmxr_poll_tx (&pas_desc); /* poll xmt */ } } /* end else normal */ @@ -355,7 +361,8 @@ for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */ } /* 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 */ + if (pas_rarm[ln]) /* intr */ + SET_INT (v_PAS + ln + ln); } } /* end for */ return SCPE_OK; @@ -386,7 +393,8 @@ if (pas_ldsc[ln].conn) { /* connected? */ } } pas_sta[ln] = pas_sta[ln] & ~STA_BSY; /* not busy */ -if (pas_xarm[ln]) SET_INT (v_PASX + ln + ln); /* set intr */ +if (pas_xarm[ln]) /* set intr */ + SET_INT (v_PASX + ln + ln); return SCPE_OK; } @@ -461,7 +469,8 @@ else { if (pas_unit.flags & UNIT_ATT) /* master att? */ sim_activate_abs (&pas_unit, lfc_poll); /* cosched with clock */ else sim_cancel (&pas_unit); /* else stop */ -for (i = 0; i < PAS_LINES; i++) pas_reset_ln (i); +for (i = 0; i < PAS_LINES; i++) + pas_reset_ln (i); return SCPE_OK; } @@ -472,7 +481,8 @@ 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 */ +if (r != SCPE_OK) /* error */ + return r; sim_activate_abs (uptr, 100); /* quick poll */ return SCPE_OK; } @@ -485,42 +495,12 @@ 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 */ +for (i = 0; i < PAS_LINES; i++) /* disable rcv */ + pas_ldsc[i].rcve = 0; sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < PAS_LINES; i++) t = t + (pas_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -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; -} - /* Change number of lines */ t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -528,12 +508,16 @@ t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = get_uint (cptr, 10, PAS_LINES, &r); -if ((r != SCPE_OK) || (newln == PAS_ENAB)) return r; -if (newln == 0) return SCPE_ARG; +if ((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; + 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++) { diff --git a/Interdata/id_pt.c b/Interdata/id_pt.c index 0a7da165..27cc0c85 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-2005, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -135,7 +135,8 @@ switch (op) { /* case IO op */ } else { /* not active */ pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */ - if (pt_arm) SET_INT (v_PT); /* no, set int */ + if (pt_arm) /* no, set int */ + SET_INT (v_PT); } } if (pt_rd) { /* reader? */ @@ -158,12 +159,14 @@ switch (op) { /* case IO op */ 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 */ + if (pt_rd) /* set busy */ + pt_sta = pt_sta | STA_BSY; 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 */ + if (!pt_rd) /* set busy */ + pt_sta = pt_sta | STA_BSY; sim_activate (&pt_unit[PTP], pt_unit[PTP].wait); break; @@ -173,7 +176,8 @@ switch (op) { /* case IO op */ 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 */ + if (t & SET_EX) /* test for EX */ + t = t | STA_EX; return t; } @@ -190,14 +194,17 @@ 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? */ + if (pt_arm) /* if armed, intr */ + SET_INT (v_PT); + if (pt_chp) /* overrun? */ + pt_sta = pt_sta | STA_OVR; } 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"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); @@ -206,7 +213,8 @@ if ((temp = getc (uptr->fileref)) == EOF) { /* error? */ } uptr->buf = temp & DMASK8; /* store char */ uptr->pos = uptr->pos + 1; /* incr pos */ -if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */ +if (pt_slew) /* slew? continue */ + sim_activate (uptr, uptr->wait); return SCPE_OK; } @@ -216,7 +224,8 @@ 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 (pt_arm) /* if armed, intr */ + SET_INT (v_PT); } if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */ perror ("PTP I/O error"); @@ -339,22 +348,30 @@ uint32 i, lo, hi, cs; char *tptr; extern DEVICE cpu_dev; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; +if ((cptr == NULL) || (*cptr == 0)) + return SCPE_2FARG; tptr = get_range (NULL, cptr, &lo, &hi, cpu_dev.aradix, 0xFFFF, 0); -if ((tptr == NULL) || (lo < INTSVT)) return SCPE_ARG; -if (*tptr != 0) return SCPE_2MARG; -for (i = lo, cs = 0; i <= hi; i++) cs = cs ^ IOReadB (i); +if ((tptr == NULL) || (lo < INTSVT)) + return SCPE_ARG; +if (*tptr != 0) + return SCPE_2MARG; +for (i = lo, cs = 0; i <= hi; i++) + cs = cs ^ IOReadB (i); IOWriteBlk (LOAD_START, LOAD_LEN, load_rom); IOWriteB (LOAD_LO, (lo >> 8) & 0xFF); IOWriteB (LOAD_LO + 1, lo & 0xFF); IOWriteB (LOAD_HI, (hi >> 8) & 0xFF); IOWriteB (LOAD_HI + 1, hi & 0xFF); IOWriteB (LOAD_CS, cs & 0xFF); -for (i = 0; i < LOAD_LDR; i++) fputc (0, of); +for (i = 0; i < LOAD_LDR; i++) + fputc (0, of); for (i = LOAD_START; i < (LOAD_START + LOAD_LEN); i++) fputc (IOReadB (i), of); -for (i = 0; i < LOAD_LDR; i++) fputc (0, of); -for (i = lo; i <= hi; i++) fputc (IOReadB (i), of); -for (i = 0; i < LOAD_LDR; i++) fputc (0, of); +for (i = 0; i < LOAD_LDR; i++) + fputc (0, of); +for (i = lo; i <= hi; i++) + fputc (IOReadB (i), of); +for (i = 0; i < LOAD_LDR; i++) + fputc (0, of); return SCPE_OK; } diff --git a/Interdata/id_tt.c b/Interdata/id_tt.c index c446ed9c..e56f4c7c 100644 --- a/Interdata/id_tt.c +++ b/Interdata/id_tt.c @@ -1,6 +1,6 @@ /* id_tt.c: Interdata teletype - Copyright (c) 2000-2007, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -143,7 +143,8 @@ switch (op) { /* case IO op */ 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 */ + if (tt_arm) /* req intr */ + SET_INT (v_TT); } else { tt_sta = STA_BSY; /* busy = 1 */ @@ -155,18 +156,21 @@ switch (op) { /* case IO op */ case IO_RD: /* read */ tt_chp = 0; /* clear pend */ - if (tt_rd) tt_sta = (tt_sta | STA_BSY) & ~STA_OVR; + 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 */ + if (!tt_rd) /* set busy */ + tt_sta = tt_sta | STA_BSY; 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 */ + if (t & SET_EX) /* test for EX */ + t = t | STA_EX; return t; } @@ -181,11 +185,14 @@ int32 out, temp; sim_activate (uptr, KBD_WAIT (uptr->wait, lfc_poll)); /* continue poll */ tt_sta = tt_sta & ~STA_BRK; /* clear break */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return temp; 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 */ + if (tt_arm) /* if armed, intr */ + SET_INT (v_TT); + if (tt_chp) /* got char? overrun */ + tt_sta = tt_sta | STA_OVR; } tt_chp = 1; /* char pending */ out = temp & 0x7F; /* echo is 7B */ @@ -219,7 +226,8 @@ if (ch >= 0) { } if (!tt_rd) { /* write mode? */ tt_sta = tt_sta & ~STA_BSY; /* clear busy */ - if (tt_arm) SET_INT (v_TT); /* if armed, intr */ + if (tt_arm) /* if armed, intr */ + SET_INT (v_TT); } uptr->pos = uptr->pos + 1; /* incr count */ return SCPE_OK; @@ -229,7 +237,8 @@ return SCPE_OK; t_stat tt_reset (DEVICE *dptr) { -if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */ +if (dptr->flags & DEV_DIS) /* dis? cancel poll */ + sim_cancel (&tt_unit[TTI]); else sim_activate_abs (&tt_unit[TTI], KBD_WAIT (tt_unit[TTI].wait, lfc_poll)); sim_cancel (&tt_unit[TTO]); /* cancel output */ tt_rd = tt_fdpx = 1; /* read, full duplex */ @@ -246,7 +255,8 @@ return SCPE_OK; t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { tt_unit[TTO].flags = (tt_unit[TTO].flags & ~TT_MODE) | val; -if (val == TT_MODE_7P) val = TT_MODE_7B; +if (val == TT_MODE_7P) + val = TT_MODE_7B; tt_unit[TTI].flags = (tt_unit[TTI].flags & ~TT_MODE) | val; return SCPE_OK; } @@ -255,11 +265,13 @@ return SCPE_OK; t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (tt_dev.flags & DEV_DIS) return SCPE_NOFNC; +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 */ + if (tt_arm) /* if armed, intr */ + SET_INT (v_TT); } sim_cancel (&tt_unit[TTI]); /* restart TT poll */ sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* so brk is seen */ diff --git a/Interdata/id_ttp.c b/Interdata/id_ttp.c index 24ed0d32..e580d303 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-2007, Robert M. Supnik + Copyright (c) 2000-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -151,8 +151,10 @@ switch (op) { /* case IO op */ 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 */ + if (!ttp_kchp) /* no char? busy */ + t = t | STA_BSY; + if (t & SET_EX) /* test for ex */ + t = t | STA_EX; } return t; @@ -179,10 +181,13 @@ int32 c, out; sim_activate (uptr, KBD_WAIT (uptr->wait, lfc_poll)); /* continue poll */ ttp_sta = ttp_sta & ~STA_FR; /* clear break */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; 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 (ttp_kchp) /* overrun? */ + ttp_sta = ttp_sta | STA_OVR; +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 */ @@ -197,7 +202,8 @@ else { ttp_kchp = 1; /* char pending */ if (ttp_cmd & CMD_ECHO) { out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags)); - if (c >= 0) sim_putchar (out); + if (c >= 0) + sim_putchar (out); ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1; } } @@ -219,7 +225,8 @@ if (c >= 0) { } } ttp_sta = ttp_sta & ~STA_BSY; /* not busy */ -if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */ +if (ttp_tarm) /* set intr */ + SET_INT (v_TTP + 1); uptr->pos = uptr->pos + 1; /* incr count */ return SCPE_OK; } @@ -228,7 +235,8 @@ return SCPE_OK; t_stat ttp_reset (DEVICE *dptr) { -if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]); +if (dptr->flags & DEV_DIS) + sim_cancel (&ttp_unit[TTI]); else sim_activate_abs (&ttp_unit[TTI], KBD_WAIT (ttp_unit[TTI].wait, lfc_poll)); sim_cancel (&ttp_unit[TTO]); CLR_INT (v_TTP); /* clear int */ @@ -247,7 +255,8 @@ return SCPE_OK; t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~TT_MODE) | val; -if (val == TT_MODE_7P) val = TT_MODE_7B; +if (val == TT_MODE_7P) + val = TT_MODE_7B; ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~TT_MODE) | val; return SCPE_OK; } @@ -256,9 +265,11 @@ return SCPE_OK; t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (ttp_dev.flags & DEV_DIS) return SCPE_NOFNC; +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 */ +if (ttp_karm) /* if armed, intr */ + SET_INT (v_TTP); 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 d660e178..d94b2a65 100644 --- a/Interdata/id_uvc.c +++ b/Interdata/id_uvc.c @@ -1,6 +1,6 @@ /* id_uvc.c: Interdata universal clock - Copyright (c) 2001-2007, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -190,7 +190,8 @@ switch (op) { /* case IO op */ case IO_RD: /* read */ t = pic_rd_cic (); /* get cic */ - if (pic_rdp) t = t & DMASK8; /* 2nd? get lo */ + if (pic_rdp) /* 2nd? get lo */ + t = t & DMASK8; else t = (t >> 8) & DMASK8; /* 1st? get hi */ pic_rdp = pic_rdp ^ 1; /* flip byte ptr */ return t; @@ -201,7 +202,8 @@ switch (op) { /* case IO op */ break; case IO_WD: /* write */ - if (pic_wdp) pic_db = (pic_db & 0xFF00) | dat; + 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; @@ -222,7 +224,8 @@ switch (op) { /* case IO op */ 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? */ + if (pic_ric & PIC_RATE) /* any rate? */ + pic_sched (TRUE); } /* end if start */ break; } /* end case */ @@ -236,16 +239,20 @@ t_stat pic_svc (UNIT *uptr) { t_bool rate_chg = FALSE; -if (pic_cnti) pic_cic = 0; /* one shot? */ +if (pic_cnti) /* one shot? */ + pic_cic = 0; 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 (pic_wdp) /* broken wr? set flag */ + pic_ovf = 1; + if (pic_arm) /* if armed, intr */ + SET_INT (v_PIC); 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_ric & PIC_RATE) == 0) + return SCPE_OK; } pic_sched (rate_chg); return SCPE_OK; @@ -269,14 +276,16 @@ 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 */ + if (strt) /* init or */ + t = sim_rtcn_init (pic_time[3], TMR_PIC); 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 */ + if (t == 1) /* for diagn */ + t++; } sim_activate (&pic_unit, t); /* activate */ return; @@ -290,7 +299,8 @@ 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 */ + if (delta >= ((uint32) pic_cic)) /* cap value */ + return 0; return pic_cic - delta; } return pic_cic; @@ -357,8 +367,10 @@ return SCPE_OK; t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 100) && (val != 120)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 100) && (val != 120)) + return SCPE_IERR; lfc_tps = val; return SCPE_OK; } diff --git a/LGP/lgp_cpu.c b/LGP/lgp_cpu.c index 57235c42..87e040e8 100644 --- a/LGP/lgp_cpu.c +++ b/LGP/lgp_cpu.c @@ -1,6 +1,6 @@ /* lgp_cpu.c: LGP CPU simulator - Copyright (c) 2004-2005, Robert M. Supnik + Copyright (c) 2004-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -279,7 +279,8 @@ 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 */ + if (!OVF) /* ovf off? skip */ + PC = (PC + 1) & AMASK; else OVF = 0; /* on? reset */ } @@ -287,7 +288,8 @@ if (lgp21_sov) { /* stop sense pending? * do { if (sim_interval <= 0) { /* check clock queue */ - if (r = sim_process_event ()) break; + if (r = sim_process_event ()) + break; } if (delay > 0) { /* delay to next instr */ @@ -374,7 +376,7 @@ switch (op) { /* case on opcode */ case OP_T: /* conditional transfer */ if ((A & SIGN) || /* A < 0 or */ - ((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */ + ((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */ PCQ_ENTRY; PC = ea; /* transfer */ } @@ -416,7 +418,8 @@ switch (op) { /* case on opcode */ case OP_D: /* divide */ dat = Read (ea); /* get operand */ - if (Div32 (A, dat, &A)) ovf_this_cycle = TRUE; /* divide; overflow? */ + if (Div32 (A, dat, &A)) /* divide; overflow? */ + ovf_this_cycle = TRUE; delay = I_delay (opc, ea, op); break; @@ -431,7 +434,8 @@ switch (op) { /* case on opcode */ case OP_P: /* output */ if (Q_LGP21) { /* LGP-21 */ ch = A >> 26; /* char, 6b */ - if (ir & SIGN) ch = (ch & 0x3C) | 2; /* 4b? convert */ + if (ir & SIGN) /* 4b? convert */ + ch = (ch & 0x3C) | 2; dev = I_GETTK (ir); /* device select */ } else { /* LGP-30 */ @@ -468,7 +472,8 @@ switch (op) { /* case on opcode */ ((ea & 0x100) && !bp4) || /* or if */ ((ir & SIGN) && !OVF)) /* ovf sel and off */ PC = (PC + 1) & AMASK; - if (ir & SIGN) OVF = 0; /* -Z? clr overflow */ + if (ir & SIGN) /* -Z? clr overflow */ + OVF = 0; } else { /* stop */ lgp21_sov = (ir & SIGN)? 1: 0; /* pending sense? */ @@ -476,12 +481,14 @@ switch (op) { /* case on opcode */ } } else { /* LGP-30 */ - if (out_done) out_done = 0; /* P complete? */ + if (out_done) /* P complete? */ + out_done = 0; 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 if (out_strt) /* P pending? stall */ + reason = STOP_STALL; else reason = STOP_STOP; /* no, stop */ } delay = I_delay (sim_grtime (), ea, op); /* next instruction */ @@ -489,7 +496,8 @@ switch (op) { /* case on opcode */ } if (ovf_this_cycle) { - if (Q_LGP21) OVF = 1; /* LGP-21? set OVF */ + if (Q_LGP21) /* LGP-21? set OVF */ + OVF = 1; else reason = STOP_OVF; /* LGP-30? stop */ } return reason; @@ -512,7 +520,8 @@ return; uint32 shift_in (uint32 a, uint32 dat, uint32 sh4) { -if (sh4) return (((a << 4) | (dat >> 2)) & DMASK); +if (sh4) + return (((a << 4) | (dat >> 2)) & DMASK); return (((a << 6) | dat) & DMASK); } @@ -524,7 +533,8 @@ uint32 sgn = a ^ b; uint32 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; if ((a == 0) || (b == 0)) { /* zero argument? */ - if (low) *low = 0; + if (low) + *low = 0; return 0; } a = ABS (a); @@ -539,14 +549,17 @@ 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 */ +if (rmid1 < rlo) /* carry? incr hi */ + rhi = rhi + 1; rmid2 = (rmid1 + (rmid2 << 16)) & M32; /* add mid2 to to */ -if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ +if (rmid2 < rmid1) /* carry? incr hi */ + rhi = rhi + 1; if (sgn & SIGN) { /* result negative? */ rmid2 = NEG (rmid2); /* negate */ rhi = (~rhi + (rmid2 == 0)) & M32; } -if (low) *low = rmid2; /* low result */ +if (low) /* low result */ + *low = rmid2; return rhi & M32; } @@ -559,7 +572,8 @@ uint32 i, quo; dvd = ABS (dvd); dvr = ABS (dvr); -if (dvd >= dvr) return TRUE; +if (dvd >= dvr) + return TRUE; for (i = quo = 0; i < 31; i++) { /* 31 iterations */ quo = quo << 1; /* shift quotient */ dvd = dvd << 1; /* shift dividend */ @@ -569,8 +583,10 @@ for (i = quo = 0; i < 31; i++) { /* 31 iterations */ } } quo = (quo + 1) & MMASK; /* round low bit */ -if (sgn & SIGN) quo = NEG (quo); /* result -? */ -if (q) *q = quo; /* return quo */ +if (sgn & SIGN) /* result -? */ + quo = NEG (quo); +if (q) /* return quo */ + *q = quo; return FALSE; /* no overflow */ } @@ -599,10 +615,12 @@ else { opdelta = (oprp - curp + NSC_30) & SCMASK_30; } if (tmax == 0) { /* skip ea calc? */ - if (pcdelta >= tmin) return pcdelta - 1; /* new PC >= min? */ + if (pcdelta >= tmin) /* new PC >= min? */ + return pcdelta - 1; return pcdelta + nsc - 1; } -if ((opdelta >= tmin) && (opdelta <= tmax)) return pcdelta - 1; +if ((opdelta >= tmin) && (opdelta <= tmax)) + return pcdelta - 1; return pcdelta + nsc - 1; } @@ -619,7 +637,8 @@ lgp21_sov = 0; delay = 0; lgp_vm_init (); pcq_r = find_reg ("CQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -629,7 +648,8 @@ return SCPE_OK; t_stat cpu_set_30opt (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (Q_LGP21) return SCPE_ARG; +if (Q_LGP21) + return SCPE_ARG; return SCPE_OK; } @@ -637,9 +657,12 @@ return SCPE_OK; t_stat cpu_set_30opt_i (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (Q_LGP21 || (cptr == NULL)) return SCPE_ARG; -if (strcmp (cptr, "TTI") == 0) uptr->flags = uptr->flags & ~UNIT_INPT; -else if (strcmp (cptr, "PTR") == 0) uptr->flags = uptr->flags | UNIT_INPT; +if (Q_LGP21 || (cptr == NULL)) + return SCPE_ARG; +if (strcmp (cptr, "TTI") == 0) + uptr->flags = uptr->flags & ~UNIT_INPT; +else if (strcmp (cptr, "PTR") == 0) + uptr->flags = uptr->flags | UNIT_INPT; else return SCPE_ARG; return SCPE_OK; } @@ -648,9 +671,12 @@ return SCPE_OK; t_stat cpu_set_30opt_o (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (Q_LGP21 || (cptr == NULL)) return SCPE_ARG; -if (strcmp (cptr, "TTO") == 0) uptr->flags = uptr->flags & ~UNIT_OUTPT; -else if (strcmp (cptr, "PTP") == 0) uptr->flags = uptr->flags | UNIT_OUTPT; +if (Q_LGP21 || (cptr == NULL)) + return SCPE_ARG; +if (strcmp (cptr, "TTO") == 0) + uptr->flags = uptr->flags & ~UNIT_OUTPT; +else if (strcmp (cptr, "PTP") == 0) + uptr->flags = uptr->flags | UNIT_OUTPT; else return SCPE_ARG; return SCPE_OK; } @@ -659,7 +685,8 @@ return SCPE_OK; t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val) uptr->flags = uptr->flags & ~(UNIT_IN4B|UNIT_INPT|UNIT_OUTPT); +if (val) + uptr->flags = uptr->flags & ~(UNIT_IN4B|UNIT_INPT|UNIT_OUTPT); return reset_all (0); } @@ -668,8 +695,10 @@ return reset_all (0); t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc) { fputs (Q_LGP21? "LGP-21": "LGP-30", st); -if (uptr->flags & UNIT_TTSS_D) fputs (", track/sector", st); -if (uptr->flags & UNIT_LGPH_D) fputs (", LGP hex", st); +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); @@ -683,8 +712,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = Read (addr); +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = Read (addr); return SCPE_OK; } @@ -692,7 +723,8 @@ 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; Write (addr, val); return SCPE_OK; } @@ -706,12 +738,14 @@ t_stat r; if (cptr) { inst = get_uint (cptr, 16, DMASK, &r); - if (r != SCPE_OK) return 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; + if (r = sim_process_event ()) + return r; } return r; } @@ -725,7 +759,8 @@ t_stat r; if (cptr) { inst = get_uint (cptr, 16, DMASK, &r); - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; IR = inst; } else IR = A; diff --git a/LGP/lgp_defs.h b/LGP/lgp_defs.h index d8b2d677..fe54057d 100644 --- a/LGP/lgp_defs.h +++ b/LGP/lgp_defs.h @@ -1,6 +1,6 @@ /* lgp_defs.h: LGP simulator definitions - Copyright (c) 2004-2005, Robert M. Supnik + Copyright (c) 2004-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/LGP/lgp_stddev.c b/LGP/lgp_stddev.c index 080e4aca..2dba6cc1 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-2005, Robert M Supnik + Copyright (c) 2004-2008, Robert 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,6 +27,8 @@ tto typewriter output (printer and punch) ptr high speed reader ptpp high speed punch + + 26-Nov-2008 RMS Changed encode character from # to ! */ #include "lgp_defs.h" @@ -103,7 +105,7 @@ const int32 ascii_to_flex[128] = { 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, + -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 @@ -309,7 +311,8 @@ switch (dev) { /* case on device */ break; case DEV_TT: /* tti/ttr */ - if (Q_MANI) sim_putchar ('`'); /* manual input? */ + if (Q_MANI) /* manual input? */ + sim_putchar ('`'); else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */ break; } @@ -318,13 +321,15 @@ 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 (Q_LGP21 && out_strt) /* LGP-21? must be idle */ + return STOP_STALL; 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 || Q_INPT) /* LGP-21 or PTR? start */ + op_i_strt (dev); } switch (dev) { /* case on device */ @@ -364,7 +369,8 @@ 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? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */ if (flex > 0) { /* it's a typewriter... */ write_tto (flex); /* always echos */ @@ -373,7 +379,8 @@ if (flex > 0) { /* it's a typewriter... } 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? */ + if (flex == FLEX_CSTOP) /* conditional stop? */ + inp_done = 1; else tti_rdy = 1; /* no, set ready */ tti_buf = flex; /* save char */ uptr->pos = uptr->pos + 1; @@ -387,9 +394,11 @@ t_stat ttr_svc (UNIT *uptr) { t_stat r; -if (r = read_reader (uptr, ttr_stopioe, (int32 *) &tti_buf)) return 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? */ + (tti_buf == FLEX_CSTOP)) /* cond stop? */ + inp_done = 1; else { tti_rdy = 1; /* no, set ready */ sim_activate (uptr, tt_wait); /* cont reading */ @@ -406,8 +415,10 @@ 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? */ +if (r = read_reader (uptr, ptr_stopioe, &uptr->buf)) + return r; +if (uptr->buf == FLEX_CSTOP) /* cond stop? */ + inp_done = 1; else { ptr_rdy = 1; /* no, set ready */ sim_activate (uptr, uptr->wait); /* cont reading */ @@ -490,7 +501,8 @@ if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ do { if ((ch = getc (uptr->fileref)) == EOF) { /* read char */ if (feof (uptr->fileref)) { /* err or eof? */ - if (stop) printf ("Reader end of file\n"); + if (stop) + printf ("Reader end of file\n"); else return SCPE_OK; } else perror ("Reader I/O error"); @@ -499,12 +511,13 @@ do { } if (uptr->flags & UNIT_FLEX) /* transposed flex? */ flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */ - else if (ch == '#') { /* encoded? */ + 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"); + if (stop) + printf ("Reader end of file\n"); else return SCPE_OK; } else perror ("Reader I/O error"); @@ -526,13 +539,17 @@ 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 */ +if (flex == FLEX_UC) /* UC? set state */ + tto_uc = 1; +else if (flex == FLEX_LC) /* LC? set state */ + tto_uc = 0; else { - if (flex == FLEX_BS) ch = '\b'; /* backspace? */ + if (flex == FLEX_BS) /* backspace? */ + ch = '\b'; 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 */ + if (r = sim_putchar_s (ch)) /* write char */ + return r; tto_unit[0].pos = tto_unit[0].pos + 1; if (flex == FLEX_CR) { /* cr? */ sim_putchar ('\n'); /* add lf */ @@ -550,8 +567,9 @@ 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 (c >= 0) /* valid? */ + sta = fputc (c, uptr->fileref); +else sta = fprintf (uptr->fileref, "!%02d", flex); /* no, encode */ if (sta == EOF) { /* error? */ perror ("Punch I/O error"); /* error? */ clearerr (uptr->fileref); @@ -601,7 +619,8 @@ t_stat tap_attach (UNIT *uptr, char *cptr) { t_stat r; -if ((r = attach_unit (uptr,cptr)) != SCPE_OK) return 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; @@ -613,7 +632,8 @@ return SCPE_OK; t_stat tap_attable (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATTABLE) return SCPE_OK; +if (uptr->flags & UNIT_ATTABLE) + return SCPE_OK; return SCPE_NOFNC; } @@ -622,7 +642,8 @@ 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; + if ((tti_unit[1].flags & UNIT_ATT) == 0) + return SCPE_UNATT; sim_activate (&tti_unit[1], tt_wait); } else sim_cancel (&tti_unit[1]); @@ -636,15 +657,18 @@ t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc) int32 cnt; t_stat r; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; +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; + 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; + if (r != SCPE_OK) + return r; } return SCPE_OK; } @@ -653,7 +677,9 @@ return SCPE_OK; t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (inp_strt) inp_done = 1; -else if (out_strt) out_done = 1; +if (inp_strt) + inp_done = 1; +else if (out_strt) + out_done = 1; return SCPE_OK; } diff --git a/LGP/lgp_sys.c b/LGP/lgp_sys.c index e52c5ff1..f445e202 100644 --- a/LGP/lgp_sys.c +++ b/LGP/lgp_sys.c @@ -1,6 +1,6 @@ /* lgp_sys.c: LGP-30 simulator interface - Copyright (c) 2004-2005, Robert M Supnik + Copyright (c) 2004-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -108,8 +108,10 @@ while ((c = fgetc (fi)) != EOF) { 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; + (flex == FLEX_BS) || (flex < 0)) + continue; + if (flex == FLEX_CSTOP) + return SCPE_OK; *wd = (*wd << 4) | ((flex >> 2) & 0xF); } return SCPE_FMT; @@ -125,10 +127,12 @@ n1 = (wd >> 12) & 0xF; n2 = (wd >> 8) & 0xF; n3 = (wd >> 4) & 0xF; n4 = wd & 0xF; -if ((n2 > 9) || (n4 > 9)) return SCPE_ARG; +if ((n2 > 9) || (n4 > 9)) + return SCPE_ARG; tr = (n1 * 10) + n2; sc = (n3 * 10) + n4; -if ((tr >= NTK_30) || (sc >= NSC_30)) return SCPE_ARG; +if ((tr >= NTK_30) || (sc >= NSC_30)) + return SCPE_ARG; *ad = (tr * NSC_30) + sc; return SCPE_OK; } @@ -141,7 +145,8 @@ 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 */ + if (load_getw (fi, &wd)) /* get ctrl word */ + break; cmd = (wd >> 28) & 0xF; /* get <0:3> */ switch (cmd) { /* decode <0:3> */ @@ -149,22 +154,28 @@ for (;;) { /* until stopped */ return SCPE_FMT; case 0x3: /* ; start fill */ - if (load_geta (wd, &origin)) return SCPE_FMT; /* origin = addr */ + if (load_geta (wd, &origin)) /* origin = addr */ + return SCPE_FMT; break; case 0x4: /* / set modifier */ - if (load_geta (wd, &amod)) return SCPE_FMT; /* modifier = addr */ + if (load_geta (wd, &amod)) /* modifier = addr */ + return SCPE_FMT; break; case 0x5: /* . transfer */ - if (load_geta (wd, &PC)) return SCPE_FMT; /* PC = addr */ + if (load_geta (wd, &PC)) /* PC = addr */ + return SCPE_FMT; 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; + if (load_geta (wd, &cnt)) /* count = addr */ + return SCPE_FMT; + if ((cnt == 0) || (cnt > 63)) + return SCPE_FMT; while (cnt--) { /* fill hex words */ - if (load_getw (fi, &wd)) return SCPE_FMT; + if (load_getw (fi, &wd)) + return SCPE_FMT; Write (origin, wd); origin = (origin + 1) & AMASK; } @@ -175,22 +186,27 @@ for (;;) { /* until stopped */ 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; + (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; + 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; */ + 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 (load_geta (wd, &ad)) /* get address */ + return SCPE_FMT; if ((wd & 0x00F00000) != 0x00900000) /* if not x, */ ad = (ad + amod) & AMASK; /* modify */ wd = (wd & (SIGN|I_OP)) + (ad << I_V_EA); /* instruction */ @@ -265,22 +281,26 @@ uint32 inst, op, ea; inst = val[0]; if (sw & SWMASK ('A')) { /* alphabetic? */ - if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG; + 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; + 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 (uptr && (uptr != &cpu_unit)) /* must be CPU */ + return SCPE_ARG; 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); + if (inst & SIGN) + fputc ('-', of); fprintf (of, "%c ", opcode[op]); lgp_fprint_addr (of, sim_devices[0], ea); return SCPE_OK; @@ -314,33 +334,41 @@ 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)) /* absorb spaces */ + cptr++; if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { - if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG; + 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; + 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 (uptr && (uptr != &cpu_unit)) /* must be CPU */ + return SCPE_ARG; +if (!parse_sym_m (cptr, val, sw)) /* symbolic parse? */ + return SCPE_OK; 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 (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; + if (*cptr == 0) + return SCPE_OK; } return SCPE_ARG; } @@ -358,7 +386,8 @@ if (*cptr == '-') { } else sgn = 0; cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -if (gbuf[1] != 0) return SCPE_ARG; +if (gbuf[1] != 0) + return SCPE_ARG; if (tptr = strchr (opcode, gbuf[0])) val[0] = ((tptr - opcode) << I_V_OP) | sgn; /* merge opcode */ else return SCPE_ARG; @@ -367,6 +396,7 @@ 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 */ -if (*cptr != 0) return SCPE_2MARG; +if (*cptr != 0) + return SCPE_2MARG; return SCPE_OK; } diff --git a/NOVA/nova_clk.c b/NOVA/nova_clk.c index 8a384797..d0c888cd 100644 --- a/NOVA/nova_clk.c +++ b/NOVA/nova_clk.c @@ -167,8 +167,10 @@ return SCPE_OK; t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; clk_tps[0] = val; return SCPE_OK; } diff --git a/NOVA/nova_cpu.c b/NOVA/nova_cpu.c index 58cc8463..136163aa 100644 --- a/NOVA/nova_cpu.c +++ b/NOVA/nova_cpu.c @@ -240,7 +240,8 @@ #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 STK_CHECK(x,y) if (((x) & 0377) < (y)) \ + int_req = int_req | INT_STK #define IND_STEP(x) M[x] & A_IND; /* return next level indicator */ \ if ( ((x) <= AUTO_TOP) && ((x) >= AUTO_INC) ) \ if ( (x) < AUTO_DEC ) \ @@ -422,7 +423,8 @@ t_stat reason; /* Restore register state */ -if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */ +if (build_devtab () != SCPE_OK) /* build dispatch */ + return SCPE_IERR; PC = saved_PC & AMASK; /* load local PC */ C = C & CBIT; mask_out (pimask); /* reset int system */ @@ -433,7 +435,8 @@ reason = 0; while (reason == 0) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ - if ( (reason = sim_process_event ()) ) break; + if ( (reason = sim_process_event ()) ) + break; } if (int_req > INT_PENDING) { /* interrupt or exception? */ @@ -561,22 +564,28 @@ while (reason == 0) { /* loop until halted */ INCREMENT_PC ; break; case 2: /* SZC */ - if (src < CBIT) INCREMENT_PC ; + if (src < CBIT) + INCREMENT_PC ; break; case 3: /* SNC */ - if (src >= CBIT) INCREMENT_PC ; + if (src >= CBIT) + INCREMENT_PC ; break; case 4: /* SZR */ - if ((src & DMASK) == 0) INCREMENT_PC ; + if ((src & DMASK) == 0) + INCREMENT_PC ; break; case 5: /* SNR */ - if ((src & DMASK) != 0) INCREMENT_PC ; + if ((src & DMASK) != 0) + INCREMENT_PC ; break; case 6: /* SEZ */ - if (src <= CBIT) INCREMENT_PC ; + if (src <= CBIT) + INCREMENT_PC ; break; case 7: /* SBN */ - if (src > CBIT) INCREMENT_PC ; + if (src > CBIT) + INCREMENT_PC ; break; } /* end switch skip */ if ((IR & I_NLD) == 0) { /* load? */ @@ -595,15 +604,18 @@ while (reason == 0) { /* loop until halted */ case 0: /* page zero */ break; case 1: /* PC relative */ - if (MA & DISPSIGN) MA = 0177400 | MA; + if (MA & DISPSIGN) + MA = 0177400 | MA; MA = (MA + PC - 1) & AMASK; break; case 2: /* AC2 relative */ - if (MA & DISPSIGN) MA = 0177400 | MA; + if (MA & DISPSIGN) + MA = 0177400 | MA; MA = (MA + AC[2]) & AMASK; break; case 3: /* AC3 relative */ - if (MA & DISPSIGN) MA = 0177400 | MA; + if (MA & DISPSIGN) + MA = 0177400 | MA; MA = (MA + AC[3]) & AMASK; break; } /* end switch mode */ @@ -633,13 +645,17 @@ while (reason == 0) { /* loop until halted */ break; case 002: /* ISZ */ src = (M[MA] + 1) & DMASK; - if (MEM_ADDR_OK(MA)) M[MA] = src; - if (src == 0) INCREMENT_PC ; + if (MEM_ADDR_OK(MA)) + M[MA] = src; + if (src == 0) + INCREMENT_PC ; break; case 003: /* DSZ */ src = (M[MA] - 1) & DMASK; - if (MEM_ADDR_OK(MA)) M[MA] = src; - if (src == 0) INCREMENT_PC ; + if (MEM_ADDR_OK(MA)) + M[MA] = src; + if (src == 0) + INCREMENT_PC ; break; case 004: /* LDA 0 */ AC[0] = M[MA]; @@ -654,16 +670,20 @@ while (reason == 0) { /* loop until halted */ AC[3] = M[MA]; break; case 010: /* STA 0 */ - if (MEM_ADDR_OK(MA)) M[MA] = AC[0]; + if (MEM_ADDR_OK(MA)) + M[MA] = AC[0]; break; case 011: /* STA 1 */ - if (MEM_ADDR_OK(MA)) M[MA] = AC[1]; + if (MEM_ADDR_OK(MA)) + M[MA] = AC[1]; break; case 012: /* STA 2 */ - if (MEM_ADDR_OK(MA)) M[MA] = AC[2]; + if (MEM_ADDR_OK(MA)) + M[MA] = AC[2]; break; case 013: /* STA 3 */ - if (MEM_ADDR_OK(MA)) M[MA] = AC[3]; + if (MEM_ADDR_OK(MA)) + M[MA] = AC[3]; break; } /* end switch */ } /* end mem ref */ @@ -713,8 +733,10 @@ while (reason == 0) { /* loop until halted */ case ioNIO: /* frame ptr */ if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) FP = AC[dstAC] & AMASK ; - if (pulse == iopC) AC[dstAC] = FP & AMASK ; + if (pulse == iopN) + FP = AC[dstAC] & AMASK ; + if (pulse == iopC) + AC[dstAC] = FP & AMASK ; } break; @@ -726,15 +748,20 @@ while (reason == 0) { /* loop until halted */ else if (cpu_unit.flags & UNIT_STK) /* if Nova 3 this is really a SAV... 2007-Jun-01, BKR */ { SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[0]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[1]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[2]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; + if (MEM_ADDR_OK (SP)) + M[SP] = FP; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | (AC[3] & AMASK); + if (MEM_ADDR_OK (SP)) + M[SP] = (C >> 1) | (AC[3] & AMASK); AC[3] = FP = SP & AMASK; STK_CHECK (SP, 5); } @@ -746,8 +773,10 @@ while (reason == 0) { /* loop until halted */ case ioDOA: /* stack ptr */ if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) SP = AC[dstAC] & AMASK; - if (pulse == iopC) AC[dstAC] = SP & AMASK; + if (pulse == iopN) + SP = AC[dstAC] & AMASK; + if (pulse == iopC) + AC[dstAC] = SP & AMASK; } break; @@ -755,13 +784,15 @@ while (reason == 0) { /* loop until halted */ if (cpu_unit.flags & UNIT_STK) { if (pulse == iopN) { /* push (PSHA) */ SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[dstAC]; STK_CHECK (SP, 1); } if ((pulse == iopS) && /* Nova 4 pshn (PSHN) */ (cpu_unit.flags & UNIT_BYT)) { SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[dstAC]; if ( (SP & 0xFFFF) > (M[042] & 0xFFFF) ) { int_req = int_req | INT_STK ; @@ -787,15 +818,20 @@ while (reason == 0) { /* loop until halted */ else if (cpu_unit.flags & UNIT_STK) /* if Nova 3 this is really a SAV... 2007-Jun-01, BKR */ { SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[0]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[1]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[2]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; + if (MEM_ADDR_OK (SP)) + M[SP] = FP; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | (AC[3] & AMASK); + if (MEM_ADDR_OK (SP)) + M[SP] = (C >> 1) | (AC[3] & AMASK); AC[3] = FP = SP & AMASK; STK_CHECK (SP, 5); } @@ -805,15 +841,20 @@ while (reason == 0) { /* loop until halted */ if (cpu_unit.flags & UNIT_STK) { if (pulse == iopN) { /* save */ SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[0]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[1]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[2]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; + if (MEM_ADDR_OK (SP)) + M[SP] = FP; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | (AC[3] & AMASK); + if (MEM_ADDR_OK (SP)) + M[SP] = (C >> 1) | (AC[3] & AMASK); AC[3] = FP = SP & AMASK; STK_CHECK (SP, 5); } @@ -838,15 +879,20 @@ while (reason == 0) { /* loop until halted */ int32 frameSz = M[PC] ; PC = INCA (PC) ; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[0]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[1]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[2]; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; + if (MEM_ADDR_OK (SP)) + M[SP] = FP; SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | (AC[3] & AMASK); + 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]) @@ -922,7 +968,8 @@ while (reason == 0) { /* loop until halted */ else if ((dstAC == 3) && (cpu_unit.flags & UNIT_STK)) /* if Nova 3 this is really a PSHA... 2007-Jun-01, BKR */ { SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; + if (MEM_ADDR_OK (SP)) + M[SP] = AC[dstAC]; STK_CHECK (SP, 1); } break; @@ -990,7 +1037,8 @@ while (reason == 0) { /* loop until halted */ 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 (code & 1) + AC[dstAC] = iodata & 0177777; } /* bkr, 2007-May-30 @@ -1055,7 +1103,8 @@ dev_disable = 0; pwr_low = 0; AMASK = 077777 ; /* 32KW mode */ pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1065,8 +1114,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & DMASK; return SCPE_OK; } @@ -1074,7 +1125,8 @@ 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 & DMASK; return SCPE_OK; } @@ -1088,11 +1140,13 @@ t_addr i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } diff --git a/NOVA/nova_dkp.c b/NOVA/nova_dkp.c index c38b4436..a89edf6e 100644 --- a/NOVA/nova_dkp.c +++ b/NOVA/nova_dkp.c @@ -571,7 +571,7 @@ switch (code) { /* decode IR<5:7> */ if ((dev_busy & INT_DKP) == 0) /* if device is not busy */ dkp_ussc = AC ; /* save unit, sect */ if (((dtype == TYPE_6099) || /* (BKR: don't forget 6097) */ - (dtype == TYPE_6097) || /* for 6099 and 6103 */ + (dtype == TYPE_6097) || /* for 6099 and 6103 */ (dtype == TYPE_6103)) && /* if data<0> set, */ (AC & 010000) ) dkp_diagmode = 1; /* set diagnostic mode */ @@ -597,9 +597,12 @@ switch (pulse) { /* decode IR<8:9> */ DEV_UPDATE_INTR ; /* update ints */ if (dkp_diagmode) { /* in diagnostic mode? */ dkp_diagmode = 0; /* reset it */ - if (dtype == TYPE_6097) dkp_ussc = 010001; /* (BKR - quad floppy) */ - if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */ - if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */ + if (dtype == TYPE_6097) /* (BKR - quad floppy) */ + dkp_ussc = 010001; + if (dtype == TYPE_6099) /* return size bits */ + dkp_ussc = 010002; + if (dtype == TYPE_6103) /* for certain types */ + dkp_ussc = 010003; } else { /* normal mode ... */ if (dkp_go (pulse)) /* do command */ @@ -638,7 +641,7 @@ switch (pulse) { /* decode IR<8:9> */ * start of this procedure and before our 'P' handler. BKR */ if (dkp_go(pulse)) - break; /* no error - do not set done and status */ + break; /* no error - do not set done and status */ } DEV_SET_DONE( INT_DKP ) ; /* set done */ @@ -905,10 +908,12 @@ do { if (uptr->FUNC == FCCY_READ) { /* read? */ awc = fxread (tbuf, sizeof(uint16), DKP_NUMWD, uptr->fileref); for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0; - if (err = ferror (uptr->fileref)) break; + 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]; + if (MEM_ADDR_OK (pa)) + M[pa] = tbuf[dx]; dkp_ma = (dkp_ma + 1) & AMASK; } } @@ -919,7 +924,8 @@ do { dkp_ma = (dkp_ma + 1) & AMASK; } fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; + if (err = ferror (uptr->fileref)) + break; } if (err != 0) { @@ -989,8 +995,10 @@ t_stat r; 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 */ +if ((r != SCPE_OK) || !(uptr->flags & UNIT_AUTO)) + return r; +if ((p = sim_fsize (uptr->fileref)) == 0) /* get file size */ + return SCPE_OK; 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); @@ -1005,7 +1013,8 @@ return SCPE_OK; t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = drv_tab[GET_DTYPE (val)].size; return SCPE_OK; } @@ -1077,7 +1086,8 @@ t_stat dkp_boot (int32 unitno, DEVICE *dptr) { int32 i; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = (uint16) boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = (uint16) boot_rom[i]; saved_PC = BOOT_START; SR = 0100000 + DEV_DKP; return SCPE_OK; diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c index 315a4804..f01063fc 100644 --- a/NOVA/nova_dsk.c +++ b/NOVA/nova_dsk.c @@ -222,7 +222,8 @@ if (pulse & 1) { /* read or write? */ DEV_SET_BUSY( INT_DSK ) ; DEV_UPDATE_INTR ; t = sector_map[dsk_da & DSK_MMASK] - GET_SECTOR (dsk_time); - if (t < 0) t = t + DSK_NUMSC; + if (t < 0) + t = t + DSK_NUMSC; sim_activate (&dsk_unit, t * dsk_time); /* activate */ } return rval; @@ -249,7 +250,8 @@ 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]; + if (MEM_ADDR_OK (pa)) + M[pa] = fbuf[da + i]; } dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; } @@ -313,7 +315,8 @@ uint32 ds_bytes = DSK_DKSIZE * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= DSK_NUMDK) p = DSK_NUMDK - 1; + 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 */ @@ -325,8 +328,10 @@ return attach_unit (uptr, cptr); t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (val < 0) + return SCPE_IERR; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * DSK_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; diff --git a/NOVA/nova_mta.c b/NOVA/nova_mta.c index 2dd287e4..2cd7fe49 100644 --- a/NOVA/nova_mta.c +++ b/NOVA/nova_mta.c @@ -282,7 +282,8 @@ 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 (dev_busy & INT_MTA) /* ignore if busy */ + break; 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 */ @@ -293,14 +294,16 @@ switch (pulse) { /* decode IR<8:9> */ 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); + 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); + if (ctype[c]) + sim_activate (uptr, mta_cwait); else { mta_upddsta (uptr, uptr->USTAT & ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)); @@ -349,7 +352,8 @@ 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); + if (u == GET_UNIT (mta_cu)) + mta_updcsta (uptr); return SCPE_OK; } @@ -364,7 +368,8 @@ else switch (c) { /* case on command */ break; case CU_DMODE: /* drive mode */ - if (!sim_tape_bot (uptr)) mta_sta = mta_sta | STA_ILL; /* must be BOT */ + if (!sim_tape_bot (uptr)) /* must be BOT */ + mta_sta = mta_sta | STA_ILL; else mta_upddsta (uptr, (mta_cu & CU_PE)? /* update drv status */ uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM); break; @@ -372,14 +377,17 @@ else switch (c) { /* case on command */ 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? */ + if (st == MTSE_RECE) /* rec in err? */ + mta_sta = mta_sta | STA_DAE; 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? */ + if (tbc & 1) /* odd byte count? */ + mta_sta = mta_sta | STA_ODD; + if (tbc > cbc) /* too big? */ + mta_sta = mta_sta | STA_WCO; else { cbc = tbc; /* no, use it */ wc = (cbc + 1) / 2; /* adjust wc */ @@ -388,7 +396,8 @@ else switch (c) { /* case on command */ c1 = mtxb[p++]; c2 = mtxb[p++]; pa = MapAddr (0, mta_ma); /* map address */ - if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2; + if (MEM_ADDR_OK (pa)) + M[pa] = (c1 << 8) | c2; mta_ma = (mta_ma + 1) & AMASK; } mta_wc = (mta_wc + wc) & DMASK; @@ -466,8 +475,10 @@ int32 mta_updcsta (UNIT *uptr) /* update ctrl */ { mta_sta = (mta_sta & ~(STA_DYN | STA_CLR | STA_ERR1 | STA_ERR2)) | (uptr->USTAT & STA_DYN) | STA_SET; -if (mta_sta & STA_EFLGS1) mta_sta = mta_sta | STA_ERR1; -if (mta_sta & STA_EFLGS2) mta_sta = mta_sta | STA_ERR2; +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; } @@ -477,7 +488,8 @@ void mta_upddsta (UNIT *uptr, int32 newsta) /* drive status */ { int32 change; -if ((uptr->flags & UNIT_ATT) == 0) newsta = 0; /* offline? */ +if ((uptr->flags & UNIT_ATT) == 0) /* offline? */ + newsta = 0; change = (uptr->USTAT ^ newsta) & STA_MON; /* changes? */ uptr->USTAT = newsta & STA_DYN; /* update status */ if (change) { @@ -571,8 +583,10 @@ for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ 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; +if (mtxb == NULL) + mtxb = (uint8 *) calloc (MTA_MAXFR, sizeof (uint8)); +if (mtxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -583,9 +597,11 @@ t_stat mta_attach (UNIT *uptr, char *cptr) t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM | - (sim_tape_wrp (uptr)? STA_WLK: 0)); +if (r != SCPE_OK) + return r; +if (!sim_is_active (uptr)) + mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM | + (sim_tape_wrp (uptr)? STA_WLK: 0)); return r; } @@ -593,8 +609,10 @@ return r; t_stat mta_detach (UNIT* uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -if (!sim_is_active (uptr)) mta_upddsta (uptr, 0); +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; +if (!sim_is_active (uptr)) + mta_upddsta (uptr, 0); return sim_tape_detach (uptr); } @@ -608,7 +626,6 @@ else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK); return SCPE_OK; } - /* Boot routine */ t_stat mta_boot (int32 unitno, DEVICE *dptr) diff --git a/NOVA/nova_pt.c b/NOVA/nova_pt.c index 47788503..2d7dff4b 100644 --- a/NOVA/nova_pt.c +++ b/NOVA/nova_pt.c @@ -192,7 +192,8 @@ 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"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); diff --git a/NOVA/nova_qty.c b/NOVA/nova_qty.c index e4c928b5..215ac3fe 100644 --- a/NOVA/nova_qty.c +++ b/NOVA/nova_qty.c @@ -109,8 +109,6 @@ 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_attach ( UNIT * uptr, char * cptr ) ; @@ -158,8 +156,6 @@ UNIT qty_unit = UDATA (&qty_svc, (UNIT_ATTABLE), 0) } ; -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) }, @@ -179,14 +175,15 @@ 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 }, + &tmxr_dscln, NULL, (void *)&qty_desc }, + { UNIT_ATT, UNIT_ATT, "connections", NULL, + NULL, &tmxr_show_summ, (void *)&qty_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &qty_show, NULL }, + NULL, &tmxr_show_cstat, (void *)&qty_desc }, { 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 }, + NULL, &tmxr_show_cstat, (void *)&qty_desc }, + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &qty_setnl, &tmxr_show_lines, (void *) &qty_desc }, { 0 } } ; @@ -750,50 +747,6 @@ int32 qty( int32 pulse, int32 code, int32 AC ) 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 ; - - 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 */ - /*--------------------------------------------------------------*/ - -t_stat qty_show( FILE * st, UNIT * uptr, int32 val, void * desc ) - { - 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' */ - - /*--------------------------------------------------------------*/ /* qty_setnl */ /*--------------------------------------------------------------*/ diff --git a/NOVA/nova_sys.c b/NOVA/nova_sys.c index 54dfc740..0dab680b 100644 --- a/NOVA/nova_sys.c +++ b/NOVA/nova_sys.c @@ -288,8 +288,8 @@ for ( pos = 0 ; (! done) && ((i=getc(fileref)) != EOF) ; ++pos ) state = 6; break; case 8: /* error (ignore) block */ - if (i == 0377) - state = 0; /* (wait for 'RUBOUT' char) */ + if (i == 0377) /* (wait for 'RUBOUT' char) */ + state = 0; break; } /* end switch */ } /* end while */ @@ -645,10 +645,12 @@ t_stat fprint_addr (FILE *of, t_addr addr, int32 ind, int32 mode, { int32 dsign, dmax; -if (ext) dmax = AMASK + 1; /* get max disp */ +if (ext) /* get max disp */ + dmax = AMASK + 1; else dmax = I_M_DISP + 1; dsign = dmax >> 1; /* get disp sign */ -if (ind) fprintf (of, "@"); /* indirect? */ +if (ind) /* indirect? */ + fprintf (of, "@"); switch (mode & 03) { /* mode */ case 0: /* absolute */ @@ -657,22 +659,26 @@ switch (mode & 03) { /* mode */ case 1: /* PC rel */ if (disp & dsign) { - if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK); + if (cflag) + fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK); else fprintf (of, ".-%-o", dmax - disp); } else { - if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK); + 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); + 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); + if (disp & dsign) + fprintf (of, "-%-o,3", dmax - disp); else fprintf (of, "%-o,3", disp); break; } /* end switch */ @@ -711,7 +717,8 @@ if (sw & SWMASK ('C')) { /* character? */ fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */ +if (!(sw & SWMASK ('M'))) /* mnemonic? */ + return SCPE_ARG; /* Instruction decode */ @@ -774,7 +781,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ case I_V_RR: /* operate */ fprintf (of, "%s %-o,%-o", opcode[i], src, dst); - if (skp) fprintf (of, ",%s", skip[skp-1]); + if (skp) + fprintf (of, ",%s", skip[skp-1]); break; case I_V_BY: /* byte */ @@ -857,7 +865,8 @@ int32 d, r, x, pflag; char gbuf[CBUFSIZE]; int32 dmax, dsign; -if (ext) dmax = AMASK + 1; /* get max disp */ +if (ext) /* get max disp */ + dmax = AMASK + 1; else dmax = I_M_DISP + 1; dsign = dmax >> 1; /* get disp sign */ val[0] = 0; /* no indirect */ @@ -885,25 +894,29 @@ else if (*cptr == '-') { /* - sign? */ 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; + 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; + 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; + 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; + if (d < dmax) + val[2] = d; else if (((d >= (((int32) addr - dsign) & AMASK)) && (d < (((int32) addr + dsign) & AMASK))) || (d >= ((int32) addr + (-dsign & AMASK)))) { @@ -922,8 +935,10 @@ switch (pflag) { /* case on flags */ 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); + 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; @@ -952,10 +967,12 @@ t_stat r; cptr = get_glyph (cptr, gbuf, ','); /* get register */ val[0] = (int32) get_uint (gbuf, 8, I_M_SRC, &r); -if (r != SCPE_OK) return NULL; +if (r != SCPE_OK) + return NULL; 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; +if (r != SCPE_OK) + return NULL; return cptr; } @@ -980,12 +997,14 @@ char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); while (isspace (*cptr)) cptr++; /* absorb spaces */ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = ((t_value) cptr[0] << 8) + (t_value) cptr[1]; return SCPE_OK; } @@ -995,7 +1014,8 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ 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; +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 */ @@ -1007,23 +1027,27 @@ switch (j) { /* case on class */ 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; + 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; + 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]; + 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; + if (r != SCPE_OK) + return SCPE_ARG; val[0] = val[0] | (d << I_V_DEV); } break; @@ -1031,57 +1055,67 @@ switch (j) { /* case on class */ 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; val[0] = val[0] | (d << I_V_DST); /* put in place */ rtn = -1; break; @@ -1089,18 +1123,21 @@ switch (j) { /* case on class */ 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; + 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; + 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; + 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; @@ -1109,10 +1146,12 @@ switch (j) { /* case on class */ 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; + 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; + 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; @@ -1120,7 +1159,8 @@ switch (j) { /* case on class */ case I_V_FST: /* flt status */ cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; + 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; @@ -1128,15 +1168,18 @@ switch (j) { /* case on class */ case I_V_XP: /* XOP */ cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; + 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; + 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? */ +if (*cptr != 0) /* any leftovers? */ + return SCPE_ARG; return rtn; } diff --git a/NOVA/nova_tt1.c b/NOVA/nova_tt1.c index ad451593..0b495651 100644 --- a/NOVA/nova_tt1.c +++ b/NOVA/nova_tt1.c @@ -27,6 +27,7 @@ tti1 second terminal input tto1 second terminal output + 19-Nov-08 RMS Revised for common TMXR show routines 09-May-03 RMS Added network device flag 05-Jan-03 RMS Fixed calling sequence for setmod 03-Oct-02 RMS Added DIBs @@ -63,8 +64,6 @@ t_stat tto1_reset (DEVICE *dptr); t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat tti1_attach (UNIT *uptr, char *cptr); t_stat tti1_detach (UNIT *uptr); -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc); void ttx1_enbdis (int32 dis); /* TTI1 data structures @@ -93,13 +92,14 @@ REG tti1_reg[] = { 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 }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &tt_desc }, { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &tt_desc }, + &tmxr_dscln, NULL, (void *) &tt_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tti1_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &tt_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tti1_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &tt_desc }, { 0 } }; @@ -136,6 +136,10 @@ REG tto1_reg[] = { MTAB tto1_mod[] = { { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", + &tmxr_set_log, &tmxr_show_log, &tt_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", + &tmxr_set_nolog, NULL, &tt_desc }, { 0 } }; @@ -225,7 +229,8 @@ return SCPE_OK; int32 tto1 (int32 pulse, int32 code, int32 AC) { -if (code == ioDOA) tto1_unit.buf = AC & 0377; +if (code == ioDOA) + tto1_unit.buf = AC & 0377; switch (pulse) { /* decode IR<8:9> */ case iopS: /* start */ @@ -256,7 +261,8 @@ 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 ((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 */ @@ -297,7 +303,8 @@ 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 */ +if (r != SCPE_OK) /* error */ + return r; sim_activate (uptr, tmxr_poll); /* start poll */ return SCPE_OK; } @@ -314,30 +321,12 @@ sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (tt1_ldsc.conn) fprintf (st, "connected"); -else fprintf (st, "disconnected"); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val) tmxr_fconns (st, &tt1_ldsc, -1); -else tmxr_fstats (st, &tt1_ldsc, -1); -return SCPE_OK; -} - /* Enable/disable device */ void ttx1_enbdis (int32 dis) { if (dis) { - tti1_dev.flags = tto1_dev.flags | DEV_DIS; + tti1_dev.flags = tti1_dev.flags | DEV_DIS; tto1_dev.flags = tto1_dev.flags | DEV_DIS; } else { diff --git a/PDP1/pdp1_clk.c b/PDP1/pdp1_clk.c index db2b7ad1..9e3914fd 100644 --- a/PDP1/pdp1_clk.c +++ b/PDP1/pdp1_clk.c @@ -1,6 +1,6 @@ /* pdp1_clk.c: PDP-1D clock simulator - Copyright (c) 2006, Robert M. Supnik + Copyright (c) 2006-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -98,7 +98,8 @@ return clk_cntr + incr; t_stat clk_svc (UNIT *uptr) { -if (clk_dev.flags & DEV_DIS) return SCPE_OK; /* disabled? */ +if (clk_dev.flags & DEV_DIS) /* disabled? */ + return SCPE_OK; tmxr_poll = sim_rtcn_calb (CLK_TPS, TMR_CLK); /* calibrate clock */ sim_activate (&clk_unit, tmxr_poll); /* reactivate unit */ clk_cntr = clk_cntr + CLK_CNTS; /* incr counter */ diff --git a/PDP1/pdp1_cpu.c b/PDP1/pdp1_cpu.c index 76876a91..40e2a910 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -522,14 +522,16 @@ if (cpu_unit.flags & UNIT_1D) { /* PDP-1D? */ if (!(cpu_unit.flags & UNIT_1D45)) { /* SN 48? */ PF &= ~PF_L; /* no link */ rtb = 0; /* no RTB */ - for (i = 0; i < RN45_SIZE; i++) rname[i] = i; /* no rename */ + for (i = 0; i < RN45_SIZE; i++) /* no rename */ + rname[i] = i; } } else { /* standard PDP-1 */ PF &= ~(PF_L|PF_RNG); /* no link, ring */ rm = 0; /* no restrict mode */ rtb = 0; /* no RTB */ - for (i = 0; i < RN45_SIZE; i++) rname[i] = i; /* no rename */ + for (i = 0; i < RN45_SIZE; i++) /* no rename */ + rname[i] = i; } if (cpu_unit.flags & UNIT_SBS) { /* 16-chan SBS? */ sbs = sbs & SB_ON; /* yes, only SB ON */ @@ -543,7 +545,8 @@ reason = 0; while (reason == 0) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; sbs_lvl = sbs_eval (); /* eval sbs system */ } @@ -583,14 +586,16 @@ while (reason == 0) { /* loop until halted */ /* Fetch, decode instruction */ MA = PC; - if (Read ()) break; /* fetch inst */ + if (Read ()) /* fetch inst */ + break; IR = MB; /* save in IR */ PC = INCR_ADDR (PC); /* increment PC */ xct_count = 0; /* track 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; + if (hst_p >= hst_lnt) + hst_p = 0; hst[hst_p].pc = MA | HIST_PC; /* save state */ hst[hst_p].ir = IR; hst[hst_p].ovac = (OV << HIST_V_SHF) | AC; @@ -604,20 +609,26 @@ while (reason == 0) { /* loop until halted */ /* Logical, load, store instructions */ case 001: /* AND */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = AC & MB; break; case 002: /* IOR */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = AC | MB; break; case 003: /* XOR */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = AC ^ MB; break; @@ -626,16 +637,20 @@ while (reason == 0) { /* loop until halted */ reason = STOP_XCT; break; } - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; xct_count = xct_count + 1; /* count XCT's */ IR = MB; /* get instruction */ goto xct_instr; /* go execute */ case 005: /* LCH */ if (cpu_unit.flags & UNIT_1D) { /* PDP-1D? */ - if (reason = Ea_ch (IR, &byno)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea_ch (IR, &byno)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = (MB << byt_shf[byno]) & 0770000; /* extract byte */ } else reason = stop_inst; /* no, illegal */ @@ -643,8 +658,10 @@ while (reason == 0) { /* loop until halted */ case 006: /* DCH */ if (cpu_unit.flags & UNIT_1D) { /* PDP-1D? */ - if (reason = Ea_ch (IR, &byno)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea_ch (IR, &byno)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; MB = (MB & ~(0770000 >> byt_shf[byno])) | /* insert byte */ ((AC & 0770000) >> byt_shf[byno]); Write (); /* rewrite */ @@ -655,7 +672,8 @@ while (reason == 0) { /* loop until halted */ case 007: /* CAL, JDA */ MA = (PC & EPCMASK) | ((IR & IA)? (IR & DAMASK): 0100); - if (hst_p) hst[hst_p].ea = MA; /* history enabled? */ + if (hst_p) /* history enabled? */ + hst[hst_p].ea = MA; PCQ_ENTRY; MB = AC; /* save AC */ AC = EPC_WORD; @@ -664,45 +682,56 @@ while (reason == 0) { /* loop until halted */ break; case 010: /* LAC */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = MB; break; case 011: /* LIO */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; IO = MB; break; case 012: /* DAC */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; MB = AC; reason = Write (); break; case 013: /* DAP */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; MB = (AC & DAMASK) | (MB & ~DAMASK); reason = Write (); break; case 014: /* DIP */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; MB = (AC & ~DAMASK) | (MB & DAMASK); reason = Write (); break; case 015: /* DIO */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; MB = IO; reason = Write (); break; case 016: /* DZM */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; MB = 0; reason = Write (); break; @@ -725,10 +754,13 @@ while (reason == 0) { /* loop until halted */ case 017: /* TAD */ if (cpu_unit.flags & UNIT_1D) { /* PDP-1D? */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = AC + MB + ((PF & PF_L)? 1: 0); /* AC + opnd + L */ - if (AC > DMASK) PF = PF | PF_L; /* carry? set L */ + if (AC > DMASK) /* carry? set L */ + PF = PF | PF_L; else PF = PF & ~PF_L; /* no, clear L */ AC = AC & DMASK; /* mask AC */ } @@ -736,54 +768,76 @@ while (reason == 0) { /* loop until halted */ break; case 020: /* ADD */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; t = AC; AC = AC + MB; - if (AC > 0777777) AC = (AC + 1) & DMASK; /* end around carry */ - if (((~t ^ MB) & (t ^ AC)) & SIGN) OV = 1; - if (AC == DMASK) AC = 0; /* minus 0 cleanup */ + if (AC > 0777777) /* end around carry */ + AC = (AC + 1) & DMASK; + if (((~t ^ MB) & (t ^ AC)) & SIGN) + OV = 1; + if (AC == DMASK) /* minus 0 cleanup */ + AC = 0; break; case 021: /* SUB */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; t = AC ^ DMASK; /* complement AC */ AC = t + MB; /* -AC + MB */ - if (AC > DMASK) AC = (AC + 1) & DMASK; /* end around carry */ - if (((~t ^ MB) & (t ^ AC)) & SIGN) OV = 1; + if (AC > DMASK) /* end around carry */ + AC = (AC + 1) & DMASK; + if (((~t ^ MB) & (t ^ AC)) & SIGN) + OV = 1; AC = AC ^ DMASK; /* recomplement AC */ break; case 022: /* IDX */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = MB + 1; - if (AC >= DMASK) AC = (AC + 1) & DMASK; + if (AC >= DMASK) + AC = (AC + 1) & DMASK; MB = AC; reason = Write (); break; case 023: /* ISP */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; AC = MB + 1; - if (AC >= DMASK) AC = (AC + 1) & DMASK; + if (AC >= DMASK) + AC = (AC + 1) & DMASK; MB = AC; - if (!(AC & SIGN)) PC = INCR_ADDR (PC); + if (!(AC & SIGN)) + PC = INCR_ADDR (PC); reason = Write (); break; case 024: /* SAD */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ - if (AC != MB) PC = INCR_ADDR (PC); + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; + if (AC != MB) + PC = INCR_ADDR (PC); break; case 025: /* SAS */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ - if (AC == MB) PC = INCR_ADDR (PC); + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; + if (AC == MB) + PC = INCR_ADDR (PC); break; case 030: /* JMP */ @@ -804,17 +858,20 @@ while (reason == 0) { /* loop until halted */ OV = (MB >> 17) & 1; /* restore OV */ extm = (MB >> 16) & 1; /* restore ext mode */ PC = MB & AMASK; /* jmp i 00x1/5 */ - if (hst_p) hst[hst_p].ea = PC; /* history enabled? */ + if (hst_p) /* history enabled? */ + hst[hst_p].ea = PC; } else { /* normal JMP */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; PCQ_ENTRY; PC = MA; } break; case 031: /* JSP */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; AC = EPC_WORD; PCQ_ENTRY; PC = MA; @@ -831,14 +888,17 @@ while (reason == 0) { /* loop until halted */ */ case 026: /* MUL */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; if (cpu_unit.flags & UNIT_MDV) { /* hardware? */ sign = AC ^ MB; /* result sign */ IO = ABS (AC); /* IO = |AC| */ v = ABS (MB); /* v = |mpy| */ for (i = AC = 0; i < 17; i++) { - if (IO & 1) AC = AC + v; + if (IO & 1) + AC = AC + v; IO = (IO >> 1) | ((AC & 1) << 17); AC = AC >> 1; } @@ -848,33 +908,41 @@ while (reason == 0) { /* loop until halted */ } } else { /* multiply step */ - if (IO & 1) AC = AC + MB; - if (AC > DMASK) AC = (AC + 1) & DMASK; + if (IO & 1) + AC = AC + MB; + if (AC > DMASK) + AC = (AC + 1) & DMASK; IO = (IO >> 1) | ((AC & 1) << 17); AC = AC >> 1; } break; case 027: /* DIV */ - if (reason = Ea (IR)) break; /* MA <- eff addr */ - if (reason = Read ()) break; /* MB <- data */ + if (reason = Ea (IR)) /* MA <- eff addr */ + break; + if (reason = Read ()) /* MB <- data */ + break; if (cpu_unit.flags & UNIT_MDV) { /* hardware */ sign = AC ^ MB; /* result sign */ signd = AC; /* remainder sign */ v = ABS (MB); /* v = |divr| */ - if (ABS (AC) >= v) break; /* overflow? */ + if (ABS (AC) >= v) /* overflow? */ + break; if (AC & SIGN) { - AC = AC ^ DMASK; /* AC'IO = |AC'IO| */ + AC = AC ^ DMASK; /* AC'IO = |AC'IO| */ IO = IO ^ DMASK; } for (i = t = 0; i < 18; i++) { - if (t) AC = (AC + v) & DMASK; + if (t) + AC = (AC + v) & DMASK; else AC = (AC - v) & DMASK; t = AC >> 17; - if (i != 17) AC = ((AC << 1) | (IO >> 17)) & DMASK; + if (i != 17) + AC = ((AC << 1) | (IO >> 17)) & DMASK; IO = ((IO << 1) | (t ^ 1)) & 0777777; } - if (t) AC = (AC + v) & DMASK; /* fix remainder */ + if (t) /* fix remainder */ + AC = (AC + v) & DMASK; t = ((signd & SIGN) && AC)? AC ^ DMASK: AC; AC = ((sign & SIGN) && IO)? IO ^ DMASK: IO; IO = t; @@ -884,10 +952,13 @@ while (reason == 0) { /* loop until halted */ t = AC >> 17; AC = ((AC << 1) | (IO >> 17)) & DMASK; IO = ((IO << 1) | (t ^ 1)) & DMASK; - if (IO & 1) AC = AC + (MB ^ DMASK); + if (IO & 1) + AC = AC + (MB ^ DMASK); else AC = AC + MB + 1; - if (AC > DMASK) AC = (AC + 1) & DMASK; - if (AC == DMASK) AC = 0; + if (AC > DMASK) + AC = (AC + 1) & DMASK; + if (AC == DMASK) + AC = 0; } break; @@ -905,9 +976,12 @@ while (reason == 0) { /* loop until halted */ ((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 */ + if (IR & IA) /* invert skip? */ + skip = skip ^ 1; + if (skip) + PC = INCR_ADDR (PC); + if (IR & 01000) /* SOV clears OV */ + OV = 0; break; /* Shifts */ @@ -989,32 +1063,40 @@ while (reason == 0) { /* loop until halted */ case 036: /* special */ if (cpu_unit.flags & UNIT_1D) { /* PDP-1D? */ - if (IR & 000100) IO = 0; /* SCI */ - if (IR & 000040) PF = 0; /* SCF */ + if (IR & 000100) /* SCI */ + IO = 0; + if (IR & 000040) /* SCF */ + PF = 0; if (cpu_unit.flags & UNIT_1D45) { /* SN 45? */ if ((IR & 000020) && /* SZL/SNL? */ (((PF & PF_L) == 0) == ((IR & IA) == 0))) PC = INCR_ADDR (PC); - if (IR & 000010) PF = PF & ~PF_L; /* CLL */ + if (IR & 000010) /* CLL */ + PF = PF & ~PF_L; if (IR & 000200) { /* SCM */ AC = (AC ^ DMASK) + ((PF & PF_L)? 1: 0); - if (AC > DMASK) PF = PF | PF_L; /* carry? set L */ + if (AC > DMASK) /* carry? set L */ + PF = PF | PF_L; else PF = PF & ~PF_L; /* no, clear L */ AC = AC & DMASK; /* mask AC */ } } t = IO & PF_VR_ALL; - if (IR & 004000) IO = IO | PF; /* IIF */ - if (IR & 002000) PF = PF | t; /* IFI */ + if (IR & 004000) /* IIF */ + IO = IO | PF; + if (IR & 002000) /* IFI */ + PF = PF | t; if (cpu_unit.flags & UNIT_1D45) { /* SN 45? */ - if (IR & 000004) PF = PF ^ PF_L; /* CML */ + if (IR & 000004) /* CML */ + PF = PF ^ PF_L; if (IR & 000400) /* IDA */ AC = (PF & PF_RNG)? (AC & 0777770) | ((AC + 1) & 07): (AC + 1) & DMASK; } else PF = PF & ~PF_L; /* no link */ - if (IR & 01000) AC = inc_bp (AC); /* IDC */ + if (IR & 01000) /* IDC */ + AC = inc_bp (AC); } else reason = stop_inst; /* no, illegal */ break; @@ -1022,19 +1104,28 @@ while (reason == 0) { /* loop until halted */ /* Operates - performed in the order shown */ case 037: /* operate */ - if (IR & 004000) IO = 0; /* CLI */ - if (IR & 000200) AC = 0; /* CLA */ - if (IR & 002000) AC = AC | TW; /* LAT */ - if (IR & 000100) AC = AC | EPC_WORD; /* LAP */ - if (IR & 001000) AC = AC ^ DMASK; /* CMA */ + if (IR & 004000) /* CLI */ + IO = 0; + if (IR & 000200) /* CLA */ + AC = 0; + if (IR & 002000) /* LAT */ + AC = AC | TW; + if (IR & 000100) /* LAP */ + AC = AC | EPC_WORD; + if (IR & 001000) /* CMA */ + AC = AC ^ DMASK; if (cpu_unit.flags & UNIT_1D) { /* PDP-1D? */ - if (IR & 010000) IO = IO ^ DMASK; /* CMI */ + if (IR & 010000) /* CMI */ + IO = IO ^ DMASK; MB = IO; - if (IR & 000020) IO = AC; /* LIA */ - if (IR & 000040) AC = MB; /* LAI */ + if (IR & 000020) /* LIA */ + IO = AC; + if (IR & 000040) /* LAI */ + AC = MB; } t = IR & 07; /* flag select */ - if (IR & 010) PF = PF | fs_test[t]; /* STFn */ + if (IR & 010) /* STFn */ + PF = PF | fs_test[t]; else PF = PF & ~fs_test[t]; /* CLFn */ if (IR & 000400) { /* HLT */ if (rm && !sbs_act) /* restrict, ~brk? */ @@ -1071,7 +1162,8 @@ while (reason == 0) { /* loop until halted */ } if (IR & IO_WAIT) { /* wait? */ if (ioh) { /* I/O halt? */ - if (ios) ioh = 0; /* comp pulse? done */ + if (ios) /* comp pulse? done */ + ioh = 0; else { /* wait more */ PC = DECR_ADDR (PC); /* re-execute */ if (cpls == 0) { /* pending pulses? */ @@ -1094,7 +1186,8 @@ while (reason == 0) { /* loop until halted */ break; case 001: - if (IR & 003700) io_data = dt (IR, dev, IO); /* DECtape */ + if (IR & 003700) /* DECtape */ + io_data = dt (IR, dev, IO); else io_data = ptr (IR, dev, IO); /* paper tape rdr */ break; @@ -1115,16 +1208,18 @@ while (reason == 0) { /* loop until halted */ break; case 010: /* leave ring mode */ - if (cpu_unit.flags & UNIT_1D) PF = PF & ~PF_RNG; + if (cpu_unit.flags & UNIT_1D) + PF = PF & ~PF_RNG; else reason = stop_inst; break; case 011: /* enter ring mode */ - if (cpu_unit.flags & UNIT_1D) PF = PF | PF_RNG; + if (cpu_unit.flags & UNIT_1D) + PF = PF | PF_RNG; else reason = stop_inst; break; - case 022: /* data comm sys */ + case 022: /* data comm sys */ io_data = dcs (IR, dev, IO); break; @@ -1167,7 +1262,8 @@ while (reason == 0) { /* loop until halted */ break; case 053: /* clear all chan */ - if (cpu_unit.flags & UNIT_SBS) sbs_enb = 0; + if (cpu_unit.flags & UNIT_SBS) + sbs_enb = 0; else reason = stop_inst; break; @@ -1191,7 +1287,8 @@ while (reason == 0) { /* loop until halted */ break; case 064: /* drum/leave rm */ - if (cpu_unit.flags & UNIT_1D) rm = 0; + if (cpu_unit.flags & UNIT_1D) + rm = 0; else io_data = drm (IR, dev, IO); break; @@ -1214,7 +1311,8 @@ while (reason == 0) { /* loop until halted */ case 067: /* reset renaming */ if (cpu_unit.flags & UNIT_1D45) { /* SN45 */ - for (i = 0; i < RN45_SIZE; i++) rname[i] = i; + for (i = 0; i < RN45_SIZE; i++) + rname[i] = i; } else reason = stop_inst; break; @@ -1229,8 +1327,10 @@ while (reason == 0) { /* loop until halted */ } /* end switch dev */ IO = io_data & DMASK; - if (io_data & IOT_SKP) PC = INCR_ADDR (PC); /* skip? */ - if (io_data >= IOT_REASON) reason = io_data >> IOT_V_REASON; + if (io_data & IOT_SKP) /* skip? */ + PC = INCR_ADDR (PC); + if (io_data >= IOT_REASON) + reason = io_data >> IOT_V_REASON; sbs_lvl = sbs_eval (); /* eval SBS system */ break; @@ -1261,19 +1361,24 @@ t_stat r; MA = (PC & EPCMASK) | (IR & DAMASK); /* direct address */ if (IR & IA) { /* indirect addr? */ if (extm) { /* extend? */ - if (r = Read ()) return r; /* read; err? */ + if (r = Read ()) /* read; err? */ + return r; MA = MB & AMASK; /* one level */ } else { /* multi-level */ for (i = 0; i < ind_max; i++) { /* count indirects */ - if (r = Read ()) return r; /* get ind word */ + if (r = Read ()) /* get ind word */ + return r; MA = (PC & EPCMASK) | (MB & DAMASK); - if ((MB & IA) == 0) break; + if ((MB & IA) == 0) + break; } - if (i >= ind_max) return STOP_IND; /* indirect loop? */ + if (i >= ind_max) /* indirect loop? */ + return STOP_IND; } /* end else !extm */ } /* end if indirect */ -if (hst_p) hst[hst_p].ea = MA; /* history enabled? */ +if (hst_p) /* history enabled? */ + hst[hst_p].ea = MA; return SCPE_OK; } @@ -1286,15 +1391,19 @@ t_stat r; MA = (PC & EPCMASK) | (IR & DAMASK); /* direct address */ if (extm) { /* extend? */ - if (r = Read ()) return r; /* read; err? */ + if (r = Read ()) /* read; err? */ + return r; } else { /* multi-level */ for (i = 0; i < ind_max; i++) { /* count indirects */ - if (r = Read ()) return r; /* get ind word */ - if ((MB & IA) == 0) break; + if (r = Read ()) /* get ind word */ + return r; + if ((MB & IA) == 0) + break; MA = (PC & EPCMASK) | (MB & DAMASK); } - if (i >= ind_max) return STOP_IND; /* indirect loop? */ + if (i >= ind_max) /* indirect loop? */ + return STOP_IND; } /* end else !extm */ if (IR & IA) { /* automatic mode? */ if (rm & !sbs_act & ((MB & 0607777) == 0607777)) /* page cross? */ @@ -1303,9 +1412,11 @@ if (IR & IA) { /* automatic mode? */ Write (); /* rewrite */ } *bn = (MB >> 16) & 03; /* byte num */ -if (extm) MA = MB & AMASK; /* final ea */ +if (extm) /* final ea */ + MA = MB & AMASK; else MA = (PC & EPCMASK) | (MB & DAMASK); -if (hst_p) hst[hst_p].ea = MA; /* history enabled? */ +if (hst_p) /* history enabled? */ + hst[hst_p].ea = MA; return SCPE_OK; } @@ -1328,21 +1439,26 @@ t_stat Read (void) { if (rm && !sbs_act) { /* restrict check? */ int32 bnk = MA_GETBNK (MA); /* get bank */ - if ((rmask << bnk) & SIGN) return set_rmv (0); + if ((rmask << bnk) & SIGN) + return set_rmv (0); } MB = M[MA]; -if (hst_p) hst[hst_p].opnd = MB; /* history enabled? */ +if (hst_p) /* history enabled? */ + hst[hst_p].opnd = MB; return SCPE_OK; } t_stat Write (void) { -if (hst_p) hst[hst_p].opnd = M[MA]; /* hist? old contents */ +if (hst_p) /* hist? old contents */ + hst[hst_p].opnd = M[MA]; if (rm && !sbs_act) { /* restrict check? */ int32 bnk = MA_GETBNK (MA); /* get bank */ - if ((rmask << bnk) & SIGN) return set_rmv (0); + if ((rmask << bnk) & SIGN) + return set_rmv (0); } -if (MEM_ADDR_OK (MA)) M[MA] = MB; +if (MEM_ADDR_OK (MA)) + M[MA] = MB; return SCPE_OK; } @@ -1361,9 +1477,11 @@ int32 sbs_eval (void) int32 hi; if (cpu_unit.flags & UNIT_SBS) { /* SBS enabled? */ - if (sbs_req == 0) return 0; /* any requests? */ + if (sbs_req == 0) /* any requests? */ + return 0; hi = sbs_ffo (sbs_req); /* find highest */ - if (hi < sbs_ffo (sbs_act)) return hi + 1; /* higher? */ + if (hi < sbs_ffo (sbs_act)) /* higher? */ + return hi + 1; } return 0; } @@ -1382,7 +1500,8 @@ else return (ffo_map[mask & 0377] + 8); t_stat dev_req_int (int32 lvl) { if (cpu_unit.flags & UNIT_SBS) { /* SBS enabled? */ - if (lvl >= SBS_LVLS) return SCPE_IERR; /* invalid level? */ + if (lvl >= SBS_LVLS) /* invalid level? */ + return SCPE_IERR; if (sbs_enb & SBS_MASK (lvl)) /* level active? */ sbs_req |= SBS_MASK (lvl); /* set SBS request */ } @@ -1398,9 +1517,11 @@ int32 *lvl = (int32 *) desc; int32 newlvl; t_stat r; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_ARG; +if ((cptr == NULL) || (*cptr == 0)) + return SCPE_ARG; newlvl = get_uint (cptr, 10, SBS_LVLS - 1, &r); -if (r != SCPE_OK) return SCPE_ARG; +if (r != SCPE_OK) + return SCPE_ARG; *lvl = newlvl; return SCPE_OK; } @@ -1409,7 +1530,8 @@ t_stat dev_show_sbs (FILE *st, UNIT *uptr, int32 val, void *desc) { int32 *lvl = (int32 *) desc; -if (lvl == NULL) return SCPE_IERR; +if (lvl == NULL) + return SCPE_IERR; fprintf (st, "SBS level %d", *lvl); return SCPE_OK; } @@ -1435,9 +1557,11 @@ MB = 0; rm = 0; rtb = 0; rmask = 0; -for (i = 0; i < RN45_SIZE; i++) rname[i] = i; +for (i = 0; i < RN45_SIZE; i++) + rname[i] = i; pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1447,8 +1571,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & DMASK; return SCPE_OK; } @@ -1456,7 +1582,8 @@ 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 & DMASK; return SCPE_OK; } @@ -1470,11 +1597,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } @@ -1494,12 +1623,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -1508,7 +1639,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -1526,14 +1658,17 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ diff --git a/PDP1/pdp1_dcs.c b/PDP1/pdp1_dcs.c index deeef5c4..dd54ce18 100644 --- a/PDP1/pdp1_dcs.c +++ b/PDP1/pdp1_dcs.c @@ -1,6 +1,6 @@ /* pdp1_dcs.c: PDP-1D terminal multiplexor simulator - Copyright (c) 2006, Robert M Supnik + Copyright (c) 2006-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ dcs Type 630 data communications subsystem + 19-Nov-2008 RMS Revised for common TMXR show routines + This module implements up to 32 individual serial interfaces. */ @@ -54,8 +56,6 @@ t_stat dcso_svc (UNIT *uptr); t_stat dcs_reset (DEVICE *dptr); t_stat dcs_attach (UNIT *uptr, char *cptr); t_stat dcs_detach (UNIT *uptr); -t_stat dcs_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dcs_show (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat dcs_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); void dcs_reset_ln (int32 ln); void dcs_scan_next (t_bool unlk); @@ -68,8 +68,6 @@ void dcs_scan_next (t_bool unlk); dcs_mod DCS modifiers list */ -REG dcs_nlreg = { DRDATA (NLINES, DCS_NUMLIN, 6), PV_LEFT }; - UNIT dcs_unit = { UDATA (&dcsi_svc, UNIT_ATTABLE, 0) }; REG dcs_reg[] = { @@ -85,15 +83,16 @@ REG dcs_reg[] = { MTAB dcs_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL", &dev_set_sbs, &dev_show_sbs, (void *) &dcs_sbs }, - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &dcs_vlines, NULL, &dcs_nlreg }, + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &dcs_vlines, &tmxr_show_lines, (void *) &dcs_desc }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &dcs_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &dcs_summ }, + &tmxr_dscln, NULL, (void *) &dcs_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &dcs_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &dcs_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dcs_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &dcs_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dcs_desc }, { 0 } }; @@ -184,7 +183,8 @@ int32 pls = (inst >> 6) & 077; if (dcs_dev.flags & DEV_DIS) /* disabled? */ return (stop_inst << IOT_V_REASON) | dat; /* illegal inst */ -if (pls & 020) dat = 0; /* pulse 20? clr IO */ +if (pls & 020) /* pulse 20? clr IO */ + dat = 0; switch (pls & 057) { /* case IR<6,8:11> */ @@ -239,8 +239,10 @@ t_stat dcsi_svc (UNIT *uptr) { int32 ln, c, out; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -if (dcs_dev.flags & DEV_DIS) return SCPE_OK; +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; +if (dcs_dev.flags & DEV_DIS) + return SCPE_OK; sim_activate (uptr, tmxr_poll); /* continue poll */ ln = tmxr_poll_conn (&dcs_desc); /* look for connect */ if (ln >= 0) { /* got one? */ @@ -250,7 +252,8 @@ tmxr_poll_rx (&dcs_desc); /* poll for input */ for (ln = 0; ln < DCS_NUMLIN; ln++) { /* loop thru lines */ if (dcs_ldsc[ln].conn) { /* connected? */ if (c = tmxr_getc_ln (&dcs_ldsc[ln])) { /* get char */ - if (c & SCPE_BREAK) c = 0; /* break? */ + if (c & SCPE_BREAK) /* break? */ + c = 0; else c = sim_tt_inpcvt (c, TT_GET_MODE (dcsl_unit[ln].flags)|TTUF_KSR); dcs_buf[ln] = c; /* save char */ dcs_flg[ln] = 1; /* set line flag */ @@ -274,11 +277,13 @@ t_stat dcso_svc (UNIT *uptr) int32 c; uint32 ln = uptr - dcsl_unit; /* line # */ -if (dcs_dev.flags & DEV_DIS) return SCPE_OK; +if (dcs_dev.flags & DEV_DIS) + return SCPE_OK; if (dcs_ldsc[ln].conn) { /* connected? */ if (dcs_ldsc[ln].xmte) { /* xmt enabled? */ c = sim_tt_outcvt (dcs_buf[ln] & 0177, TT_GET_MODE (uptr->flags)); - if (c >= 0) tmxr_putc_ln (&dcs_ldsc[ln], c); /* output char */ + if (c >= 0) /* output char */ + tmxr_putc_ln (&dcs_ldsc[ln], c); tmxr_poll_tx (&dcs_desc); /* poll xmt */ } else { /* buf full */ @@ -298,8 +303,10 @@ void dcs_scan_next (t_bool unlk) { int32 i; -if (unlk) iosta &= ~IOS_DCS; /* unlock? */ -else if (iosta & IOS_DCS) return; /* no, locked? */ +if (unlk) /* unlock? */ + iosta &= ~IOS_DCS; +else if (iosta & IOS_DCS) /* no, locked? */ + return; for (i = 0; i < DCS_LINES; i++) { /* scan flags */ dcs_scan = (dcs_scan + 1) & DCS_LINE_MASK; /* next flag */ if (dcs_flg[dcs_scan] != 0) { /* flag set? */ @@ -323,7 +330,8 @@ else dcsl_dev.flags = dcsl_dev.flags & ~DEV_DIS; if (dcs_unit.flags & UNIT_ATT) /* master att? */ sim_activate_abs (&dcs_unit, tmxr_poll); /* activate */ else sim_cancel (&dcs_unit); /* else stop */ -for (i = 0; i < DCS_LINES; i++) dcs_reset_ln (i); /* reset lines */ +for (i = 0; i < DCS_LINES; i++) /* reset lines */ + dcs_reset_ln (i); dcs_send = 0; dcs_scan = 0; iosta &= ~IOS_DCS; /* clr intr req */ @@ -337,7 +345,8 @@ t_stat dcs_attach (UNIT *uptr, char *cptr) t_stat r; r = tmxr_attach (&dcs_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ +if (r != SCPE_OK) /* error */ + return r; sim_activate_abs (uptr, tmxr_poll); /* start poll */ return SCPE_OK; } @@ -350,42 +359,12 @@ int32 i; t_stat r; r = tmxr_detach (&dcs_desc, uptr); /* detach */ -for (i = 0; i < DCS_LINES; i++) dcs_ldsc[i].rcve = 0; /* disable rcv */ +for (i = 0; i < DCS_LINES; i++) /* disable rcv */ + dcs_ldsc[i].rcve = 0; sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat dcs_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < DCS_LINES; i++) t = t + (dcs_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat dcs_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < DCS_LINES; i++) t = t + (dcs_ldsc[i].conn != 0); -if (t) { - for (i = 0; i < DCS_LINES; i++) { - if (dcs_ldsc[i].conn) { - if (val) tmxr_fconns (st, &dcs_ldsc[i], i); - else tmxr_fstats (st, &dcs_ldsc[i], i); - } - } - } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - /* Change number of lines */ t_stat dcs_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -393,12 +372,16 @@ t_stat dcs_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = get_uint (cptr, 10, DCS_LINES, &r); -if ((r != SCPE_OK) || (newln == DCS_NUMLIN)) return r; -if (newln == 0) return SCPE_ARG; +if ((r != SCPE_OK) || (newln == DCS_NUMLIN)) + return r; +if (newln == 0) + return SCPE_ARG; if (newln < DCS_LINES) { - for (i = newln, t = 0; i < DCS_NUMLIN; i++) t = t | dcs_ldsc[i].conn; + for (i = newln, t = 0; i < DCS_NUMLIN; i++) + t = t | dcs_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < DCS_NUMLIN; i++) { diff --git a/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h index ef35bde9..47290d26 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-2006, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c index beffa0a4..5842db1f 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -203,13 +203,16 @@ if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */ 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? */ + if (t <= 0) /* wrap around? */ + t = t + DRM_NUMWDT; 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 */ + if (pulse == 011) + return (stop_inst << IOT_V_REASON) | dat; + if (iosta & IOS_DRM) /* skip if done */ + return (dat | IOT_SKP); break; case 064: /* DSE, DSP */ @@ -231,7 +234,8 @@ if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */ 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? */ + if (t <= 0) /* wrap around? */ + t = t + DRP_NUMWDT; sim_activate (&drp_unit, t); /* start operation */ drp_unit.FUNC = DRP_BRK; /* mark as break */ } @@ -251,7 +255,8 @@ if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */ 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? */ + if (t <= 0) /* wrap around? */ + t = t + DRP_NUMWDT; sim_activate (&drp_unit, t); /* start operation */ iosta = iosta | IOS_DRP; /* set busy */ break; @@ -287,10 +292,12 @@ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ M[drm_ma] = fbuf[da]; /* read word */ } else { /* write */ - if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; + 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; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; } } drm_ma = (drm_ma + 1) & AMASK; /* incr mem addr */ @@ -324,7 +331,8 @@ 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) dev_req_int (drm_sbs); /* req intr */ + if (uptr->FUNC) /* req intr */ + dev_req_int (drm_sbs); return IORETURN (drp_stopioe, SCPE_UNATT); } @@ -340,7 +348,8 @@ if (uptr->FUNC == DRP_RW) { /* read/write? */ } /* end for */ } /* end if */ iosta = iosta & ~IOS_DRP; /* clear busy */ -if (uptr->FUNC) dev_req_int (drm_sbs); /* req intr */ +if (uptr->FUNC) /* req intr */ + dev_req_int (drm_sbs); return SCPE_OK; } diff --git a/PDP1/pdp1_dt.c b/PDP1/pdp1_dt.c index 731fc8f6..2c902f62 100644 --- a/PDP1/pdp1_dt.c +++ b/PDP1/pdp1_dt.c @@ -1,6 +1,6 @@ /* pdp1_dt.c: 18b DECtape simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -180,7 +180,7 @@ #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)) \ - dev_req_int (dt_sbs); + dev_req_int (dt_sbs); #define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT) #define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC) @@ -369,10 +369,12 @@ 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 (unum >= 0) /* get unit */ + uptr = dt_dev.units + unum; if (pulse == 003) { /* MSE */ - if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ + if ((dtsa ^ dat) & DTA_UNIT) /* new unit? */ + dt_deselect (dtsa); dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } @@ -400,7 +402,8 @@ 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_DIR) /* rev? set */ + dtsb = dtsb | DTB_REV; if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) dtsb = dtsb | DTB_GO; /* accel? go */ } @@ -418,7 +421,8 @@ int32 old_unit, old_mot; UNIT *uptr; old_unit = DTA_GETUNIT (oldf); /* get unit no */ -if (old_unit < 0) return; /* invalid? */ +if (old_unit < 0) /* invalid? */ + return; uptr = dt_dev.units + old_unit; /* get unit */ old_mot = DTS_GETMOT (uptr->STATE); if (old_mot >= DTS_ATSF) /* at speed? */ @@ -456,7 +460,8 @@ int32 prev_mving, new_mving, prev_dir, new_dir; UNIT *uptr; new_unit = DTA_GETUNIT (newf); /* new unit */ -if (new_unit < 0) return; /* invalid? */ +if (new_unit < 0) /* invalid? */ + return; uptr = dt_dev.units + new_unit; if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ dt_seterr (uptr, DTB_SEL); /* no, error */ @@ -469,10 +474,12 @@ 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) /* stop to stop */ + return; if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -482,7 +489,8 @@ if (new_mving & ~prev_mving) { /* start? */ if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -492,7 +500,8 @@ if (prev_mving & ~new_mving) { /* stop? */ if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -503,7 +512,8 @@ if (prev_dir ^ new_dir) { /* dir chg? */ } if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* cancel cur */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -538,7 +548,8 @@ int32 fnc, dir, blk, unum, newpos; uint32 oldpos; oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ +if (dt_setpos (uptr)) /* update pos */ + return; uptr->STATE = newsta; /* update state */ fnc = DTS_GETFNC (uptr->STATE); /* set variables */ dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; @@ -556,23 +567,27 @@ dt_substate = DTO_SOB; /* substate = block star switch (fnc) { /* case function */ case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ + if (dir) /* rev? < start */ + newpos = -1000; 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")); + 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")); + 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 */ @@ -580,12 +595,14 @@ switch (fnc) { /* case function */ 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; + 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 (!dir) + newpos = newpos + (DT_WSIZE - 1); } if (DEBUG_PRI (dt_dev, LOG_RW) || (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) @@ -633,7 +650,8 @@ 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 */ +if (ut == 0) /* no time gone? exit */ + return FALSE; uptr->LASTT = new_time; /* update last time */ switch (mot & ~DTS_DIR) { /* case on motion */ @@ -658,7 +676,8 @@ switch (mot & ~DTS_DIR) { /* case on motion */ break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ +if (mot & DTS_DIR) /* update pos */ + uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { @@ -778,13 +797,15 @@ switch (fnc) { /* at speed, check fnc * #endif if ((fnc == FNC_READ) && /* read, skip if not */ (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; + (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); + if (dir) + dtdb = dt_comobv (dtdb); break; /* Write and write all */ @@ -800,9 +821,11 @@ switch (fnc) { /* at speed, check fnc * (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 */ + if (dir) /* get data word */ + fbuf[ba] = dt_comobv (dtdb); else fbuf[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + 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 */ @@ -841,7 +864,8 @@ 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 */ + if (dt_setpos (uptr)) /* update position */ + return; sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); /* state = decel */ } @@ -855,7 +879,8 @@ void dt_schedez (UNIT *uptr, int32 dir) { int32 newpos; -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ +if (dir) /* rev? rev ez */ + newpos = DT_EZLIN - DT_WSIZE; else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); return; @@ -884,7 +909,8 @@ 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; + if (csum > 0777777) + csum = (csum + 1) & 0777777; } return (csum ^ 0777777); /* 1's comp res */ } @@ -895,11 +921,13 @@ 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 */ +if (wrd == DT_BLKWD) /* fwd blknum */ + return blk; +if (wrd == DT_CSMWD) /* rev csum */ + return 0777777; +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 */ +if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */ return dt_comobv (blk); return 0; /* all others */ } @@ -916,7 +944,8 @@ for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ 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 */ + if (dt_setpos (uptr)) /* update pos */ + continue; sim_cancel (uptr); sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); @@ -962,7 +991,8 @@ int32 u = uptr - dt_dev.units; t_stat r; r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ +if (r != SCPE_OK) /* error? */ + return r; if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */ if (sim_switches & SWMASK ('T')) /* att 12b? */ @@ -985,15 +1015,19 @@ if (uptr->filebuf == NULL) { /* can't alloc? */ } 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"); +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 (uint16), D8_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0; + 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); @@ -1007,8 +1041,10 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */ 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; + if (k == 0) + break; + for ( ; k < D18_BSIZE; k++) + pdp11b[k] = 0; for (k = 0; k < D18_BSIZE; k++) fbuf[ba++] = pdp11b[k]; } @@ -1038,7 +1074,8 @@ 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)) /* attached? */ + return SCPE_OK; if (sim_is_active (uptr)) { sim_cancel (uptr); if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { @@ -1061,7 +1098,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ ba = ba + 2; } /* end loop blk */ fxwrite (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; + if (ferror (uptr->fileref)) + break; } /* end loop file */ } /* end if 12b */ else if (uptr->flags & UNIT_11FMT) { /* 16b? */ @@ -1069,12 +1107,14 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ 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; + 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"); + 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 */ diff --git a/PDP1/pdp1_lp.c b/PDP1/pdp1_lp.c index 1b7b058d..a4c49d16 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -179,7 +179,8 @@ 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? */ + if (lpt_ovrpr) /* overprint? */ + fputc ('\r', uptr->fileref); fputs (lpt_buf, uptr->fileref); /* print buffer */ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* test error */ @@ -188,7 +189,8 @@ else { return SCPE_IOERR; } lpt_bptr = 0; - for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ + for (i = 0; i <= LPT_BSIZE; i++) /* clear buffer */ + lpt_buf[i] = 0; lpt_ovrpr = 1; /* set overprint */ } return SCPE_OK; @@ -201,7 +203,8 @@ 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 */ +for (i = 0; i <= LPT_BSIZE; i++) /* clear buffer */ + lpt_buf[i] = 0; lpt_spc = 0; /* clear state */ lpt_ovrpr = 0; /* clear overprint */ cpls = cpls & ~CPLS_LPT; diff --git a/PDP1/pdp1_stddev.c b/PDP1/pdp1_stddev.c index 4ddd114f..c5c9f6bc 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-2006, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -299,14 +299,16 @@ 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 */ +if (dev == 0002) /* RPB, mode = binary */ + ptr_state = 18; 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 */ +if (inst & IO_WAIT) /* set ptr wait */ + ptr_wait = 1; else ptr_wait = 0; /* from IR<5> */ if (GEN_CPLS (inst)) { /* comp pulse? */ ios = 0; @@ -324,8 +326,10 @@ 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; + if (ptr_wait) /* if wait, clr ioh */ + ptr_wait = ioh = 0; + if ((cpls & CPLS_PTR) || ptr_stopioe) + return SCPE_UNATT; return SCPE_OK; } if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */ @@ -333,16 +337,19 @@ if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha rea 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 (ptr_wait) /* if wait, clr ioh */ + ptr_wait = ioh = 0; if (feof (uptr->fileref)) { - if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n"); + 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 */ +if (ptr_state == 0) /* alpha */ + uptr->buf = temp & 0377; else if (temp & 0200) { /* binary */ ptr_state = ptr_state - 6; uptr->buf = uptr->buf | ((temp & 077) << ptr_state); @@ -384,10 +391,13 @@ else { 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 */ + if (c == '\n') /* NL -> CR */ + c = '\r'; + else if (c == '\r') /* ignore CR */ + continue; in = ascii_to_fiodec[c]; /* convert char */ - if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */ + if ((in == 0) && (c != ' ')) /* ignore unknowns */ + continue; if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */ in = in & TT_WIDTH; /* cut to 6b */ else { /* no, case shift */ @@ -434,7 +444,8 @@ int32 ptr_getw (UNIT *uptr) int32 i, tmp, word; for (i = word = 0; i < 3;) { - if ((tmp = getc (uptr->fileref)) == EOF) return -1; + if ((tmp = getc (uptr->fileref)) == EOF) + return -1; uptr->pos = uptr->pos + 1; if (tmp & 0200) { word = (word << 6) | (tmp & 077); @@ -450,11 +461,13 @@ int32 origin, val; int32 fld = TA & EPCMASK; for (;;) { - if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; + 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; + if ((val = ptr_getw (&ptr_unit)) < 0) + return SCPE_FMT; M[fld | origin] = val; } else if ((val & 0760000) == OP_JMP) { /* JMP? */ @@ -548,14 +561,19 @@ if (tti_hold & CW) { /* char waiting? */ tti_hold = 0; /* not waiting */ } else { - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; - if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ + if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) + return temp; + if (temp & SCPE_BREAK) /* ignore break */ + return SCPE_OK; temp = temp & 0177; - if (temp == 0177) temp = '\b'; /* rubout? bs */ + if (temp == 0177) /* rubout? bs */ + temp = '\b'; sim_putchar (temp); /* echo */ - if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */ + if (temp == '\r') /* cr? add nl */ + sim_putchar ('\n'); in = ascii_to_fiodec[temp]; /* translate char */ - if (in == 0) return SCPE_OK; /* no xlation? */ + if (in == 0) /* no xlation? */ + return SCPE_OK; if ((in & BOTH) || ((in & UC) == (tty_uc & UC))) tty_buf = in & TT_WIDTH; else { /* must shift */ @@ -576,8 +594,10 @@ 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? */ +if (tty_buf == FIODEC_UC) /* upper case? */ + tty_uc = UC; +else if (tty_buf == FIODEC_LC) /* lower case? */ + tty_uc = 0; else { c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */ if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) { /* output; error? */ diff --git a/PDP1/pdp1_sys.c b/PDP1/pdp1_sys.c index fd3470c1..d8985cd9 100644 --- a/PDP1/pdp1_sys.c +++ b/PDP1/pdp1_sys.c @@ -1,6 +1,6 @@ /* pdp1_sys.c: PDP-1 simulator interface - Copyright (c) 1993-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -119,7 +119,8 @@ int32 i, tmp, word; word = 0; for (i = 0; i < 3;) { - if ((tmp = getc (inf)) == EOF) return -1; + if ((tmp = getc (inf)) == EOF) + return -1; if (tmp & 0200) { word = (word << 6) | (tmp & 077); i++; @@ -133,11 +134,13 @@ t_stat rim_load (FILE *inf, int32 fld) int32 origin, val; for (;;) { - if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; + 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; + if ((val = pdp1_getw (inf)) < 0) + return SCPE_FMT; M[fld | origin] = val; } else if ((val & 0760000) == OP_JMP) { /* JMP? */ @@ -154,25 +157,34 @@ 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 = pdp1_getw (inf)) < 0) /* get word, EOF? */ + return SCPE_FMT; 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; + if ((val = pdp1_getw (inf)) < 0) + return SCPE_FMT; + if ((val & 0760000) != OP_DIO) + return SCPE_FMT; csum = csum + val; - if (csum > DMASK) csum = (csum + 1) & DMASK; + if (csum > DMASK) + csum = (csum + 1) & DMASK; count = (val & DAMASK) - start; /* block count */ - if (count <= 0) return SCPE_FMT; + if (count <= 0) + return SCPE_FMT; while (count--) { /* loop on data */ - if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; + if ((val = pdp1_getw (inf)) < 0) + return SCPE_FMT; csum = csum + val; - if (csum > DMASK) csum = (csum + 1) & DMASK; + if (csum > DMASK) + csum = (csum + 1) & DMASK; M[fld | start] = val; start = (start + 1) & DAMASK; } - if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; - if (val != csum) return SCPE_CSUM; + 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); @@ -188,15 +200,18 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) t_stat sta; int32 fld; -if (flag != 0) return SCPE_ARG; +if (flag != 0) + return SCPE_ARG; if (cptr && (*cptr != 0)) { fld = get_uint (cptr, 8, AMASK, &sta); - if (sta != SCPE_OK) return 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 (sta != SCPE_OK) + return sta; if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN")) return blk_load (fileref, fld); return SCPE_OK; @@ -435,7 +450,8 @@ 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; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } @@ -449,7 +465,8 @@ if (sw & SWMASK ('C')) { /* character? */ fprintf (of, "%c", SIXTOASC (inst & 077)); return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; /* Instruction decode */ @@ -467,8 +484,10 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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); + 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; @@ -485,19 +504,24 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ case I_V_OPR: /* operates */ sp = fprint_opr (of, inst & 017760, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); + 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"); + if (opcode[i]) + sp = fprintf (of, (sp? " %s": "%s"), opcode[i]); + if (inst & IA) + fprintf (of, sp? " I": "I"); break; case I_V_SPC: /* specials */ sp = fprint_opr (of, inst & 007774, j, 0); - if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]); - if (inst & IA) fprintf (of, sp? " I": "I"); + 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 */ @@ -556,15 +580,21 @@ 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; +for (i = 1; (i < 3) && (cptr[i] != 0); i++) { + if (cptr[i] == 0) { + for (j = i + 1; j <= 3; j++) + cptr[j] = 0; + } + } if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = ((ASCTOSIX (cptr[0]) & 077) << 12) | ((ASCTOSIX (cptr[1]) & 077) << 6) | (ASCTOSIX (cptr[2]) & 077); @@ -573,7 +603,8 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ 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; +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 */ @@ -588,8 +619,10 @@ switch (j) { /* case on class */ 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; + 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; @@ -598,7 +631,8 @@ switch (j) { /* case on class */ 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; + if (r != SCPE_OK) + return SCPE_ARG; val[0] = val[0] | sc_enc[d]; break; @@ -616,14 +650,18 @@ switch (j) { /* case on class */ } 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; + 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? */ +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; return SCPE_OK; } diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index d45516e1..652341d8 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-2007, Robert M. Supnik + Copyright (c) 1993-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -627,14 +627,16 @@ t_stat r; /* Restore register state */ -if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ +if ((r = build_dib_tab ()) != SCPE_OK) /* build, chk dib_tab */ + return r; 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 */ -if (!Q_ITS) its_1pr = 0; /* ~ITS, clr 1-proc */ +if (!Q_ITS) /* ~ITS, clr 1-proc */ + its_1pr = 0; t20_idlelock = 0; /* clr T20 idle lock */ /* Abort handling @@ -659,9 +661,11 @@ if ((abortval > 0) || pager_pi) { /* stop or pi err? */ else if (abortval == PAGE_FAIL) { /* page fail */ d10 mb; - if (rlog) xtcln (rlog); /* clean up extend */ + if (rlog) /* clean up extend */ + xtcln (rlog); rlog = 0; /* clear log */ - if (pager_tc) flags = pager_flags; /* trap? get flags */ + if (pager_tc) /* trap? get flags */ + flags = pager_flags; if (T20PAG) { /* TOPS-20 paging? */ WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */ WriteP (upta + UPT_T20_OFL, XWD (flags, 0)); @@ -672,7 +676,8 @@ else if (abortval == PAGE_FAIL) { /* page fail */ a10 ea; /* TOPS-10 or ITS */ if (Q_ITS) { /* ITS? */ ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3); - if (its_1pr) flags = flags | F_1PR; /* store 1-proc */ + if (its_1pr) /* store 1-proc */ + flags = flags | F_1PR; its_1pr = 0; /* clear 1-proc */ } else ea = upta + UPT_T10_PAG; @@ -699,7 +704,8 @@ 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 */ + if (i = sim_process_event ()) /* error? stop sim */ + ABORT (i); pi_eval (); /* eval pi system */ } @@ -714,9 +720,11 @@ if (qintr) { 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 */ + if (mb == 0) /* invalid? stop */ + ABORT (STOP_ZERINT); inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK); - if (inst == 0) ABORT (STOP_ZERINT); + if (inst == 0) + ABORT (STOP_ZERINT); } else inst = ReadP (epta + EPT_PIIT + (2 * qintr)); op = GET_OP (inst); /* get opcode */ @@ -744,7 +752,8 @@ if (qintr) { 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 */ + if (sim_interval) /* charge for instr */ + sim_interval--; continue; } /* end if interrupt */ @@ -792,15 +801,18 @@ 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); + 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; + 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; @@ -810,7 +822,9 @@ switch (op) { /* case on opcode */ /* UUO's (0000 - 0077) - checked against KS10 ucode */ -case 0000: if (stop_op0) { ABORT (STOP_ILLEG); } +case 0000: if (stop_op0) { + ABORT (STOP_ILLEG); + } goto MUUO; case 0001: /* local UUO's */ case 0002: @@ -854,12 +868,14 @@ case 0037: Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */ /* case 0101: MUUO /* unassigned */ case 0102: if (Q_ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */ inst = Read (ea, MM_OPND); - pflgs = pflgs | ac; goto XCT; + pflgs = pflgs | ac; + goto XCT; } goto MUUO; case 0103: if (Q_ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */ inst = Read (ea, MM_OPND); - pflgs = pflgs | ac; goto XCT; + pflgs = pflgs | ac; + goto XCT; } goto MUUO; /* case 0104: MUUO /* JSYS (T20) */ @@ -895,7 +911,8 @@ 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 */ +case 0133: if (!ac) /* IBP */ + ibp (ea, pflgs); else adjbp (ac, ea, pflgs); break; case 0134: CIBP; LDB; CLRF (F_FPD); break; /* ILBP */ case 0135: LDB; break; /* LDB */ @@ -952,7 +969,8 @@ 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) = NEG (IM); /* MOVNI */ - if (AC(ac) == 0) SETF (F_C0 | F_C1); break; + if (AC(ac) == 0) SETF (F_C0 | F_C1); + break; 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 */ @@ -979,7 +997,8 @@ 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; + 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 */ @@ -1001,7 +1020,8 @@ case 0256: if (xct_cnt++ >= xct_max) /* XCT */ pflgs = pflgs | ac; goto XCT; case 0257: if (Q_ITS) goto MUUO; /* MAP */ - AC(ac) = map (ea, MM_OPND); break; + 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 */ @@ -1376,7 +1396,8 @@ MUUO: (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 */ + if (TSTF (F_USR)) /* set PCU */ + mb = mb | XWD (F_UIO, 0); set_newflags (mb, FALSE); /* set new flags */ break; @@ -1452,7 +1473,8 @@ case 0254: /* JRST */ break; case 015: /* JRST 15 = XJRST */ - if (!T20PAG) goto MUUO; /* only in TOPS20 paging */ + if (!T20PAG) /* only in TOPS20 paging */ + goto MUUO; JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */ break; } /* end case subop */ @@ -1498,15 +1520,18 @@ d10 r; r = (a + b) & DMASK; if (TSTS (a & b)) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ + if (TSTS (r)) /* case 8 */ + SETF (F_C0 | F_C1); 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 */ + if (TSTS (r)) /* case 2 */ + SETF (F_C1 | F_AOV | F_T1); return r; /* case 1 */ } -if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ +if (!TSTS (r)) /* cases 3,5 */ + SETF (F_C0 | F_C1); return r; } @@ -1518,15 +1543,18 @@ d10 r; r = (a - b) & DMASK; if (TSTS (a & ~b)) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ + if (TSTS (r)) /* case 8 */ + SETF (F_C0 | F_C1); 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 */ + if (TSTS (r)) /* case 2 */ + SETF (F_C1 | F_AOV | F_T1); return r; /* case 1 */ } -if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ +if (!TSTS (r)) /* cases 3,5 */ + SETF (F_C0 | F_C1); return r; } @@ -1537,8 +1565,10 @@ d10 lsh (d10 val, a10 ea) { int32 sc = LIT8 (ea); -if (sc > 35) return 0; -if (ea & RSIGN) return (val >> sc); +if (sc > 35) + return 0; +if (ea & RSIGN) + return (val >> sc); return ((val << sc) & DMASK); } @@ -1548,8 +1578,10 @@ d10 rot (d10 val, a10 ea) { int32 sc = LIT8 (ea) % 36; -if (sc == 0) return val; -if (ea & RSIGN) sc = 36 - sc; +if (sc == 0) + return val; +if (ea & RSIGN) + sc = 36 - sc; return (((val << sc) | (val >> (36 - sc))) & DMASK); } @@ -1565,13 +1597,16 @@ 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 */ + if (TSTS (r)) /* case 8 */ + SETF (F_C0 | F_C1); 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 */ + if (TSTS (r)) /* case 2 */ + SETF (F_C1 | F_AOV | F_T1); } -else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ +else if (!TSTS (r)) /* cases 3,5 */ + SETF (F_C0 | F_C1); AC(ac) = r; AC(p1) = TSTS (r)? SETS (AC(p1)): CLRS (AC(p1)); return; @@ -1587,13 +1622,16 @@ 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 */ + if (TSTS (r)) /* case 8 */ + SETF (F_C0 | F_C1); 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 */ + if (TSTS (r)) /* case 2 */ + SETF (F_C1 | F_AOV | F_T1); } -else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ +else if (!TSTS (r)) /* cases 3,5 */ + SETF (F_C0 | F_C1); AC(ac) = r; AC(p1) = (TSTS (r)? SETS (AC(p1)): CLRS (AC(p1))) & DMASK; return; @@ -1607,7 +1645,8 @@ void lshc (int32 ac, a10 ea) int32 p1 = ADDAC (ac, 1); int32 sc = LIT8 (ea); -if (sc > 71) AC(ac) = AC(p1) = 0; +if (sc > 71) + AC(ac) = AC(p1) = 0; else if (ea & RSIGN) { if (sc >= 36) { AC(p1) = AC(ac) >> (sc - 36); @@ -1639,8 +1678,10 @@ int32 p1 = ADDAC (ac, 1); int32 sc = LIT8 (ea) % 72; d10 t = AC(ac); -if (sc == 0) return; -if (ea & RSIGN) sc = 72 - sc; +if (sc == 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; @@ -1661,12 +1702,15 @@ d10 sign = TSTS (val); d10 fill = sign? ONES: 0; d10 so; -if (sc == 0) return val; -if (sc > 35) sc = 35; /* cap sc at 35 */ +if (sc == 0) + return val; +if (sc > 35) /* cap sc at 35 */ + sc = 35; if (ea & RSIGN) return (((val >> sc) | (fill << (36 - sc))) & DMASK); so = val >> (35 - sc); /* bits lost left + sign */ -if (so != (sign? bytemask[sc + 1]: 0)) SETF (F_AOV | F_T1); +if (so != (sign? bytemask[sc + 1]: 0)) + SETF (F_AOV | F_T1); return (sign | ((val << sc) & MMASK)); } @@ -1678,8 +1722,10 @@ d10 sign = TSTS (AC(ac)); d10 fill = sign? ONES: 0; d10 so; -if (sc == 0) return; -if (sc > 70) sc = 70; /* cap sc at 70 */ +if (sc == 0) + return; +if (sc > 70) /* cap sc at 70 */ + sc = 70; AC(ac) = CLRS (AC(ac)); /* clear signs */ AC(p1) = CLRS (AC(p1)); if (ea & RSIGN) { @@ -1697,13 +1743,15 @@ 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); + (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); + 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); @@ -1727,11 +1775,14 @@ 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); + 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); +if (i >= ind_max) + ABORT (STOP_IND); return ea; } @@ -1751,12 +1802,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; + 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 (TSTS (XR (xr, MM_EA))) + ea = ea & AMASK; } return ea; } @@ -1773,11 +1826,14 @@ 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); + 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); +if (i >= ind_max) + ABORT (STOP_IND); return (mb & DMASK); } @@ -1962,8 +2018,10 @@ 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? */ + if (t = sim_process_event ()) /* IO event? */ + return t; + if (pi_eval ()) /* interrupt? */ + return (INTERRUPT); } else sim_interval--; /* count clock */ return 0; @@ -1986,7 +2044,8 @@ d10 left, right; left = ADDL (val, imm); right = ADDR (val, imm); -if (TSTS ((val ^ left) & (~left ^ RLZ (imm)))) SETF (F_T2); +if (TSTS ((val ^ left) & (~left ^ RLZ (imm)))) + SETF (F_T2); return (left | right); } @@ -1998,10 +2057,12 @@ int32 jffo (d10 val) { int32 i, by; -if ((val & DMASK) == 0) return 0; +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); + if (by) + return (pi_m2lvl[by] + i - 1); } return 35; /* must be bit 35 */ } @@ -2019,8 +2080,10 @@ 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 */ +if (sc == 0) /* any shift? */ + return; +if (ea & RSIGN) /* if right, make left */ + sc = 72 - sc; 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; @@ -2055,10 +2118,14 @@ 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 (ea & APR_SENB) /* set enables? */ + apr_enb = apr_enb | bits; +if (ea & APR_CENB) /* clear enables? */ + apr_enb = apr_enb & ~bits; +if (ea & APR_CFLG) /* clear flags? */ + apr_flg = apr_flg & ~bits; +if (ea & APR_SFLG) /* set flags? */ + apr_flg = apr_flg | bits; if (apr_flg & APRF_ITC) { /* interrupt console? */ fe_intr (); /* explicit callout */ apr_flg = apr_flg & ~APRF_ITC; /* interrupt clears */ @@ -2094,7 +2161,8 @@ 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 (!TSTF (F_UIO)) /* if !UIO, can't set */ + fl = fl & ~F_UIO; } if (Q_ITS && (fl & F_1PR)) { /* ITS 1-proceed? */ its_1pr = 1; /* set flag */ @@ -2133,13 +2201,20 @@ 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? */ +if (ea & PI_INIT) + pi_on = pi_enb = pi_act = pi_prq = 0; +if (ea & PI_CPRQ) /* clear prog reqs? */ + pi_prq = pi_prq & ~lvl; +if (ea & PI_SPRQ) /* set prog reqs? */ + pi_prq = pi_prq | lvl; +if (ea & PI_SENB) /* enable levels? */ + pi_enb = pi_enb | lvl; +if (ea & PI_CENB) /* disable levels? */ + pi_enb = pi_enb & ~lvl; +if (ea & PI_SON) /* enable pi? */ + pi_on = 1; +if (ea & PI_CON) /* disable pi? */ + pi_on = 0; pi_eval (); /* eval pi system */ return FALSE; } @@ -2181,7 +2256,8 @@ if (pi_on) { 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; + if ((actlvl == 0) || (reqlvl < actlvl)) + qintr = reqlvl; } return qintr; } @@ -2208,10 +2284,13 @@ hsb = (Q_ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */ set_dyn_ptrs (); set_ac_display (ac_cur); pi_eval (); -if (M == NULL) M = (d10 *) calloc (MAXMEMSIZE, sizeof (d10)); -if (M == NULL) return SCPE_MEM; +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; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -2221,14 +2300,18 @@ return SCPE_OK; 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; +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 >= MAXMEMSIZE) + return SCPE_REL; } - if (ea >= MEMSIZE) return SCPE_NXM; + if (ea >= MEMSIZE) + return SCPE_NXM; *vptr = M[ea] & DMASK; } return SCPE_OK; @@ -2238,13 +2321,16 @@ 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; +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 >= MAXMEMSIZE) + return SCPE_REL; } - if (ea >= MEMSIZE) return SCPE_NXM; + if (ea >= MEMSIZE) + return SCPE_NXM; M[ea] = val & DMASK; } return SCPE_OK; @@ -2259,8 +2345,10 @@ REG *rptr; int i; rptr = find_reg ("AC0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i); +if (rptr == NULL) + return; +for (i = 0; i < AC_NUM; i++, rptr++) + rptr->loc = (void *) (acbase + i); return; } @@ -2272,12 +2360,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -2286,7 +2376,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -2304,14 +2395,17 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index 7bd35852..5c8bfc30 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -760,6 +760,7 @@ 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 show_vec_mux (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat auto_config (char *name, int32 num); int32 clk_cosched (int32 wait); diff --git a/PDP10/pdp10_fe.c b/PDP10/pdp10_fe.c index 83a1e665..43df088c 100644 --- a/PDP10/pdp10_fe.c +++ b/PDP10/pdp10_fe.c @@ -143,8 +143,10 @@ t_stat fei_svc (UNIT *uptr) int32 temp; sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return temp; +if (temp & SCPE_BREAK) /* ignore break */ + return SCPE_OK; uptr->buf = temp & 0177; uptr->pos = uptr->pos + 1; M[FE_CTYIN] = uptr->buf | FE_CVALID; /* put char in mem */ diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index 5ec67958..b37e8039 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -71,13 +71,16 @@ #include "pdp10_defs.h" #include +#include "sim_sock.h" +#include "sim_tmxr.h" #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; \ + 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); \ @@ -195,10 +198,12 @@ t_bool io710 (int32 ac, a10 ea) { d10 val; -if (Q_ITS) AC(ac) = ReadIO (IO_UBA3 | ea); /* IORDI */ +if (Q_ITS) /* IORDI */ + AC(ac) = ReadIO (IO_UBA3 | ea); else { /* TIOE */ val = ReadIO (ea); /* read word */ - if ((AC(ac) & val) == 0) return TRUE; + if ((AC(ac) & val) == 0) + return TRUE; } return FALSE; } @@ -212,10 +217,12 @@ t_bool io711 (int32 ac, a10 ea) { d10 val; -if (Q_ITS) AC(ac) = ReadIO (IO_UBA1 | ea); /* IORDQ */ +if (Q_ITS) /* IORDQ */ + AC(ac) = ReadIO (IO_UBA1 | ea); else { /* TION */ val = ReadIO (ea); /* read word */ - if ((AC(ac) & val) != 0) return TRUE; + if ((AC(ac) & val) != 0) + return TRUE; } return FALSE; } @@ -248,7 +255,8 @@ void io714 (d10 val, a10 ea) d10 temp; val = val & 0177777; -if (Q_ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */ +if (Q_ITS) /* IOWRI */ + WriteIO (IO_UBA3 | ea, val, WRITE); else { temp = ReadIO (ea); /* BSIO */ temp = temp | val; @@ -266,7 +274,8 @@ void io715 (d10 val, a10 ea) d10 temp; val = val & 0177777; -if (Q_ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */ +if (Q_ITS) /* IOWRQ */ + WriteIO (IO_UBA1 | ea, val, WRITE); else { temp = ReadIO (ea); /* BCIO */ temp = temp & ~val; @@ -291,7 +300,8 @@ if (Q_ITS) { /* IORDBI */ else { /* TIOEB */ val = ReadIO (eaRB); val = GETBYTE (ea, val); - if ((AC(ac) & val) == 0) return TRUE; + if ((AC(ac) & val) == 0) + return TRUE; } return FALSE; } @@ -312,7 +322,8 @@ if (Q_ITS) { /* IORDBQ */ else { /* TIONB */ val = ReadIO (eaRB); val = GETBYTE (ea, val); - if ((AC(ac) & val) != 0) return TRUE; + if ((AC(ac) & val) != 0) + return TRUE; } return FALSE; } @@ -348,7 +359,8 @@ void io724 (d10 val, a10 ea) d10 temp; val = val & 0377; -if (Q_ITS) WriteIO (IO_UBA3 | ea, val, WRITEB); /* IOWRBI */ +if (Q_ITS) /* IOWRBI */ + WriteIO (IO_UBA3 | ea, val, WRITEB); else { temp = ReadIO (eaRB); /* BSIOB */ temp = GETBYTE (ea, temp); @@ -367,7 +379,8 @@ void io725 (d10 val, a10 ea) d10 temp; val = val & 0377; -if (Q_ITS) WriteIO (IO_UBA1 | ea, val, WRITEB); /* IOWRBQ */ +if (Q_ITS) /* IOWRBQ */ + WriteIO (IO_UBA1 | ea, val, WRITEB); else { temp = ReadIO (eaRB); /* BCIOB */ temp = GETBYTE (ea, temp); @@ -423,8 +436,9 @@ a10 Map_Addr10 (a10 ba, int32 ub) a10 pa10; int32 vpn = PAG_GETVPN (ba >> 2); /* get PDP-10 page number */ -if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || - ((ubmap[ub][vpn] & UMAP_VLD) == 0)) return -1; /* invalid map? */ +if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || /* invalid map? */ + ((ubmap[ub][vpn] & UMAP_VLD) == 0)) + return -1; pa10 = (ubmap[ub][vpn] + PAG_GETOFF (ba >> 2)) & PAMASK; return pa10; } @@ -499,7 +513,8 @@ for ( ; ba < lim; ba++) { /* by bytes */ return (lim - ba); /* return bc */ } val = *buf++; /* get data */ - if (ba & 2) M[pa10] = (M[pa10] & 0777777600000) | val; + if (ba & 2) + M[pa10] = (M[pa10] & 0777777600000) | val; else M[pa10] = (M[pa10] & 0600000777777) | (val << 18); } return 0; @@ -533,15 +548,18 @@ 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; + (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; + (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](); + if (int_ack[i]) + return int_ack[i](); return int_vec[i]; /* return vector */ } } @@ -554,7 +572,8 @@ t_stat ubmap_rd (int32 *val, int32 pa, int32 mode) { int32 n = iocmap[GET_IOUBA (pa)]; -if (n < 0) ABORT (STOP_ILLIOC); +if (n < 0) + ABORT (STOP_ILLIOC); *val = ubmap[n][pa & UMAP_AMASK]; return SCPE_OK; } @@ -563,7 +582,8 @@ t_stat ubmap_wr (int32 val, int32 pa, int32 mode) { int32 n = iocmap[GET_IOUBA (pa)]; -if (n < 0) ABORT (STOP_ILLIOC); +if (n < 0) + ABORT (STOP_ILLIOC); ubmap[n][pa & UMAP_AMASK] = UMAP_POSFL (val) | UMAP_POSPN (val); return SCPE_OK; } @@ -574,9 +594,12 @@ t_stat ubs_rd (int32 *val, int32 pa, int32 mode) { int32 n = iocmap[GET_IOUBA (pa)]; -if (n < 0) ABORT (STOP_ILLIOC); -if (int_req & ubabr76[n]) ubcs[n] = ubcs[n] | UBCS_HI; -if (int_req & ubabr54[n]) ubcs[n] = ubcs[n] | UBCS_LO; +if (n < 0) + ABORT (STOP_ILLIOC); +if (int_req & ubabr76[n]) + ubcs[n] = ubcs[n] | UBCS_HI; +if (int_req & ubabr54[n]) + ubcs[n] = ubcs[n] | UBCS_LO; *val = ubcs[n] = ubcs[n] & ~UBCS_RDZ; return SCPE_OK; } @@ -585,14 +608,17 @@ t_stat ubs_wr (int32 val, int32 pa, int32 mode) { int32 n = iocmap[GET_IOUBA (pa)]; -if (n < 0) ABORT (STOP_ILLIOC); +if (n < 0) + ABORT (STOP_ILLIOC); if (val & UBCS_INI) { reset_all (5); /* start after UBA */ ubcs[n] = val & UBCS_DXF; } else ubcs[n] = val & UBCS_RDW; -if (int_req & ubabr76[n]) ubcs[n] = ubcs[n] | UBCS_HI; -if (int_req & ubabr54[n]) ubcs[n] = ubcs[n] | UBCS_LO; +if (int_req & ubabr76[n]) + ubcs[n] = ubcs[n] | UBCS_HI; +if (int_req & ubabr54[n]) + ubcs[n] = ubcs[n] | UBCS_LO; return SCPE_OK; } @@ -615,7 +641,8 @@ t_stat uba_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { int32 uba = uptr - uba_unit; -if (addr >= UMAP_MEMSIZE) return SCPE_NXM; +if (addr >= UMAP_MEMSIZE) + return SCPE_NXM; *vptr = ubmap[uba][addr]; return SCPE_OK; } @@ -624,7 +651,8 @@ t_stat uba_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { int32 uba = uptr - uba_unit; -if (addr >= UMAP_MEMSIZE) return SCPE_NXM; +if (addr >= UMAP_MEMSIZE) + return SCPE_NXM; ubmap[uba][addr] = (int32) val & UMAP_MASK; return SCPE_OK; } @@ -636,7 +664,8 @@ 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; + for (i = 0; i < UMAP_MEMSIZE; i++) + ubmap[uba][i] = 0; } pi_eval (); return SCPE_OK; @@ -651,17 +680,23 @@ DIB *dibp; uint32 newba; t_stat r; -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; +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; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; newba = (uint32) get_uint (cptr, 8, PAMASK, &r); /* get new */ -if ((r != SCPE_OK) || (newba == dibp->ba)) return r; -if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; -if (newba % ((uint32) val)) return SCPE_ARG; /* check modulus */ -if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; +if ((r != SCPE_OK) || (newba == dibp->ba)) + return r; +if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) + return SCPE_ARG; +if (newba % ((uint32) val)) /* check modulus */ + return SCPE_ARG; dibp->ba = newba; /* store */ return SCPE_OK; } @@ -673,11 +708,14 @@ t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; +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); @@ -693,16 +731,21 @@ DIB *dibp; uint32 newvec; t_stat r; -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; +if (cptr == NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; newvec = (uint32) get_uint (cptr, 8, VEC_Q + 01000, &r); if ((r != SCPE_OK) || (newvec == VEC_Q) || ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; + (newvec & ((dibp->vnum > 1)? 07: 03))) + return SCPE_ARG; dibp->vec = newvec; return SCPE_OK; } @@ -715,22 +758,39 @@ DEVICE *dptr; DIB *dibp; uint32 vec, numvec; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; vec = dibp->vec; -if (arg) numvec = arg; +if (arg) + numvec = arg; else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); +if (vec == 0) + fprintf (st, "no vector"); else { fprintf (st, "vector=%o", vec); - if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); + if (numvec > 1) + fprintf (st, "-%o", vec + (4 * (numvec - 1))); } return SCPE_OK; } +/* Show vector for terminal multiplexor */ + +t_stat show_vec_mux (FILE *st, UNIT *uptr, int32 arg, void *desc) +{ +TMXR *mp = (TMXR *) desc; + +if ((mp == NULL) || (arg == 0)) + return SCPE_IERR; +return show_vec (st, uptr, ((mp->lines * 2) / arg), desc); +} + /* Test for conflict in device addresses */ t_bool dev_conflict (DIB *curr) @@ -743,16 +803,17 @@ 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; + (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); + if (sim_log) + fprintf (sim_log, "Device %s address conflict at %08o\n", + sim_dname (dptr), dibp->ba); return TRUE; } } @@ -763,7 +824,8 @@ return FALSE; void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) { -if (iack != NULL) int_ack[vloc] = iack; +if (iack != NULL) + int_ack[vloc] = iack; else int_vec[vloc] = ivec; return; } @@ -783,23 +845,27 @@ for (i = 0; i < 32; i++) { /* clear intr tables */ 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; + 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? */ + if (j >= DIB_MAX) /* too many? */ + return SCPE_IERR; } } /* end if enabled */ } /* end for */ for (i = 0; (dibp = std_dib[i]) != NULL; i++) { /* loop thru std */ dib_tab[j++] = dibp; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; /* too many? */ + if (j >= DIB_MAX) /* too many? */ + return SCPE_IERR; } 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 */ + if (dev_conflict (dibp)) /* for conflicts */ + return SCPE_STOP; } return SCPE_OK; } diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index c7af5a95..64f2ccba 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -1,6 +1,6 @@ /* pdp10_lp20.c: PDP-10 LP20 line printer simulator - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2009, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -291,17 +291,19 @@ 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 (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_INIT) /* init? */ + lp20_reset (&lp20_dev); if (data & CSA_GO) { /* go set? */ if ((lpcsa & CSA_GO) == 0) { /* not set before? */ - if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE; + if (lpcsb & CSB_ERR) + lpcsb = lpcsb | CSB_GOE; lpcsum = 0; /* clear checksum */ sim_activate (&lp20_unit, lp20_unit.wait); } @@ -314,27 +316,27 @@ switch ((pa >> 1) & 07) { /* case on PA<3:1> */ break; /* ignore writes to TEST */ case 02: /* LPBA */ - if (access == WRITEB) data = (pa & 1)? - (lpba & 0377) | (data << 8): (lpba & ~0377) | data; + 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; + 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; + 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; + 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; @@ -344,7 +346,8 @@ switch ((pa >> 1) & 07) { /* case on PA<3:1> */ lpcolc = data & 0377; else { lpcbuf = data & 0377; /* even byte, word */ - if (access == WRITE) lpcolc = (data >> 8) & 0377; + if (access == WRITE) + lpcolc = (data >> 8) & 0377; } break; @@ -366,16 +369,20 @@ return SCPE_OK; actions : = print_input, print_xlate, davfu_action, interrupt if (inter) { - if (!xlate || delim || delim_hold) interrupt; - else if (paper) davfu_action; + if (!xlate || delim || delim_hold) + interrupt; + else if (paper) + davfu_action; else print_xlate; } else if (paper) { - if (xlate || delim || delim_hold) davfu_action; + if (xlate || delim || delim_hold) + davfu_action; else print_input; } else { - if (xlate || delim || delim_hold) print_xlate; + if (xlate || delim || delim_hold) + print_xlate; else print_input; } */ @@ -434,15 +441,16 @@ for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { dvld = dvlnt = 0; /* reset lnt */ else if (lpcbuf == 0357) { /* stop DVU load? */ dvptr = 0; /* reset ptr */ - if (dvld & 1) dvlnt = 0; /* if odd, invalid */ + if (dvld & 1) /* if odd, invalid */ + dvlnt = 0; } 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); + if (dvlnt < DV_SIZE) + davfu[dvlnt++] = temp | ((lpcbuf & DV_DMASK) << 6); dvld = 0; } break; @@ -453,7 +461,8 @@ for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { 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; + 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 */ @@ -486,7 +495,8 @@ for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { 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 */ +if (lpbc) /* intr, but not done */ + update_lpcs (CSA_MBZ); else update_lpcs (CSA_DONE); /* intr and done */ if ((fnc == FNC_PR) && ferror (lp20_unit.fileref)) { perror ("LP I/O error"); @@ -511,10 +521,14 @@ 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 */ +if (lppdat == 000) /* NUL? no op */ + return TRUE; +if (lppdat == 012) /* LF? adv carriage */ + return lp20_adv (1, TRUE); +if (lppdat == 014) /* FF? top of form */ + return lp20_davfu (DV_TOF); +if (lppdat == 015) /* CR? reset col cntr */ + lpcolc = 0; else if (lppdat == 011) { /* TAB? simulate */ lppdat = ' '; /* with spaces */ if (lpcolc >= 128) { @@ -524,7 +538,8 @@ else if (lppdat == 011) { /* TAB? simulate */ else rpt = 8 - (lpcolc & 07); /* else adv 1 to 8 */ } else { - if (lppdat < 040) lppdat = ' '; /* cvt non-prnt to spc */ + if (lppdat < 040) /* cvt non-prnt to spc */ + lppdat = ' '; if (lpcolc >= LP_WIDTH) /* line full? */ r = lp20_adv (1, TRUE); /* adv carriage */ } @@ -539,12 +554,14 @@ t_bool lp20_adv (int32 cnt, t_bool dvuadv) { int32 i; -if (cnt == 0) return TRUE; +if (cnt == 0) + return TRUE; lpcolc = 0; /* reset col cntr */ for (i = 0; i < cnt; i++) fputc ('\n', lp20_unit.fileref); lp20_unit.pos = ftell (lp20_unit.fileref); /* print 'n' newlines */ -if (dvuadv) dvptr = (dvptr + cnt) % dvlnt; /* update DAVFU ptr */ +if (dvuadv) /* update DAVFU ptr */ + dvptr = (dvptr + cnt) % dvlnt; 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 */ @@ -562,13 +579,17 @@ t_bool lp20_davfu (int32 cnt) { int i; -if (cnt > DV_MAX) cnt = 7; /* inval chan? */ +if (cnt > DV_MAX) /* inval chan? */ + cnt = 7; for (i = 0; i < dvlnt; i++) { /* search DAVFU */ dvptr = dvptr + 1; /* adv DAVFU ptr */ - if (dvptr >= dvlnt) dvptr = 0; /* wrap at end */ + if (dvptr >= dvlnt) /* wrap at end */ + dvptr = 0; 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? */ + if (cnt) /* ~TOF, adv */ + return lp20_adv (i + 1, FALSE); + if (lpcolc) /* TOF, need newline? */ + lp20_adv (1, FALSE); fputc ('\f', lp20_unit.fileref); /* print form feed */ lp20_unit.pos = ftell (lp20_unit.fileref); if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */ @@ -576,7 +597,7 @@ for (i = 0; i < dvlnt; i++) { /* search DAVFU */ return TRUE; } else { - lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ + lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ return FALSE; } } @@ -589,7 +610,8 @@ return FALSE; void update_lpcs (int32 flg) { -if (flg) lp20_irq = 1; /* set int req */ +if (flg) /* set int req */ + lp20_irq = 1; 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) { @@ -601,8 +623,10 @@ if (dvlnt) { lpcsa = lpcsa | CSA_DVON; lpcsb = lpcsb & ~CSB_DVOF; } -if (lpcsb & CSB_ERR) lpcsa = lpcsa | CSA_ERR; -if ((lpcsa & CSA_IE) && lp20_irq) int_req = int_req | INT_LP20; +if (lpcsb & CSB_ERR) + lpcsa = lpcsa | CSA_ERR; +if ((lpcsa & CSA_IE) && lp20_irq) + int_req = int_req | INT_LP20; else int_req = int_req & ~INT_LP20; return; } @@ -633,8 +657,10 @@ 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 */ +if (lpcsa & CSA_ONL) /* just file chg? */ + return reason; +if (sim_is_active (&lp20_unit)) /* busy? no int */ + update_lpcs (0); else update_lpcs (CSA_MBZ); /* interrupt */ return reason; } @@ -643,7 +669,8 @@ t_stat lp20_detach (UNIT *uptr) { t_stat reason; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; reason = detach_unit (uptr); sim_cancel (&lp20_unit); lpcsa = lpcsa & ~CSA_GO; @@ -655,8 +682,10 @@ t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc) { int i; -if (!get_yn ("Clear DAVFU? [N]", FALSE)) return SCPE_OK; -for (i = 0; i < DV_SIZE; i++) davfu[i] = 0; +if (!get_yn ("Clear DAVFU? [N]", FALSE)) + return SCPE_OK; +for (i = 0; i < DV_SIZE; i++) + davfu[i] = 0; dvlnt = dvptr = 0; update_lpcs (0); return SCPE_OK; diff --git a/PDP10/pdp10_mdfp.c b/PDP10/pdp10_mdfp.c index 348c990a..2aab8688 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -194,8 +194,10 @@ if (dvr == 0) { /* divide by 0? */ } 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 (TSTS (a ^ b)) /* sign of result */ + rs[0] = NEG (rs[0]); +if (TSTS (a)) /* sign of remainder */ + rs[1] = NEG (rs[1]); return TRUE; } @@ -226,7 +228,9 @@ else { rs[1] = r & MMASK; } -if (TSTS (s1 ^ s2)) { MKDNEG (rs); } /* result -? */ +if (TSTS (s1 ^ s2)) { /* result -? */ + MKDNEG (rs); + } else if (TSTS (rs[0])) { /* result +, 2**70? */ SETF (F_AOV | F_T1); /* overflow */ rs[1] = SETS (rs[1]); /* consistent - */ @@ -249,7 +253,9 @@ 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 (TSTS (AC(ac))) { /* make divd positive */ + DMOVN (dvd); + } if (dvd[0] >= dvr) { /* divide fail? */ SETF (F_AOV | F_DCK | F_T1); /* set flags, return */ return FALSE; @@ -271,8 +277,10 @@ else { 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 */ +if (TSTS (AC(ac) ^ b)) /* sign of result */ + rs[0] = NEG (rs[0]); +if (TSTS (AC(ac))) /* sign of remainder */ + rs[1] = NEG (rs[1]); return TRUE; } @@ -291,11 +299,16 @@ 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) */ +if (TSTS (mpc[0])) { /* get abs (mpcnd) */ + DMOVN (mpc); + } +if (TSTS (mpy[0])) { /* get abs (mpyer) */ + DMOVN (mpy); + } 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; +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); @@ -317,7 +330,8 @@ if (TSTS (sign)) { /* result minus? */ 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 */ +else if (TSTS (AC(ac))) /* wrong sign */ + SETF (F_AOV | F_T1); if (TSTS (AC(ac))) { /* if result - */ AC(p1) = SETS (AC(p1)); /* make signs consistent */ AC(p2) = SETS (AC(p2)); @@ -334,16 +348,20 @@ int32 i, cryin; d10 sign, qu[2], dvd[4]; dvd[0] = AC(ac); /* save dividend */ -for (i = 1; i < 4; i++) dvd[i] = CLRS (AC(ADDAC (ac, i))); +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 */ + if (dvd[i]) /* next carry in */ + cryin = 0; } dvd[0] = (~dvd[0] + cryin) & DMASK; } -if (TSTS (dvr[0])) { DMOVN (dvr); } /* get abs (divisor) */ +if (TSTS (dvr[0])) { /* get abs (divisor) */ + DMOVN (dvr); + } else dvr[1] = CLRS (dvr[1]); if (DCMPGE (dvd, dvr)) { /* will divide work? */ SETF (F_AOV | F_DCK | F_T1); /* no, set flags */ @@ -363,8 +381,12 @@ for (i = 0; i < 70; i++) { /* 70 quotient bits */ 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); } +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 */ @@ -388,9 +410,12 @@ 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 */ +if (inv) /* subtract? -b */ + op2 = NEG (op2); +if (op1 == 0) /* a = 0? result is b */ + funpack (op2, 0, &a, AFRC); +else if (op2 == 0) /* b = 0? result is a */ + funpack (op1, 0, &a, AFRC); else { funpack (op1, 0, &a, SFRC); /* unpack operands */ funpack (op2, 0, &b, SFRC); /* fracs are 2's comp */ @@ -401,8 +426,10 @@ else { 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) */ + if (ediff > 63) /* cap diff at 63 */ + ediff = 63; + if (ediff) /* shift b (signed) */ + b.fhi = (t_int64) b.fhi >> ediff; a.fhi = a.fhi + b.fhi; /* add fractions */ if (a.sign ^ b.sign) { /* add or subtract? */ if (a.fhi & FP_UCRY) { /* subtract, frac -? */ @@ -412,7 +439,8 @@ else { else a.sign = 0; /* result is + */ } else { - if (a.sign) a.fhi = UNEG (a.fhi); /* add, src -? comp */ + if (a.sign) /* add, src -? comp */ + a.fhi = UNEG (a.fhi); if (a.fhi & FP_UCRY) { /* check for carry */ a.fhi = a.fhi >> 1; /* flo won't be used */ a.exp = a.exp + 1; @@ -436,7 +464,8 @@ 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? */ +if ((a.fhi == 0) || (b.fhi == 0)) /* either 0? */ + return 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 */ @@ -489,9 +518,11 @@ d10 fsc (d10 val, a10 ea) int32 sc = LIT8 (ea); UFP a; -if (val == 0) return 0; +if (val == 0) + return 0; funpack (val, 0, &a, AFRC); /* unpack operand */ -if (ea & RSIGN) a.exp = a.exp - sc; /* adjust exponent */ +if (ea & RSIGN) /* adjust exponent */ + a.exp = a.exp - sc; else a.exp = a.exp + sc; fnorm (&a, 0); /* renormalize */ return fpack (&a, NULL, FALSE); /* pack result */ @@ -521,16 +552,20 @@ t_uint64 so; UFP a; funpack (mb, 0, &a, AFRC); /* unpack operand */ -if (a.exp > (FP_BIAS + FP_N_FHI + FP_N_EXP)) SETF (F_AOV | F_T1); -else if (a.exp < FP_BIAS) AC(ac) = 0; /* < 1/2? */ +if (a.exp > (FP_BIAS + FP_N_FHI + FP_N_EXP)) + SETF (F_AOV | F_T1); +else if (a.exp < FP_BIAS) /* < 1/2? */ + AC(ac) = 0; else { sc = FP_V_UNORM - (a.exp - FP_BIAS) + 1; AC(ac) = a.fhi >> sc; if (rnd) { so = a.fhi << (64 - sc); - if (so >= (0x8000000000000000 + a.sign)) AC(ac) = AC(ac) + 1; + if (so >= (0x8000000000000000 + a.sign)) + AC(ac) = AC(ac) + 1; } - if (a.sign) AC(ac) = NEG (AC(ac)); + if (a.sign) + AC(ac) = NEG (AC(ac)); } return; } @@ -546,11 +581,13 @@ int32 p1 = ADDAC (ac, 1); int32 ediff; UFP a, b, t; -if (inv) { DMOVN (rs); } /* subtract? -b */ -if ((AC(ac) | AC(p1)) == 0) funpack (rs[0], rs[1], &a, AFRC); - /* a == 0? sum = b */ -else if ((rs[0] | rs[1]) == 0) funpack (AC(ac), AC(p1), &a, AFRC); - /* b == 0? sum = a */ +if (inv) { /* subtract? -b */ + DMOVN (rs); + } +if ((AC(ac) | AC(p1)) == 0) /* a == 0? sum = b */ + funpack (rs[0], rs[1], &a, AFRC); +else if ((rs[0] | rs[1]) == 0) /* b == 0? sum = a */ + funpack (AC(ac), AC(p1), &a, AFRC); else { funpack (AC(ac), AC(p1), &a, SFRC); /* unpack operands */ funpack (rs[0], rs[1], &b, SFRC); @@ -561,7 +598,8 @@ else { b = t; ediff = -ediff; } - if (ediff > 127) ediff = 127; /* cap diff at 127 */ + if (ediff > 127) /* cap diff at 127 */ + ediff = 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 */ @@ -579,7 +617,9 @@ else { else a.sign = 0; /* result is + */ } else { - if (a.sign) { DUNEG (a); }; /* add, src -? comp */ + if (a.sign) { /* add, src -? comp */ + DUNEG (a); + }; if (a.fhi & FP_UCRY) { /* check for carry */ a.fhi = a.fhi >> 1; /* flo won't be used */ a.exp = a.exp + 1; @@ -684,16 +724,18 @@ 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 */ + if (r->fhi) /* extend sign */ + r->fhi = r->fhi | FP_UCRY; 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; + if (r->fhi) + r->fhi = UNEG (r->fhi) & FP_UFRAC; else { - r->exp = r->exp + 1; + r->exp = r->exp + 1; r->fhi = FP_UNORM; } } @@ -725,7 +767,8 @@ if ((a->fhi | a->flo) == 0) { /* if fraction = 0 */ } while ((a->fhi & FP_UNORM) == 0) { /* normalized? */ for (i = 0; i < 6; i++) { - if (a->fhi & normmask[i]) break; + if (a->fhi & normmask[i]) + break; } a->fhi = (a->fhi << normtab[i]) | (a->flo >> (64 - normtab[i])); a->flo = a->flo << normtab[i]; @@ -747,19 +790,25 @@ d10 fpack (UFP *r, d10 *lo, t_bool fdvneg) { d10 val[2]; -if (r->exp < 0) SETF (F_AOV | F_FOV | F_FXU | F_T1); -else if (r->exp > FP_M_EXP) SETF (F_AOV | F_FOV | F_T1); +if (r->exp < 0) + SETF (F_AOV | F_FOV | F_FXU | F_T1); +else if (r->exp > FP_M_EXP) + SETF (F_AOV | F_FOV | F_T1); val[0] = (((((d10) r->exp) & FP_M_EXP) << FP_V_EXP) | ((r->fhi & FP_UFHI) >> FP_V_UFHI)) & DMASK; -if (lo) val[1] = ((r->fhi & FP_UFLO) >> FP_V_UFLO) & MMASK; +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 */ + else { /* 2's comp */ + DMOVN (val); + } } -if (lo) *lo = val[1]; +if (lo) + *lo = val[1]; return val[0]; } diff --git a/PDP10/pdp10_pag.c b/PDP10/pdp10_pag.c index 07b5eebc..3b0fd445 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -165,12 +165,15 @@ d10 Read (a10 ea, int32 prv) { int32 pa, vpn, xpte; -if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ +if (ea < AC_NUM) /* AC request */ + return (prv? ac_prv[ea]: ac_cur[ea]); 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); +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 */ +if (MEM_ADDR_NXM (pa)) /* process nxm */ + pag_nxm (pa, REF_V, PF_TR); return M[pa]; /* return data */ } @@ -178,12 +181,15 @@ d10 ReadM (a10 ea, int32 prv) { int32 pa, vpn, xpte; -if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ +if (ea < AC_NUM) /* AC request */ + return (prv? ac_prv[ea]: ac_cur[ea]); 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); +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 */ +if (MEM_ADDR_NXM (pa)) /* process nxm */ + pag_nxm (pa, REF_V, PF_TR); return M[pa]; /* return data */ } @@ -191,20 +197,26 @@ 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 */ +if (ea < AC_NUM) /* AC? use current */ + return AC(ea); +if (!PAGING) /* phys? no mapping */ + return M[ea]; 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); +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 */ +if (MEM_ADDR_NXM (pa)) /* process nxm */ + pag_nxm (pa, REF_V, PF_TR); 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 */ +if (ea < AC_NUM) /* AC request */ + return AC(ea); +if (MEM_ADDR_NXM (ea)) /* process nxm */ + pag_nxm (ea, REF_P, PF_TR); return M[ea]; /* return data */ } @@ -213,15 +225,18 @@ 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 */ + if (prv) /* write AC */ + ac_prv[ea] = val; 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); + 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 */ + if (MEM_ADDR_NXM (pa)) /* process nxm */ + pag_nxm (pa, REF_V, PF_TR); else M[pa] = val; /* write data */ } return; @@ -231,14 +246,18 @@ 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 */ +if (ea < AC_NUM) /* AC? use current */ + AC(ea) = val; +else if (!PAGING) /* phys? no mapping */ + M[ea] = val; 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); + 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 */ + if (MEM_ADDR_NXM (pa)) /* process nxm */ + pag_nxm (pa, REF_V, PF_TR); else M[pa] = val; /* write data */ } return; @@ -246,9 +265,11 @@ return; void WriteP (a10 ea, d10 val) { -if (ea < AC_NUM) AC(ea) = val; /* AC request */ +if (ea < AC_NUM) /* AC request */ + AC(ea) = val; else { - if (MEM_ADDR_NXM (ea)) pag_nxm (ea, REF_P, PF_TR); /* process nxm */ + if (MEM_ADDR_NXM (ea)) /* process nxm */ + pag_nxm (ea, REF_P, PF_TR); M[ea] = val; /* memory */ } return; @@ -258,12 +279,14 @@ t_bool AccViol (a10 ea, int32 prv, int32 mode) { int32 vpn, xpte; -if (ea < AC_NUM) return FALSE; /* AC request */ +if (ea < AC_NUM) /* AC request */ + return FALSE; 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 */ +if (xpte) /* accessible */ + return FALSE; return TRUE; /* not accessible */ } @@ -273,7 +296,8 @@ 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? */ +if (PAGING && trap) /* trap? */ + ABORT (PAGE_FAIL); return; } @@ -291,7 +315,8 @@ return; page fail word is properly set up. */ -#define PAGE_FAIL_TRAP if (mode & (PTF_CON | PTF_MAP)) return 0; \ +#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); \ @@ -327,7 +352,8 @@ if (Q_ITS) { /* ITS paging */ ((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); + 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); @@ -354,9 +380,12 @@ else if (!T20PAG) { /* TOPS-10 paging */ 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); + 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); @@ -371,7 +400,8 @@ else if (!T20PAG) { /* TOPS-10 paging */ 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 */ + if (!(mode & PTF_CON)) /* set tbl if ~cons */ + tbl[vpn] = xpte; return xpte; } PAGE_FAIL_TRAP; @@ -444,7 +474,8 @@ else { /* TOPS-20 paging */ break; case T20_IND: /* indirect */ - if (flg && (t = test_int ())) ABORT (t); + 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 */ @@ -452,7 +483,9 @@ else { /* TOPS-20 paging */ PAGE_FAIL_TRAP; } READPT (ptr, pa & PAMASK); /* get SPT entry */ - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } + 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 */ @@ -463,11 +496,15 @@ else { /* TOPS-20 paging */ 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 (ptr & PTE_T20_STM) { /* non-res? */ + PAGE_FAIL_TRAP; + } 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; } + if ((cste & CST_AGE) == 0) { + PAGE_FAIL_TRAP; + } cste = (cste & cstm) | pur; /* update entry */ WriteP (csta, cste); /* rewrite */ } @@ -490,7 +527,8 @@ else { /* TOPS-20 paging */ break; case T20_IND: /* indirect */ - if (flg && (t = test_int ())) ABORT (t); + 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 */ @@ -501,11 +539,15 @@ else { /* TOPS-20 paging */ /* Last phase - have final page pointer, check modifiability */ - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } /* non-resident? */ + if (ptr & PTE_T20_STM) { /* non-resident? */ + PAGE_FAIL_TRAP; + } 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; } + if ((cste & CST_AGE) == 0) { + PAGE_FAIL_TRAP; + } cste = (cste & cstm) | pur; /* update entry */ } else cste = 0; /* no, entry = 0 */ @@ -516,14 +558,18 @@ else { /* TOPS-20 paging */ xpte = xpte | PTBL_M; /* set PTE M */ cste = cste | CST_M; /* set CST M */ } - else { PAGE_FAIL_TRAP; } /* no, trap */ + else { /* no, trap */ + PAGE_FAIL_TRAP; + } } - if (cst) WriteP (csta, cste); /* write CST entry */ + if (cst) /* write CST entry */ + WriteP (csta, cste); 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 */ + if (!(mode & PTF_CON)) /* set tbl if ~cons */ + tbl[vpn] = xpte; return xpte; } /* end TOPS20 paging */ } @@ -537,7 +583,8 @@ 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]; + if (TSTF (F_USR)) + ptbl_cur = ptbl_prv = &uptbl[0]; else { ptbl_cur = &eptbl[0]; ptbl_prv = TSTF (F_UIO)? &uptbl[0]: &eptbl[0]; @@ -549,7 +596,8 @@ else { } t = EBR_GETEBR (ebr); epta = t << PAG_V_PN; -if (Q_ITS) upta = (int32) ubr & PAMASK; +if (Q_ITS) + upta = (int32) ubr & PAMASK; else { t = UBR_GETUBR (ubr); upta = t << PAG_V_PN; @@ -569,11 +617,14 @@ d10 map (a10 ea, int32 prv) int32 xpte; d10 val = (TSTF (F_USR)? PF_USER: 0); -if (!PAGING) return (val | PF_T10_A | PF_T10_W | PF_T10_S | ea); +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); +if (xpte) + val = (pager_word & ~PAMASK) | PAG_XPTEPA (xpte, ea); else { - if (pager_word & PF_HARD) val = pager_word; /* hard error */ + if (pager_word & PF_HARD) /* hard error */ + val = pager_word; else val = val | PF_VIRT | ea; /* inaccessible */ } return val; @@ -585,13 +636,17 @@ a10 conmap (a10 ea, int32 mode, int32 sw) { int32 xpte, *tbl; -if (!PAGING) return ea; +if (!PAGING) + return ea; set_dyn_ptrs (); /* in case changed */ -if (sw & SWMASK ('E')) tbl = eptbl; -else if (sw & SWMASK ('U')) tbl = uptbl; +if (sw & SWMASK ('E')) + tbl = eptbl; +else if (sw & SWMASK ('U')) + tbl = uptbl; else tbl = ptbl_cur; xpte = ptbl_fill (ea, tbl, mode); -if (xpte) return PAG_XPTEPA (xpte, ea); +if (xpte) + return PAG_XPTEPA (xpte, ea); else return MAXMEMSIZE; } @@ -633,7 +688,8 @@ t_bool wrubr (a10 ea, int32 prv) d10 val = Read (ea, prv); d10 ubr_mask = (Q_ITS)? PAMASK: UBR_UBRMASK; /* ITS: ubr is wd addr */ -if (val & UBR_SETACB) ubr = ubr & ~UBR_ACBMASK; /* set AC's? */ +if (val & UBR_SETACB) /* set AC's? */ + ubr = ubr & ~UBR_ACBMASK; else val = val & ~UBR_ACBMASK; /* no, keep old val */ if (val & UBR_SETUBR) { /* set UBR? */ ubr = ubr & ~ubr_mask; @@ -817,7 +873,8 @@ t_stat pag_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { int32 tbln = uptr - pag_unit; -if (addr >= PTBL_MEMSIZE) return SCPE_NXM; +if (addr >= PTBL_MEMSIZE) + return SCPE_NXM; *vptr = tbln? uptbl[addr]: eptbl[addr];; return SCPE_OK; } @@ -826,8 +883,10 @@ t_stat pag_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { int32 tbln = uptr - pag_unit; -if (addr >= PTBL_MEMSIZE) return SCPE_NXM; -if (tbln) uptbl[addr] = (int32) val & PTBL_MASK; +if (addr >= PTBL_MEMSIZE) + return SCPE_NXM; +if (tbln) + uptbl[addr] = (int32) val & PTBL_MASK; else eptbl[addr] = (int32) val & PTBL_MASK; return SCPE_OK; } diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c index c384eb6b..ad55f313 100644 --- a/PDP10/pdp10_rp.c +++ b/PDP10/pdp10_rp.c @@ -1,6 +1,6 @@ /* pdp10_rp.c - RH11/RP04/05/06/07 RM02/03/05/80 "Massbus" disk controller - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -541,7 +541,8 @@ switch (j) { /* decode PA<5:1> */ case 007: /* RPAS */ *data = 0; for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); + if (rpds[i] & DS_ATA) + *data = *data | (AS_U0 << i); break; case 010: /* RPLA */ @@ -631,7 +632,8 @@ rmhr[drv] = data; switch (j) { /* decode PA<5:1> */ case 000: /* RPCS1 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; + 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> */ @@ -654,61 +656,71 @@ switch (j) { /* decode PA<5:1> */ 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; + 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; + 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; + 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; + 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? */ + if ((access == WRITEB) && (PA & 1)) + data = data << 8; + if (data & CS2_CLR) /* init? */ + rp_reset (&rp_dev); 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; + if (access == WRITEB) /* merge data */ + data = (rpcs2 & ((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; + if ((access == WRITEB) && (PA & 1)) + data = data << 8; rper1[drv] = data; break; case 007: /* RPAS */ - if ((access == WRITEB) && (PA & 1)) break; + if ((access == WRITEB) && (PA & 1)) + break; for (i = 0; i < RP_NUMDR; i++) - if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; + 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; + 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; + if ((access == WRITEB) && (PA & 1)) + data = data << 8; rpmr[drv] = data; break; @@ -717,7 +729,8 @@ switch (j) { /* decode PA<5:1> */ break; case 016: /* RPDC */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; + if ((access == WRITEB) && (PA & 1)) + data = data << 8; rpdc[drv] = data & ~DC_MBZ; break; @@ -810,7 +823,8 @@ switch (fnc) { /* case on function */ } rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ t = abs (dc - uptr->CYL); /* cyl diff */ - if (t == 0) t = 1; /* min time */ + if (t == 0) /* min time */ + t = 1; sim_activate (uptr, rp_swait * t); /* schedule */ uptr->CYL = dc; /* save cylinder */ return; @@ -934,11 +948,13 @@ switch (uptr->FUNC) { /* case on function */ break; } dbuf[twc10] = M[mpa10]; /* write to disk */ - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; + 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; + for (i = 0; i < fc10; i++) + dbuf[twc10 + i] = 0; } fxwrite (dbuf, sizeof (d10), twc10 + fc10, uptr->fileref); err = ferror (uptr->fileref); @@ -946,7 +962,8 @@ switch (uptr->FUNC) { /* case on function */ else { /* read, wchk, readh */ awc10 = fxread (dbuf, sizeof (d10), wc10, uptr->fileref); err = ferror (uptr->fileref); - for ( ; awc10 < wc10; awc10++) dbuf[awc10] = 0; + for ( ; awc10 < wc10; awc10++) + dbuf[awc10] = 0; for (twc10 = 0; twc10 < wc10; twc10++) { pa10 = ba >> 2; vpn = PAG_GETVPN (pa10); /* map addr */ @@ -969,7 +986,8 @@ switch (uptr->FUNC) { /* case on function */ rpcs2 = rpcs2 | CS2_WCE; /* set error */ break; } - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; + if ((rpcs2 & CS2_UAI) == 0) + ba = ba + 4; } } /* end else */ @@ -977,7 +995,8 @@ switch (uptr->FUNC) { /* case on function */ 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; + 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; @@ -1026,9 +1045,11 @@ UNIT *uptr; if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */ rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ uptr = rp_dev.units + drv; /* get unit */ -if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0; +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; +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; @@ -1036,11 +1057,16 @@ else rpds[drv] = rpds[drv] & ~DS_ERR; rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag; rpcs1 = rpcs1 | (uptr->FUNC << CS1_V_FNC); -if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO; -if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC; -else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC; -for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC; +if (sim_is_active (uptr)) + rpcs1 = rpcs1 | CS1_GO; +if (rpcs2 & CS2_ERR) + rpcs1 = rpcs1 | CS1_TRE | CS1_SC; +else if (rpcs1 & CS1_TRE) + rpcs1 = rpcs1 | CS1_SC; +for (i = 0; i < RP_NUMDR; i++) { + if (rpds[i] & DS_ATA) + rpcs1 = rpcs1 | CS1_SC; + } if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE))) int_req = int_req | INT_RP; else int_req = int_req & ~INT_RP; @@ -1072,9 +1098,11 @@ 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; + 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; @@ -1100,15 +1128,18 @@ t_stat r; uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; 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); rper1[drv] = 0; update_rpcs (CS1_SC, drv); -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if ((p = sim_fsize (uptr->fileref)) == 0) return SCPE_OK; +if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; +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); @@ -1125,7 +1156,8 @@ t_stat rp_detach (UNIT *uptr) { int32 drv; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; 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; @@ -1145,7 +1177,8 @@ t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 dtype = GET_DTYPE (val); -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = drv_tab[dtype].size; return SCPE_OK; } diff --git a/PDP10/pdp10_sys.c b/PDP10/pdp10_sys.c index e22c6d7f..78b1d2c0 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -142,7 +142,8 @@ d10 word; word = 0; for (i = 0; i < 6;) { - if ((tmp = getc (fileref)) == EOF) return -1; + if ((tmp = getc (fileref)) == EOF) + return -1; if (tmp & 0200) { word = (word << 6) | ((d10) tmp & 077); i++; @@ -159,22 +160,27 @@ int32 op; for ( ;; ) { /* loop until JRST */ count = cksm = getrimw (fileref); /* get header */ - if (count < 0) return SCPE_FMT; /* read err? */ + if (count < 0) /* read err? */ + return SCPE_FMT; if (TSTS (count)) { /* hdr = IOWD? */ for ( ; TSTS (count); count = AOB (count)) { data = getrimw (fileref); /* get data wd */ - if (data < 0) return SCPE_FMT; + 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 */ + if (data < 0) + return SCPE_FMT; + if ((cksm + data) & DMASK) /* test cksm */ + return SCPE_CSUM; } /* end if count */ else { op = GET_OP (count); /* not IOWD */ - if (op != OP_JRST) return SCPE_FMT; /* JRST? */ + if (op != OP_JRST) /* JRST? */ + return SCPE_FMT; saved_PC = (a10) count & AMASK; /* set PC */ break; } /* end else */ @@ -203,18 +209,21 @@ int32 wc, op; for ( ;; ) { /* loop */ wc = fxread (&count, sizeof (d10), 1, fileref); /* read IOWD */ - if (wc == 0) return SCPE_OK; /* done? */ + if (wc == 0) /* done? */ + return SCPE_OK; if (TSTS (count)) { /* IOWD? */ for ( ; TSTS (count); count = AOB (count)) { wc = fxread (&data, sizeof (d10), 1, fileref); - if (wc == 0) return SCPE_FMT; + 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? */ + if (op != OP_JRST) /* JRST? */ + return SCPE_FMT; saved_PC = (a10) count & AMASK; /* set PC */ break; } /* end else */ @@ -259,16 +268,20 @@ 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? */ + if (wc == 0) /* error? */ + return SCPE_FMT; bsz = (int32) ((data & RMASK) - 1); /* get count */ - if (bsz <= 0) return SCPE_FMT; /* zero? */ + if (bsz <= 0) /* zero? */ + return SCPE_FMT; bty = (int32) LRZ (data); /* get type */ switch (bty) { /* case type */ case EXE_DIR: /* directory */ - if (ndir) return SCPE_FMT; /* got one */ + if (ndir) /* got one */ + return SCPE_FMT; ndir = fxread (dirbuf, sizeof (d10), bsz, fileref); - if (ndir < bsz) return SCPE_FMT; /* error */ + if (ndir < bsz) /* error */ + return SCPE_FMT; break; case EXE_PDV: /* ??? */ @@ -276,14 +289,17 @@ do { break; case EXE_VEC: /* entry vec */ - if (bsz != 2) return SCPE_FMT; /* must be 2 wds */ + if (bsz != 2) /* must be 2 wds */ + return SCPE_FMT; entvec = fxread (entbuf, sizeof (d10), bsz, fileref); - if (entvec < 2) return SCPE_FMT; /* error? */ + if (entvec < 2) /* error? */ + return SCPE_FMT; cont = 0; /* stop */ break; case EXE_END: /* end */ - if (bsz != 0) return SCPE_FMT; /* must be hdr */ + if (bsz != 0) /* must be hdr */ + return SCPE_FMT; cont = 0; /* stop */ break; @@ -300,12 +316,14 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ 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; + 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; + if (MEM_ADDR_NXM (ma)) + return SCPE_NXM; M[ma] = fpage? (pagbuf[k] & DMASK): 0; } /* end copy */ } /* end rpt */ @@ -324,17 +342,26 @@ 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? */ +if (sim_switches & SWMASK ('R')) /* -r? */ + fmt = FMT_R; +else if (sim_switches & SWMASK ('S')) /* -s? */ + fmt = FMT_S; +else if (sim_switches & SWMASK ('E')) /* -e? */ + fmt = FMT_E; +else if (match_ext (fnam, "RIM")) /* .RIM? */ + fmt = FMT_R; +else if (match_ext (fnam, "SAV")) /* .SAV? */ + fmt = FMT_S; +else if (match_ext (fnam, "EXE")) /* .EXE? */ + fmt = FMT_E; 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? */ + if (wc == 0) /* error? */ + return SCPE_FMT; + if (LRZ (data) == EXE_DIR) /* EXE magic? */ + fmt = FMT_E; + else if (TSTS (data)) /* SAV magic? */ + fmt = FMT_S; fseek (fileref, 0, SEEK_SET); /* rewind */ } @@ -673,7 +700,8 @@ d10 inst; inst = val[0]; cflag = (uptr == NULL) || (uptr == &cpu_unit); if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC ((int32) (inst & 0177))); return SCPE_OK; } @@ -691,7 +719,8 @@ if (sw & SWMASK ('P')) { /* packed? */ } return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; /* Instruction decode */ @@ -709,16 +738,21 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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); + 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]); + 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); + if (inst & INST_IND) + fprintf (of, "@"); + if (xr) + fprintf (of, "%-o(%-o)", y, xr); else fprintf (of, "%-o", y); break; } /* end case */ @@ -748,23 +782,28 @@ if (*cptr == '@') { ind = INST_IND; cptr++; } -if (*cptr == '+') cptr++; +if (*cptr == '+') + cptr++; else if (*cptr == '-') { sign = 1; cptr++; } val = strtotv (cptr, &tptr, 8); -if (val > 0777777) return 0; -if (sign) val = (~val + 1) & 0777777; +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; + (xr > AC_NUM) || (xr == 0)) + return 0; cptr = ++tptr; } -if (*cptr == 0) *status = SCPE_OK; +if (*cptr == 0) + *status = SCPE_OK; return (ind | (xr << 18) | val); } @@ -796,12 +835,14 @@ for (i = 0; i < 6; i++) { } } if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; for (i = 0; i < 6; i++) { val[0] = (val[0] << 6); if (cptr[i]) val[0] = val[0] | @@ -810,8 +851,10 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ 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]); + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; + for (i = 0; i < 5; i++) + val[0] = (val[0] << 7) | ((t_value) cptr[i]); val[0] = val[0] << 1; return SCPE_OK; } @@ -820,7 +863,8 @@ if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ 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; +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 */ @@ -830,14 +874,16 @@ switch (j) { /* case on class */ 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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; break; case I_V_IO: /* I/O */ @@ -845,15 +891,18 @@ switch (j) { /* case on class */ 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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; return SCPE_OK; } diff --git a/PDP10/pdp10_tim.c b/PDP10/pdp10_tim.c index b67dfdaa..726e06f4 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -199,7 +199,7 @@ tim_ttg = tim_period; /* reload */ apr_flg = apr_flg | APRF_TIM; /* request interrupt */ if (Q_ITS) { /* ITS? */ if (pi_act == 0) - quant = (quant + TIM_ITS_QUANT) & DMASK; + quant = (quant + TIM_ITS_QUANT) & DMASK; if (TSTS (pcst)) { /* PC sampling? */ WriteP ((a10) pcst & AMASK, pager_PC); /* store sample */ pcst = AOB (pcst); /* add 1,,1 */ @@ -216,7 +216,8 @@ int32 clk_cosched (int32 wait) { int32 t; -if (tim_mult == TIM_MULT_T20) return wait; +if (tim_mult == TIM_MULT_T20) + return wait; t = sim_is_active (&tim_unit); return (t? t - 1: wait); } @@ -259,7 +260,8 @@ else { uptr->wait = TIM_WAIT_T10; tmr_poll = TIM_WAIT_T10; tim_mult = TIM_MULT_T10; - if (Q_ITS) uptr->flags = uptr->flags | UNIT_Y2K; + if (Q_ITS) + uptr->flags = uptr->flags | UNIT_Y2K; else uptr->flags = uptr->flags & ~UNIT_Y2K; } tmxr_poll = tmr_poll * tim_mult; @@ -275,9 +277,10 @@ struct tm *tptr; curtim = time (NULL); /* get time */ tptr = localtime (&curtim); /* decompose */ -if (tptr == NULL) return SCPE_NXM; /* Y2K prob? */ +if (tptr == NULL) + return SCPE_NXM; if ((tptr->tm_year > 99) && !(tim_unit.flags & UNIT_Y2K)) - tptr->tm_year = 99; + tptr->tm_year = 99; /* Y2K prob? */ switch ((PA >> 1) & 03) { /* decode PA<3:1> */ diff --git a/PDP10/pdp10_tu.c b/PDP10/pdp10_tu.c index a430f716..0e73ec13 100644 --- a/PDP10/pdp10_tu.c +++ b/PDP10/pdp10_tu.c @@ -1,6 +1,6 @@ /* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -438,7 +438,8 @@ update_tucs (0, drv); /* update status */ switch (j) { /* decode PA<4:1> */ case 000: /* MTCS1 */ - if (fmtr != 0) *data = tucs1 & ~CS1_DRV; + if (fmtr != 0) + *data = tucs1 & ~CS1_DRV; else *data = tucs1; break; @@ -526,7 +527,8 @@ if (reg_in_fmtr1[j] && ((tucs1 & CS1_DONE) == 0)) { /* formatter busy? */ switch (j) { /* decode PA<4:1> */ case 000: /* MTCS1 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; + 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> */ @@ -544,67 +546,79 @@ switch (j) { /* decode PA<4:1> */ cs1f = CS1_SC; /* req interrupt */ } else if (tucs1 & CS1_GO) { /* busy? */ - if (tucs1 & CS1_DONE) set_tuer (ER_RMR); + 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); + if (tucs1 & CS1_GO) + tu_go (drv); } } break; case 001: /* MTWC */ - if (access == WRITEB) data = (PA & 1)? - (tuwc & 0377) | (data << 8): (tuwc & ~0377) | data; + 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; + 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; + 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? */ + if ((access == WRITEB) && (PA & 1)) + data = data << 8; + if (data & CS2_CLR) /* init? */ + tu_reset (&tu_dev); 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; + if (access == WRITEB) /* merge data */ + data = (tucs2 & ((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; + 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; + 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; + 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; + 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; @@ -635,9 +649,9 @@ UNIT *uptr; 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 (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 */ @@ -728,7 +742,8 @@ switch (fnc) { /* case on function */ set_tuer (ER_FER); break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ + if (uptr->UDENS == UD_UNK) /* set dens */ + uptr->UDENS = den; uptr->USTAT = 0; goto GO_XFER; @@ -757,7 +772,8 @@ switch (fnc) { /* case on function */ set_tuer (ER_FER); break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ + if (uptr->UDENS == UD_UNK) /* set dens */ + uptr->UDENS = den; uptr->USTAT = 0; tucs1 = tucs1 & ~CS1_DONE; /* clear done */ GO_XFER: @@ -822,7 +838,8 @@ switch (fnc) { /* case on function */ break; } } while ((tufc != 0) && !sim_tape_eot (uptr)); - if (tufc) set_tuer (ER_FCE); + if (tufc) + set_tuer (ER_FCE); else tutc = tutc & ~TC_FCS; tufs = tufs | FS_ATA; break; @@ -835,7 +852,8 @@ switch (fnc) { /* case on function */ break; } } while (tufc != 0); - if (tufc) set_tuer (ER_FCE); + if (tufc) + set_tuer (ER_FCE); else tutc = tutc & ~TC_FCS; tufs = tufs | FS_ATA; break; @@ -872,7 +890,8 @@ switch (fnc) { /* case on function */ 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 */ - if (st == MTSE_TMK) set_tuer (ER_FCE); /* TMK also sets FCE */ + if (st == MTSE_TMK) /* TMK also sets FCE */ + set_tuer (ER_FCE); r = tu_map_err (uptr, st, 1); /* map error */ break; /* done */ } @@ -880,10 +899,13 @@ switch (fnc) { /* case on function */ 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++]; + 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 */ + if (fmt == TC_10C) + val = val | ((d10) xbuf[j++] & 017); + if (fnc == FNC_READF) /* read? store */ + M[mpa10] = val; else if (M[mpa10] != val) { /* wchk, mismatch? */ tucs2 = tucs2 | CS2_WCE; /* flag, stop */ break; @@ -893,7 +915,8 @@ switch (fnc) { /* case on function */ tufc = tbc & 0177777; tuwc = (tuwc + (i << 1)) & 0177777; ba = ba + (i << 2); - if (tuwc) set_tuer (ER_FCE); /* short record? */ + if (tuwc) /* short record? */ + set_tuer (ER_FCE); break; case FNC_WRITE: /* write */ @@ -907,15 +930,18 @@ switch (fnc) { /* case on function */ 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); + if (fmt == TC_10C) + xbuf[j++] = (uint8) (val & 017); mpa10 = mpa10 + 1; } /* end for */ - if (j < fc) fc = j; /* short record? */ + if (j < fc) /* short record? */ + fc = j; 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; + if (tufc == 0) + tutc = tutc & ~TC_FCS; tuwc = (tuwc + (i << 1)) & 0177777; ba = ba + (i << 2); } @@ -926,19 +952,23 @@ switch (fnc) { /* case on function */ 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 */ - if (st == MTSE_TMK) set_tuer (ER_FCE); /* TMK also sets FCE */ + if (st == MTSE_TMK) /* TMK also sets FCE */ + set_tuer (ER_FCE); r = tu_map_err (uptr, st, 1); /* map error */ break; /* done */ } - for (i = 0; i < 4; i++) xbuf[i] = 0; + 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]; + 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 */ + if (fnc == FNC_READR) /* read? store */ + M[mpa10] = val; else if (M[mpa10] != val) { /* wchk, mismatch? */ tucs2 = tucs2 | CS2_WCE; /* flag, stop */ break; @@ -948,18 +978,20 @@ switch (fnc) { /* case on function */ tufc = tbc & 0177777; tuwc = (tuwc + (i << 1)) & 0177777; ba = ba - (i << 2); - if (tuwc) set_tuer (ER_FCE); /* short record? */ + if (tuwc) /* short record? */ + set_tuer (ER_FCE); 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? */ +if (fnc >= FNC_XFER) /* data xfer? */ + update_tucs (CS1_DONE, drv); 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); +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); return SCPE_OK; } @@ -991,24 +1023,33 @@ 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 (tu_unit[drv].UDENS == TC_1600) + tufs = tufs | FS_PE; + if (sim_tape_wrp (&tu_unit[drv])) + tufs = tufs | FS_WRL; if (!act) { - if (sim_tape_bot (&tu_unit[drv])) tufs = tufs | FS_BOT; - if (sim_tape_eot (&tu_unit[drv])) tufs = tufs | FS_EOT; + if (sim_tape_bot (&tu_unit[drv])) + tufs = tufs | FS_BOT; + if (sim_tape_eot (&tu_unit[drv])) + tufs = tufs | FS_EOT; } } - if (tuer) tufs = tufs | FS_ERR; + 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 (tucs2 & CS2_ERR) + tucs1 = tucs1 | CS1_TRE | CS1_SC; +else if (tucs1 & CS1_TRE) + tucs1 = tucs1 | CS1_SC; +if (tufs & FS_ATA) + tucs1 = tucs1 | CS1_SC; if (tuiff || ((tucs1 & CS1_SC) && (tucs1 & CS1_DONE) && (tucs1 & CS1_IE))) int_req = int_req | INT_TU; else int_req = int_req & ~INT_TU; -if ((tucs1 & CS1_DONE) && tufs && !act) tufs = tufs | FS_RDY; +if ((tucs1 & CS1_DONE) && tufs && !act) + tufs = tufs | FS_RDY; return; } @@ -1030,7 +1071,8 @@ 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 */ + if (qdt) /* data xfr? set TRE */ + tucs1 = tucs1 | CS1_TRE; case MTSE_OK: /* no error */ return SCPE_IERR; @@ -1040,23 +1082,28 @@ switch (st) { 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; + if (qdt) /* data xfr? set TRE */ + tucs1 = tucs1 | CS1_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 */ + if (qdt) /* data xfr? set TRE */ + tucs1 = tucs1 | CS1_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 */ + if (qdt) /* data xfr? set TRE */ + tucs1 = tucs1 | CS1_TRE; break; case MTSE_EOM: /* end of medium */ set_tuer (ER_OPI); /* incomplete */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + if (qdt) /* data xfr? set TRE */ + tucs1 = tucs1 | CS1_TRE; break; case MTSE_BOT: /* reverse into BOT */ @@ -1064,7 +1111,8 @@ switch (st) { case MTSE_WRP: /* write protect */ set_tuer (ER_NXF); /* can't execute */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + if (qdt) /* data xfr? set TRE */ + tucs1 = tucs1 | CS1_TRE; break; } @@ -1085,7 +1133,8 @@ tuwc = 0; tufc = 0; tuer = 0; tufs = FS_FPR | FS_RDY; -if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */ +if (sim_switches & SWMASK ('P')) /* powerup? clr TC */ + tutc = 0; else tutc = tutc & ~TC_FCS; /* no, clr */ tuiff = 0; /* clear CSTB INTR */ int_req = int_req & ~INT_TU; /* clear interrupt */ @@ -1095,8 +1144,10 @@ for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */ 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 (xbuf == NULL) + xbuf = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8)); +if (xbuf == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -1108,7 +1159,8 @@ int32 drv = uptr - tu_dev.units; t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +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 */ @@ -1124,7 +1176,8 @@ t_stat tu_detach (UNIT* uptr) { int32 drv = uptr - tu_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; if (sim_is_active (uptr)) { /* unit active? */ sim_cancel (uptr); /* cancel operation */ tuer = tuer | ER_UNS; /* set formatter error */ diff --git a/PDP10/pdp10_xtnd.c b/PDP10/pdp10_xtnd.c index af0e1555..a73a9619 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -194,7 +194,8 @@ int32 flg, i, s2, t, pp, pat, xop, xac, ret; xinst = Read (ea, MM_OPND); /* get extended instr */ xop = GET_OP (xinst); /* get opcode */ xac = GET_AC (xinst); /* get AC */ -if (xac || (xop == 0) || (xop > XT_MOVSRJ)) return XT_MUUO; +if (xac || (xop == 0) || (xop > XT_MOVSRJ)) + return XT_MUUO; rlog = 0; /* clear log */ switch (xop) { /* case on opcode */ @@ -214,19 +215,25 @@ switch (xop) { /* case on opcode */ 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 */ + if ((AC(ac) | AC(p3)) & XT_MBZ) /* check length MBZ */ + return XT_MUUO; 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); + if (flg && (t = test_int ())) + ABORT (t); rlog = 0; /* clear log */ - if (AC(ac)) b1 = incloadbp (p1, pflgs); /* src1 */ + if (AC(ac)) /* src1 */ + b1 = incloadbp (p1, pflgs); else b1 = f1; - if (AC(p3)) b2 = incloadbp (p4, pflgs); /* src2 */ + if (AC(p3)) /* src2 */ + b2 = incloadbp (p4, pflgs); else b2 = f2; - if (AC(ac)) AC(ac) = (AC(ac) - 1) & XLNTMASK; - if (AC(p3)) AC(p3) = (AC(p3) - 1) & XLNTMASK; + if (AC(ac)) + AC(ac) = (AC(ac) - 1) & XLNTMASK; + if (AC(p3)) + AC(p3) = (AC(p3) - 1) & XLNTMASK; } switch (xop) { case XT_CMPSL: @@ -261,18 +268,24 @@ switch (xop) { /* case on opcode */ 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 (TSTS (AC(ac))) { /* get abs value */ + DMOVN (rs); } - if (i > (AC(p3) & XLNTMASK)) return XT_NOSK; + 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; + 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 */ @@ -281,18 +294,22 @@ switch (xop) { /* case on opcode */ /* Now do actual binary to decimal conversion */ for (flg = 0; AC(p3) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); + 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 */ + if (i > 22) /* put in range */ + i = 22; 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; + 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; + if ((i == 1) && (AC(p3) & XT_LFLG)) + f1 = f1 >> 18; digit = f1 & RMASK; } incstorebp (digit, p4, pflgs); /* store digit */ @@ -314,7 +331,8 @@ switch (xop) { /* case on opcode */ 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 */ + if ((AC(ac) & XT_SFLG) == 0) /* !S? clr res */ + AC(p3) = AC(p4) = 0; else AC(p4) = CLRS (AC(p4)); /* clear low sign */ if (xop == XT_CVTDBO) { /* offset? */ xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ @@ -322,23 +340,28 @@ switch (xop) { /* case on opcode */ } xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ for (flg = 0; AC(ac) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); + 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; + 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)); + if (TSTS (AC(p3))) + AC(p4) = SETS (AC(p4)); return XT_NOSK; } - if (xflgs & XT_SFLG) b1 = b1 & XT_DGMASK; + 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)); + if (TSTS (AC(p3))) + AC(p4) = SETS (AC(p4)); return XT_NOSK; } AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */ @@ -349,7 +372,8 @@ switch (xop) { /* case on opcode */ AC(p4) = -AC(p4) & MMASK; AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK; } - if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); + if (TSTS (AC(p3))) + AC(p4) = SETS (AC(p4)); return XT_SKIP; /* String move instructions - checked against KS10 ucode @@ -365,14 +389,16 @@ switch (xop) { /* case on opcode */ case XT_MOVST: /* MOVST */ case XT_MOVSRJ: /* MOVSRJ */ case XT_MOVSLJ: /* MOVSLJ */ - if (AC(p3) & XT_MBZ) return XT_MUUO; /* test dst lnt MBZ */ + if (AC(p3) & XT_MBZ) /* test dst lnt MBZ */ + return XT_MUUO; 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 */ + if (xoff & RSIGN) /* sign extend 18b */ + xoff = xoff | LMASK; s2 = GET_S (AC(p4)); /* get dst byte size */ break; @@ -382,10 +408,12 @@ switch (xop) { /* case on opcode */ 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(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); + if (flg && (t = test_int ())) + ABORT (t); AC(p1) = incbp (AC(p1)); AC(ac) = (AC(ac) - 1) & XLNTMASK; } @@ -400,9 +428,11 @@ switch (xop) { /* case on opcode */ } /* end case xop */ xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ - if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP); + 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); + if (flg && (t = test_int ())) + ABORT (t); rlog = 0; /* clear log */ if (AC(ac) & XLNTMASK) { /* any source? */ b1 = incloadbp (p1, pflgs); /* src byte */ @@ -419,7 +449,8 @@ switch (xop) { /* case on opcode */ AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); return XT_NOSK; } - if (xflgs & XT_SFLG) b1 = b1 & XT_BYMASK; + if (xflgs & XT_SFLG) + b1 = b1 & XT_BYMASK; else b1 = -1; } } @@ -428,7 +459,8 @@ switch (xop) { /* case on opcode */ 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); + if (AC(ac) & XLNTMASK) + AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); } return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP; @@ -441,12 +473,14 @@ switch (xop) { /* case on opcode */ AC + 4 = destination byte pointer */ - case XT_EDIT: /* EDIT */ - if (AC(ac) & XT_MBZE) return XT_MUUO; /* check pattern MBZ */ + case XT_EDIT: /* EDIT */ + if (AC(ac) & XT_MBZE) /* check pattern MBZ */ + return XT_MUUO; 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); + 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 */ @@ -462,15 +496,17 @@ switch (xop) { /* case on opcode */ 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; + 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; + if (xflgs & XT_SFLG) + f1 = f1 & XT_BYMASK; else { f1 = Read (INCA (ea), MM_OPND); - if (f1 == 0) break; + if (f1 == 0) + break; } incstorebp (f1, p4, pflgs); break; @@ -485,7 +521,8 @@ switch (xop) { /* case on opcode */ 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); + if (f2) + incstorebp (f2, p4, pflgs); xflgs = xflgs | XT_SFLG; } incstorebp (f1, p4, pflgs); @@ -502,7 +539,8 @@ switch (xop) { /* case on opcode */ 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); + if (f2) + incstorebp (f2, p4, pflgs); xflgs = xflgs | XT_SFLG; } break; @@ -522,17 +560,20 @@ switch (xop) { /* case on opcode */ f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND); else { f1 = Read (ea + 1, MM_OPND); - if (f1 == 0) break; + 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; + 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; + if (xflgs & XT_NFLG) + ppi = (pat & ED_M_NUM) + 2; break; case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */ @@ -681,7 +722,8 @@ int32 i, t; int32 p1 = ADDA (ac, 1); for (i = 0; i < cnt; i++) { - if (i && (t = test_int ())) ABORT (t); + if (i && (t = test_int ())) + ABORT (t); rlog = 0; /* clear log */ incstorebp (fill, p1, pflgs); AC(ac) = (AC(ac) & XFLGMASK) | ((AC(ac) - 1) & XLNTMASK); diff --git a/PDP11/pdp11_cis.c b/PDP11/pdp11_cis.c index 3f1e2e6b..9c7fe51b 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ This module simulates the PDP-11 commercial instruction set (CIS). + 16-Oct-08 RMS Fixed overflow bug in ASHx (Word/NibbleLShift) + Fixed bug in DIVx (LntDstr calculation) 30-May-06 RMS Added interrupt tests to character instructions Added 11/44 stack probe test to MOVCx (only) 22-May-06 RMS Fixed bug in decode table (found by John Dundas) @@ -430,14 +432,16 @@ switch (op) { /* case on opcode */ if (R[1] < R[3]) { /* backwards? */ for (i = 0; R[0] && R[2]; ) { /* move loop */ t = ReadB (((R[1] - 1) & 0177777) | dsenable); - if (op & 2) t = ReadB (((R[5] + t) & 0177777) | dsenable); + if (op & 2) + t = ReadB (((R[5] + t) & 0177777) | dsenable); WriteB (t, ((R[3] - 1) & 0177777) | dsenable); R[0]--; R[1] = (R[1] - 1) & 0177777; R[2]--; R[3] = (R[3] - 1) & 0177777; if ((++i >= INT_TEST) && R[0] && R[2]) { - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } /* end for lnts */ @@ -447,14 +451,16 @@ switch (op) { /* case on opcode */ else { /* forward */ for (i = 0; R[0] && R[2]; ) { /* move loop */ t = ReadB ((R[1] & 0177777) | dsenable); - if (op & 2) t = ReadB (((R[5] + t) & 0177777) | dsenable); + if (op & 2) + t = ReadB (((R[5] + t) & 0177777) | dsenable); WriteB (t, (R[3] & 0177777) | dsenable); R[0]--; R[1] = (R[1] + 1) & 0177777; R[2]--; R[3] = (R[3] + 1) & 0177777; if ((++i >= INT_TEST) && R[0] && R[2]) { - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } /* end for lnts */ @@ -514,7 +520,8 @@ switch (op) { /* case on opcode */ R[2]--; R[3] = (R[3] - 1) & 0177777; if ((++i >= INT_TEST) && R[0] && R[2]) { - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } /* end for lnts */ @@ -528,7 +535,8 @@ switch (op) { /* case on opcode */ R[2]--; R[3] = (R[3] + 1) & 0177777; if ((++i >= INT_TEST) && R[0] && R[2]) { - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } /* end for lnts */ @@ -557,7 +565,8 @@ switch (op) { /* case on opcode */ R[j] = ReadW (addr | dsenable); R[j + 1] = ReadW (((addr + 2) & 0177777) | dsenable); } - if (rn >= limit) R[rn] = (R[rn] + limit) & 0177777; + if (rn >= limit) + R[rn] = (R[rn] + limit) & 0177777; return SCPE_OK; /* LOCC, SKPC, LOCCI, SKPCI @@ -590,11 +599,13 @@ switch (op) { /* case on opcode */ R[4] = R[4] & 0377; /* match character */ for (i = 0; R[0] != 0;) { /* loop */ c = ReadB (R[1] | dsenable); /* get char */ - if ((c == R[4]) ^ (op & 1)) break; /* = + LOC, != + SKP? */ + if ((c == R[4]) ^ (op & 1)) /* = + LOC, != + SKP? */ + break; R[0]--; /* decr count, */ R[1] = (R[1] + 1) & 0177777; /* incr addr */ if ((++i >= INT_TEST) && R[0]) { /* test for intr? */ - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } @@ -643,11 +654,13 @@ switch (op) { /* case on opcode */ for (i = 0; R[0] != 0;) { /* loop */ t = ReadB (R[1] | dsenable); /* get char as index */ c = ReadB (((R[5] + t) & 0177777) | dsenable); - if (((c & R[4]) != 0) ^ (op & 1)) break; /* != + SCN, = + SPN? */ + if (((c & R[4]) != 0) ^ (op & 1)) /* != + SCN, = + SPN? */ + break; R[0]--; /* decr count, */ R[1] = (R[1] + 1) & 0177777; /* incr addr */ if ((++i >= INT_TEST) && R[0]) { /* test for intr? */ - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } @@ -701,11 +714,14 @@ switch (op) { /* case on opcode */ R[4] = R[4] & 0377; /* mask fill */ c = t = 0; for (i = 0; (R[0] || R[2]); ) { /* until cnts == 0 */ - if (R[0]) c = ReadB (R[1] | dsenable); /* get src1 or fill */ + if (R[0]) /* get src1 or fill */ + c = ReadB (R[1] | dsenable); else c = R[4]; - if (R[2]) t = ReadB (R[3] | dsenable); /* get src2 or fill */ + if (R[2]) /* get src2 or fill */ + t = ReadB (R[3] | dsenable); else t = R[4]; - if (c != t) break; /* if diff, done */ + if (c != t) /* if diff, done */ + break; if (R[0]) { /* if more src1 */ R[0]--; /* decr count, */ R[1] = (R[1] + 1) & 0177777; /* incr addr */ @@ -715,7 +731,8 @@ switch (op) { /* case on opcode */ R[3] = (R[3] + 1) & 0177777; /* incr addr */ } if ((++i >= INT_TEST) && (R[0] || R[2])) { /* test for intr? */ - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; i = 0; } } @@ -781,10 +798,12 @@ switch (op) { /* case on opcode */ t = ReadB (((R[3] + i) & 0177777) | dsenable); match = (c == t); /* end for substring */ } - if (match) break; /* exit if match */ + if (match) /* exit if match */ + break; R[0]--; /* on to next char */ R[1] = (R[1] + 1) & 0177777; - if (cis_int_test (i, old_PC, &st)) return st; + if (cis_int_test (i, old_PC, &st)) + return st; } if (!match) { /* if no match */ R[1] = (R[1] + R[0]) & 0177777; @@ -820,7 +839,8 @@ switch (op) { /* case on opcode */ 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 (op & 1) /* sub? invert sign */ + src1.sign = src1.sign ^ 1; if (src1.sign ^ src2.sign) { /* opp signs? sub */ if (CmpDstr (&src1, &src2) < 0) { /* src1 < src2? */ SubDstr (&src1, &src2, &dst); /* src2 - src1 */ @@ -951,8 +971,10 @@ switch (op) { /* case on opcode */ 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); + 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 */ @@ -989,8 +1011,10 @@ switch (op) { /* case on opcode */ 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)) V = 1; + if (WordLshift (&src1, shift / 8)) /* do word shifts */ + V = 1; + if (NibbleLshift (&src1, shift % 8)) /* do nibble shifts */ + V = 1; } /* end left shift */ WriteDstr (A2, &src1, op); /* store result */ if ((op & INLINE) == 0) /* if reg, clr reg */ @@ -1015,7 +1039,8 @@ switch (op) { /* case on opcode */ 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 */ + if ((op & INLINE) == 0) /* if reg, clr reg */ + R[0] = R[1] = 0; return SCPE_OK; /* CVTNP, CVTNPI @@ -1036,7 +1061,8 @@ switch (op) { /* case on opcode */ 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 */ + if ((op & INLINE) == 0) /* if reg, clr reg */ + R[0] = R[1] = 0; return SCPE_OK; /* CVTNL, CVTPL, CVTNLI, CVTPLI @@ -1060,12 +1086,15 @@ switch (op) { /* case on opcode */ 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; + if (result >= MAXDVAL) + V = 1; result = (result * 10) + digit; - if (result < digit) V = 1; + if (result < digit) + V = 1; } /* end if */ } /* end for */ - if (src1.sign) result = (~result + 1) & 0xFFFFFFFF; + 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 */ @@ -1105,7 +1134,8 @@ switch (op) { /* case on opcode */ result = (A2ADR << 16) | A2LNT; /* op in VAX format */ CVTLx: dst = Dstr0; /* clear result */ - if (dst.sign = GET_SIGN_L (result)) result = (~result + 1) & 0xFFFFFFFF; + 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; @@ -1157,13 +1187,18 @@ 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 */ + if (i == 0) /* save sign */ + t = c & 0xF; + if ((i == end) && ((lnt & 1) == 0)) + c = c & 0xF; + if (c >= 0xA0) /* check hi digit */ + c = c & 0xF; + if ((c & 0xF) >= 0xA) /* check lo digit */ + c = c & 0xF0; 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 */ + if ((t == 0xB) || (t == 0xD)) /* if -, set sign */ + src->sign = 1; src->val[0] = src->val[0] & ~0xF; /* clear sign */ } /* end packed */ else { /* numeric */ @@ -1179,7 +1214,8 @@ else { /* numeric */ src->sign = c >> 7; /* set sign */ } c = c & 0xF; /* get digit */ - if (c > 9) c = 0; /* range check */ + if (c > 9) /* range check */ + c = 0; src->val[i / 8] = src->val[i / 8] | (c << ((i % 8) * 4)); } /* end for */ } /* end numeric */ @@ -1225,17 +1261,22 @@ 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 */ + if (i == limit) /* at limit, get mask */ + mask = masktab[lnt % 8]; + else if (i > limit) /* beyond, all ovflo */ + mask = 0xFFFFFFFF; + if (dst->val[i] & mask) /* test for ovflo */ + V = 1; + if (dst->val[i] = dst->val[i] & ~mask) /* test nz */ + Z = 0; } dst->sign = dst->sign & ~unsignedtab[type] & ~(Z & ~V); N = dst->sign & ~Z; /* N = sign, if ~zero */ if (flag & PACKED) { /* packed? */ end = lnt / 2; /* end of string */ - if (type == UP) dst->val[0] = dst->val[0] | 0xF; + 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; @@ -1335,7 +1376,8 @@ void SubDstr (DSTR *s1, DSTR *s2, DSTR *ds) int32 i; DSTR compl; -for (i = 0; i < DSTRLNT; i++) compl.val[i] = 0x99999999 - s1->val[i]; +for (i = 0; i < DSTRLNT; i++) + compl.val[i] = 0x99999999 - s1->val[i]; AddDstr (&compl, s2, ds, 1); /* s1 + ~s2 + 1 */ return; } @@ -1353,8 +1395,10 @@ 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; } @@ -1372,7 +1416,10 @@ int32 TestDstr (DSTR *dsrc) { int32 i; -for (i = DSTRMAX; i >= 0; i--) if (dsrc->val[i]) return (i + 1); +for (i = DSTRMAX; i >= 0; i--) { + if (dsrc->val[i]) + return (i + 1); + } dsrc->sign = 0; return 0; } @@ -1388,9 +1435,11 @@ int32 LntDstr (DSTR *dsrc, int32 nz) { int32 i; -if (nz == 0) return 0; -for (i = 7; i > 0; i--) { - if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; +if (nz == 0) + return 0; +for (i = 7; i >= 0; i--) { + if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) + break; } return ((nz - 1) * 8) + i; } @@ -1411,7 +1460,8 @@ void CreateTable (DSTR *dsrc, DSTR mtable[10]) int32 (i); mtable[1] = *dsrc; -for (i = 2; i < 10; i++) AddDstr (&mtable[1], &mtable[i-1], &mtable[i], 0); +for (i = 2; i < 10; i++) + AddDstr (&mtable[1], &mtable[i-1], &mtable[i], 0); return; } @@ -1428,7 +1478,8 @@ int32 i; if (sc) { for (i = 0; i < DSTRLNT; i++) { - if ((i + sc) < DSTRLNT) dsrc->val[i] = dsrc->val[i + sc]; + if ((i + sc) < DSTRLNT) + dsrc->val[i] = dsrc->val[i + sc]; else dsrc->val[i] = 0; } } @@ -1449,9 +1500,12 @@ 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; + if (i >= sc) + dsrc->val[i] = dsrc->val[i - sc]; + else { + c |= dsrc->val[i]; + dsrc->val[i] = 0; + } } } return c; @@ -1467,14 +1521,13 @@ return c; uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin) { -int32 i, s, rs, nc; +int32 i, s, nc; if (s = sc * 4) { - rs = 32 - s; for (i = DSTRMAX; i >= 0; i--) { - nc = dsrc->val[i]; + nc = (dsrc->val[i] << (32 - s)) & 0xFFFFFFFF; dsrc->val[i] = ((dsrc->val[i] >> s) | - (cin << rs)) & 0xFFFFFFFF; + cin) & 0xFFFFFFFF; cin = nc; } return cin; @@ -1491,18 +1544,17 @@ return 0; uint32 NibbleLshift (DSTR *dsrc, int32 sc) { -int32 i, s, rs; -uint32 sv_val, cout; +int32 i, s; +uint32 nc, cin; -cout = 0; +cin = 0; if (s = sc * 4) { - rs = 32 - s; for (i = 0; i < DSTRLNT; i++) { - sv_val = dsrc->val[i]; - dsrc->val[i] = ((dsrc->val[i] << s) | cout) & 0xFFFFFFFF; - cout = sv_val >> rs; + nc = dsrc->val[i] >> (32 - s); + dsrc->val[i] = ((dsrc->val[i] << s) | cin) & 0xFFFFFFFF; + cin = nc; } - return cout; + return cin; } return 0; } diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index f977fb24..670a37ca 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -25,6 +25,7 @@ cpu PDP-11 CPU + 29-Dec-08 RMS Fixed failure to clear cpu_bme on RESET (found by Walter Mueller) 22-Apr-08 RMS Fixed MMR0 treatment in RESET (found by Walter Mueller) 02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas) 28-Apr-07 RMS Removed clock initialization @@ -648,7 +649,8 @@ t_stat reason; */ reason = build_dib_tab (); /* build, chk dib_tab */ -if (reason != SCPE_OK) return reason; +if (reason != SCPE_OK) + return reason; if (MEMSIZE < cpu_tab[cpu_model].maxm) /* mem size < max? */ cpu_memsize = MEMSIZE; /* then okay */ else cpu_memsize = cpu_tab[cpu_model].maxm - IOPAGESIZE;/* max - io page */ @@ -656,7 +658,8 @@ 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 */ -for (i = 0; i < 6; i++) R[i] = REGFILE[i][rs]; +for (i = 0; i < 6; i++) + R[i] = REGFILE[i][rs]; SP = STACKFILE[cm]; isenable = calc_is (cm); dsenable = calc_ds (cm); @@ -688,14 +691,16 @@ reason = 0; abortval = setjmp (save_env); /* set abort hdlr */ if (abortval != 0) { trap_req = trap_req | abortval; /* or in trap flag */ - if ((trapea > 0) && stop_vecabort) reason = STOP_VECABORT; + if ((trapea > 0) && stop_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; + if (cm == MD_KER) + SP = 4; } } @@ -761,7 +766,8 @@ while (reason == 0) { PSW = get_PSW (); /* assemble PSW */ oldrs = rs; if (CPUT (HAS_MMTR)) { /* 45,70? */ - if (update_MM) MMR2 = trapea; /* save vector */ + if (update_MM) /* save vector */ + MMR2 = trapea; MMR0 = MMR0 & ~MMR0_IC; /* clear IC */ } src = ReadW (trapea | calc_ds (MD_KER)); /* new PC */ @@ -793,7 +799,8 @@ while (reason == 0) { /* Fetch and decode next instruction */ - if (tbit) setTRAP (TRAP_TRC); + if (tbit) + setTRAP (TRAP_TRC); if (wait_state) { /* wait state? */ if (sim_idle_enab) /* idle enabled? */ sim_idle (TMR_CLK, TRUE); @@ -832,7 +839,8 @@ while (reason == 0) { else hst[hst_p].inst[i] = (uint16) val; } hst_p = (hst_p + 1); - if (hst_p >= hst_lnt) hst_p = 0; + if (hst_p >= hst_lnt) + hst_p = 0; } PC = (PC + 2) & 0177777; /* incr PC, mod 65k */ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ @@ -873,7 +881,9 @@ while (reason == 0) { STKLIM = 0; /* clear STKLIM */ MMR0 = 0; /* clear MMR0 */ MMR3 = 0; /* clear MMR3 */ - for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; + cpu_bme = 0; /* (also clear bme) */ + for (i = 0; i < IPL_HLVL; i++) + int_req[i] = 0; trap_req = trap_req & ~TRAP_INT; dsenable = calc_ds (cm); } @@ -912,7 +922,8 @@ while (reason == 0) { break; /* end case no ops */ case 001: /* JMP */ - if (dstreg) setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL); + 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 */ @@ -927,7 +938,8 @@ while (reason == 0) { dstspec = dstspec & 07; JMP_PC (R[dstspec]); R[dstspec] = ReadW (SP | dsenable); - if (dstspec != 6) SP = (SP + 2) & 0177777; + if (dstspec != 6) + SP = (SP + 2) & 0177777; break; } /* end if RTS */ if (IR < 000230) { @@ -936,23 +948,32 @@ while (reason == 0) { } if (IR < 000240) { /* SPL */ if (CPUT (HAS_SPL)) { - if (cm == MD_KER) ipl = IR & 07; + 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; + 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; + if (IR & 010) /* set CC */ + N = 1; + if (IR & 004) + Z = 1; + if (IR & 002) + V = 1; + if (IR & 001) + C = 1; break; /* end case RTS et al */ case 003: /* SWAB */ @@ -960,9 +981,11 @@ while (reason == 0) { dst = ((dst & 0377) << 8) | ((dst >> 8) & 0377); N = GET_SIGN_B (dst & 0377); Z = GET_Z (dst & 0377); - if (!CPUT (CPUT_20)) V = 0; + if (!CPUT (CPUT_20)) + V = 0; C = 0; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; /* end SWAB */ @@ -975,39 +998,57 @@ while (reason == 0) { break; case 010: case 011: /* BNE */ - if (Z == 0) { BRANCH_F (IR); } + if (Z == 0) { + BRANCH_F (IR); + } break; case 012: case 013: /* BNE */ - if (Z == 0) { BRANCH_B (IR); } + if (Z == 0) { + BRANCH_B (IR); + } break; case 014: case 015: /* BEQ */ - if (Z) { BRANCH_F (IR); } + if (Z) { + BRANCH_F (IR); + } break; case 016: case 017: /* BEQ */ - if (Z) { BRANCH_B (IR); } + if (Z) { + BRANCH_B (IR); + } break; case 020: case 021: /* BGE */ - if ((N ^ V) == 0) { BRANCH_F (IR); } + if ((N ^ V) == 0) { + BRANCH_F (IR); + } break; case 022: case 023: /* BGE */ - if ((N ^ V) == 0) { BRANCH_B (IR); } + if ((N ^ V) == 0) { + BRANCH_B (IR); + } break; case 024: case 025: /* BLT */ - if (N ^ V) { BRANCH_F (IR); } + if (N ^ V) { + BRANCH_F (IR); + } break; case 026: case 027: /* BLT */ - if (N ^ V) { BRANCH_B (IR); } + if (N ^ V) { + BRANCH_B (IR); + } break; case 030: case 031: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_F (IR); } + if ((Z | (N ^ V)) == 0) { + BRANCH_F (IR); + } break; case 032: case 033: /* BGT */ @@ -1015,16 +1056,21 @@ while (reason == 0) { break; case 034: case 035: /* BLE */ - if (Z | (N ^ V)) { BRANCH_F (IR); } + if (Z | (N ^ V)) { + BRANCH_F (IR); + } break; case 036: case 037: /* BLE */ - if (Z | (N ^ V)) { BRANCH_B (IR); } + 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); + if (dstreg) + setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL); else { srcspec = srcspec & 07; dst = GeteaW (dstspec); @@ -1032,7 +1078,8 @@ while (reason == 0) { ((dstspec & 070) == 020)) /* JSR (R)+? */ dst = R[dstspec & 07]; /* use post incr */ SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); + if (update_MM) + MMR1 = calc_MMR1 (0366); WriteW (R[srcspec], SP | dsenable); if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y))) set_stack_trap (SP); @@ -1044,7 +1091,8 @@ while (reason == 0) { case 050: /* CLR */ N = V = C = 0; Z = 1; - if (dstreg) R[dstspec] = 0; + if (dstreg) + R[dstspec] = 0; else WriteW (0, GeteaW (dstspec)); break; @@ -1055,7 +1103,8 @@ while (reason == 0) { Z = GET_Z (dst); V = 0; C = 1; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1065,7 +1114,8 @@ while (reason == 0) { N = GET_SIGN_W (dst); Z = GET_Z (dst); V = (dst == 0100000); - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1075,7 +1125,8 @@ while (reason == 0) { N = GET_SIGN_W (dst); Z = GET_Z (dst); V = (dst == 077777); - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1086,7 +1137,8 @@ while (reason == 0) { Z = GET_Z (dst); V = (dst == 0100000); C = Z ^ 1; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1097,7 +1149,8 @@ while (reason == 0) { Z = GET_Z (dst); V = (C && (dst == 0100000)); C = C & Z; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1108,7 +1161,8 @@ while (reason == 0) { Z = GET_Z (dst); V = (C && (dst == 077777)); C = (C && (dst == 0177777)); - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1126,7 +1180,8 @@ while (reason == 0) { Z = GET_Z (dst); C = (src & 1); V = N ^ C; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1137,7 +1192,8 @@ while (reason == 0) { Z = GET_Z (dst); C = GET_SIGN_W (src); V = N ^ C; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1148,7 +1204,8 @@ while (reason == 0) { Z = GET_Z (dst); C = (src & 1); V = N ^ C; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1159,7 +1216,8 @@ while (reason == 0) { Z = GET_Z (dst); C = GET_SIGN_W (src); V = N ^ C; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1181,7 +1239,8 @@ while (reason == 0) { case 065: /* MFPI */ if (CPUT (HAS_MXPY)) { if (dstreg) { - if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; + if ((dstspec == 6) && (cm != pm)) + dst = STACKFILE[pm]; else dst = R[dstspec]; } else { @@ -1192,7 +1251,8 @@ while (reason == 0) { Z = GET_Z (dst); V = 0; SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); + if (update_MM) + MMR1 = calc_MMR1 (0366); WriteW (dst, SP | dsenable); if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y))) set_stack_trap (SP); @@ -1209,7 +1269,8 @@ while (reason == 0) { SP = (SP + 2) & 0177777; if (update_MM) MMR1 = 026; if (dstreg) { - if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; + if ((dstspec == 6) && (cm != pm)) + STACKFILE[pm] = dst; else R[dstspec] = dst; } else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_is (pm)); @@ -1222,7 +1283,8 @@ while (reason == 0) { dst = N? 0177777: 0; Z = N ^ 1; V = 0; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else WriteW (dst, GeteaW (dstspec)); } else setTRAP (TRAP_ILL); @@ -1299,7 +1361,8 @@ while (reason == 0) { N = GET_SIGN_W (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else WriteW (dst, ea); break; @@ -1347,7 +1410,8 @@ while (reason == 0) { N = GET_SIGN_W (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1364,7 +1428,8 @@ while (reason == 0) { N = GET_SIGN_W (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1382,7 +1447,8 @@ while (reason == 0) { Z = GET_Z (dst); V = GET_SIGN_W ((~src ^ src2) & (src ^ dst)); C = (dst < src); - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); break; @@ -1414,8 +1480,10 @@ while (reason == 0) { } 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; + 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; @@ -1442,8 +1510,10 @@ while (reason == 0) { 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; + 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)) { @@ -1545,14 +1615,16 @@ while (reason == 0) { N = GET_SIGN_W (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = dst; + if (dstreg) + R[dstspec] = dst; else PWriteW (dst, last_pa); } else setTRAP (TRAP_ILL); break; case 5: /* FIS */ - if (CPUO (OPT_FIS)) fis11 (IR); + if (CPUO (OPT_FIS)) + fis11 (IR); else setTRAP (TRAP_ILL); break; @@ -1585,67 +1657,99 @@ while (reason == 0) { switch ((IR >> 6) & 077) { /* decode IR<11:6> */ case 000: case 001: /* BPL */ - if (N == 0) { BRANCH_F (IR); } + if (N == 0) { + BRANCH_F (IR); + } break; case 002: case 003: /* BPL */ - if (N == 0) { BRANCH_B (IR); } + if (N == 0) { + BRANCH_B (IR); + } break; case 004: case 005: /* BMI */ - if (N) { BRANCH_F (IR); } + if (N) { + BRANCH_F (IR); + } break; case 006: case 007: /* BMI */ - if (N) { BRANCH_B (IR); } + if (N) { + BRANCH_B (IR); + } break; case 010: case 011: /* BHI */ - if ((C | Z) == 0) { BRANCH_F (IR); } + if ((C | Z) == 0) { + BRANCH_F (IR); + } break; case 012: case 013: /* BHI */ - if ((C | Z) == 0) { BRANCH_B (IR); } + if ((C | Z) == 0) { + BRANCH_B (IR); + } break; case 014: case 015: /* BLOS */ - if (C | Z) { BRANCH_F (IR); } + if (C | Z) { + BRANCH_F (IR); + } break; case 016: case 017: /* BLOS */ - if (C | Z) { BRANCH_B (IR); } + if (C | Z) { + BRANCH_B (IR); + } break; case 020: case 021: /* BVC */ - if (V == 0) { BRANCH_F (IR); } + if (V == 0) { + BRANCH_F (IR); + } break; case 022: case 023: /* BVC */ - if (V == 0) { BRANCH_B (IR); } + if (V == 0) { + BRANCH_B (IR); + } break; case 024: case 025: /* BVS */ - if (V) { BRANCH_F (IR); } + if (V) { + BRANCH_F (IR); + } break; case 026: case 027: /* BVS */ - if (V) { BRANCH_B (IR); } + if (V) { + BRANCH_B (IR); + } break; case 030: case 031: /* BCC */ - if (C == 0) { BRANCH_F (IR); } + if (C == 0) { + BRANCH_F (IR); + } break; case 032: case 033: /* BCC */ - if (C == 0) { BRANCH_B (IR); } + if (C == 0) { + BRANCH_B (IR); + } break; case 034: case 035: /* BCS */ - if (C) { BRANCH_F (IR); } + if (C) { + BRANCH_F (IR); + } break; case 036: case 037: /* BCS */ - if (C) { BRANCH_B (IR); } + if (C) { + BRANCH_B (IR); + } break; case 040: case 041: case 042: case 043: /* EMT */ @@ -1659,7 +1763,8 @@ while (reason == 0) { case 050: /* CLRB */ N = V = C = 0; Z = 1; - if (dstreg) R[dstspec] = R[dstspec] & 0177400; + if (dstreg) + R[dstspec] = R[dstspec] & 0177400; else WriteB (0, GeteaB (dstspec)); break; @@ -1670,7 +1775,8 @@ while (reason == 0) { Z = GET_Z (dst); V = 0; C = 1; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1680,7 +1786,8 @@ while (reason == 0) { N = GET_SIGN_B (dst); Z = GET_Z (dst); V = (dst == 0200); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1690,7 +1797,8 @@ while (reason == 0) { N = GET_SIGN_B (dst); Z = GET_Z (dst); V = (dst == 0177); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1701,7 +1809,8 @@ while (reason == 0) { Z = GET_Z (dst); V = (dst == 0200); C = (Z ^ 1); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1712,7 +1821,8 @@ while (reason == 0) { Z = GET_Z (dst); V = (C && (dst == 0200)); C = C & Z; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1723,7 +1833,8 @@ while (reason == 0) { Z = GET_Z (dst); V = (C && (dst == 0177)); C = (C && (dst == 0377)); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1741,7 +1852,8 @@ while (reason == 0) { Z = GET_Z (dst); C = (src & 1); V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1752,7 +1864,8 @@ while (reason == 0) { Z = GET_Z (dst); C = GET_SIGN_B (src & 0377); V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1763,7 +1876,8 @@ while (reason == 0) { Z = GET_Z (dst); C = (src & 1); V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1774,7 +1888,8 @@ while (reason == 0) { Z = GET_Z (dst); C = GET_SIGN_B (src & 0377); V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; /* Notes: @@ -1801,7 +1916,8 @@ while (reason == 0) { case 065: /* MFPD */ if (CPUT (HAS_MXPY)) { if (dstreg) { - if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; + if ((dstspec == 6) && (cm != pm)) + dst = STACKFILE[pm]; else dst = R[dstspec]; } else dst = ReadW ((GeteaW (dstspec) & 0177777) | calc_ds (pm)); @@ -1809,7 +1925,8 @@ while (reason == 0) { Z = GET_Z (dst); V = 0; SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); + if (update_MM) + MMR1 = calc_MMR1 (0366); WriteW (dst, SP | dsenable); if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y))) set_stack_trap (SP); @@ -1824,9 +1941,11 @@ while (reason == 0) { Z = GET_Z (dst); V = 0; SP = (SP + 2) & 0177777; - if (update_MM) MMR1 = 026; + if (update_MM) + MMR1 = 026; if (dstreg) { - if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; + if ((dstspec == 6) && (cm != pm)) + STACKFILE[pm] = dst; else R[dstspec] = dst; } else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_ds (pm)); @@ -1840,7 +1959,8 @@ while (reason == 0) { N = GET_SIGN_B (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; + if (dstreg) + R[dstspec] = (dst & 0200)? 0177400 | dst: dst; else WriteB (dst, GeteaB (dstspec)); } else setTRAP (TRAP_ILL); @@ -1870,7 +1990,8 @@ while (reason == 0) { N = GET_SIGN_B (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; + if (dstreg) + R[dstspec] = (dst & 0200)? 0177400 | dst: dst; else WriteB (dst, ea); break; @@ -1918,7 +2039,8 @@ while (reason == 0) { N = GET_SIGN_B (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1935,7 +2057,8 @@ while (reason == 0) { N = GET_SIGN_B (dst); Z = GET_Z (dst); V = 0; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + if (dstreg) + R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; @@ -1953,14 +2076,16 @@ while (reason == 0) { Z = GET_Z (dst); V = GET_SIGN_W ((src ^ src2) & (~src ^ dst)); C = (src2 < src); - if (dstreg) R[dstspec] = dst; + 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 */ + if (CPUO (OPT_FPP)) + fp11 (IR); /* call fpp */ else setTRAP (TRAP_ILL); break; /* end case 017 */ } /* end switch op */ @@ -1969,7 +2094,8 @@ while (reason == 0) { /* Simulation halted */ PSW = get_PSW (); -for (i = 0; i < 6; i++) REGFILE[i][rs] = R[i]; +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 */ @@ -2039,25 +2165,29 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 2: /* (R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); + 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); + 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 (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 (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); @@ -2093,26 +2223,30 @@ switch (spec >> 3) { /* decode spec<5:3> */ 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); + 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); + 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 (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 (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); @@ -2148,7 +2282,8 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */ ABORT (TRAP_ODD); } pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */ +if (ADDR_IS_MEM (pa)) /* memory address? */ + return (M[pa >> 1]); if ((pa < IOPAGEBASE) || /* not I/O address */ (CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */ setCPUERR (CPUE_NXM); @@ -2170,7 +2305,8 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */ ABORT (TRAP_ODD); } pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */ +if (ADDR_IS_MEM (pa)) /* memory address? */ + return (M[pa >> 1]); if (pa < IOPAGEBASE) { /* not I/O address? */ setCPUERR (CPUE_NXM); ABORT (TRAP_NXM); @@ -2187,7 +2323,8 @@ int32 ReadB (int32 va) int32 pa, data; pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377; +if (ADDR_IS_MEM (pa)) + return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377; if (pa < IOPAGEBASE) { /* not I/O address? */ setCPUERR (CPUE_NXM); ABORT (TRAP_NXM); @@ -2208,7 +2345,8 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */ ABORT (TRAP_ODD); } last_pa = relocW (va); /* reloc, wrt chk */ -if (ADDR_IS_MEM (last_pa)) return (M[last_pa >> 1]); /* memory address? */ +if (ADDR_IS_MEM (last_pa)) /* memory address? */ + return (M[last_pa >> 1]); if (last_pa < IOPAGEBASE) { /* not I/O address? */ setCPUERR (CPUE_NXM); ABORT (TRAP_NXM); @@ -2277,7 +2415,8 @@ 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); + if (va & 1) + M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8); else M[pa >> 1] = (M[pa >> 1] & ~0377) | data; return; } @@ -2312,7 +2451,8 @@ 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); + if (pa & 1) + M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8); else M[pa >> 1] = (M[pa >> 1] & ~0377) | data; return; } @@ -2357,12 +2497,14 @@ if (MMR0 & MMR0_MME) { /* if mmgt */ pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; if ((MMR3 & MMR3_M22E) == 0) { pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; + if (pa >= 0760000) + pa = 017000000 | pa; } } else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; + if (pa >= 0160000) + pa = 017600000 | pa; } return pa; } @@ -2393,8 +2535,8 @@ switch (apr & PDR_ACF) { /* case on ACF */ 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); + if (update_MM) /* update MMR0 */ + MMR0 = (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */ setTRAP (TRAP_MME); /* set trap */ } @@ -2408,7 +2550,8 @@ switch (apr & PDR_ACF) { /* case on ACF */ return; /* continue */ } /* end switch */ -if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */ +if (PLF_test (va, apr)) /* pg lnt error? */ + err = err | MMR0_PL; reloc_abort (err, apridx); return; } @@ -2462,12 +2605,14 @@ if (MMR0 & MMR0_MME) { /* if mmgt */ pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; if ((MMR3 & MMR3_M22E) == 0) { pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; + if (pa >= 0760000) + pa = 017000000 | pa; } } else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; + if (pa >= 0160000) + pa = 017600000 | pa; } return pa; } @@ -2498,8 +2643,8 @@ switch (apr & PDR_ACF) { /* case on ACF */ 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); + if (update_MM) /* update MMR0 */ + MMR0 = (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */ setTRAP (TRAP_MME); /* set trap */ } @@ -2516,7 +2661,8 @@ switch (apr & PDR_ACF) { /* case on ACF */ case 6: /* read/write */ return; /* continue */ } /* end switch */ -if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */ +if (PLF_test (va, apr)) /* pg lnt error? */ + err = err | MMR0_PL; reloc_abort (err, apridx); return; } @@ -2536,27 +2682,35 @@ 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; + 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; + if ((apr & PDR_PRD) == 0) /* not readable? */ + return MAXMEMSIZE; + 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; + if (pa >= 0760000) + pa = 017000000 | pa; } } else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; + if (pa >= 0160000) + pa = 017600000 | pa; } return pa; } @@ -2600,8 +2754,8 @@ switch ((pa >> 1) & 3) { /* decode pa<2:1> */ return SCPE_NXM; case 1: /* MMR0 */ - if (access == WRITEB) data = (pa & 1)? - (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; + 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; @@ -2619,7 +2773,8 @@ return SCPE_OK; t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */ { -if (pa & 1) return SCPE_OK; +if (pa & 1) + return SCPE_OK; MMR3 = data & cpu_tab[cpu_model].mm3; cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM); dsenable = calc_ds (cm); @@ -2650,9 +2805,12 @@ 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 */ -if (left) *data = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par; +if ((pa & 0100) == 0) /* 1 for super, user */ + idx = idx | 020; +if (pa & 0400) /* 1 for user only */ + idx = idx | 040; +if (left) + *data = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par; else *data = APRFILE[idx] & cpu_tab[cpu_model].pdr; return SCPE_OK; } @@ -2663,14 +2821,18 @@ 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 */ -if (left) curr = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par; +if ((pa & 0100) == 0) /* 1 for super, user */ + idx = idx | 020; +if (pa & 0400) /* 1 for user only */ + idx = idx | 040; +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; -if (left) APRFILE[idx] = ((APRFILE[idx] & 0177777) | - (((uint32) (data & cpu_tab[cpu_model].par)) << 16)) & ~(PDR_A|PDR_W); +if (access == WRITEB) + data = (pa & 1)? (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); else APRFILE[idx] = ((APRFILE[idx] & ~0177777) | (data & cpu_tab[cpu_model].pdr)) & ~(PDR_A|PDR_W); return SCPE_OK; @@ -2680,7 +2842,8 @@ return SCPE_OK; t_stat PSW_rd (int32 *data, int32 pa, int32 access) { -if (access == READC) *data = PSW; +if (access == READC) + *data = PSW; else *data = get_PSW (); return SCPE_OK; } @@ -2834,10 +2997,13 @@ MMR2 = 0; MMR3 = 0; trap_req = 0; wait_state = 0; -if (M == NULL) M = (uint16 *) calloc (MEMSIZE >> 1, sizeof (uint16)); -if (M == NULL) return SCPE_MEM; +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; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); set_r_display (0, MD_KER); @@ -2851,17 +3017,21 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) int32 iodata; t_stat stat; -if (vptr == NULL) return SCPE_ARG; +if (vptr == NULL) + return SCPE_ARG; if (sw & SWMASK ('V')) { /* -v */ - if (addr >= VASIZE) return SCPE_NXM; + if (addr >= VASIZE) + return SCPE_NXM; addr = relocC (addr, sw); /* relocate */ - if (addr >= MAXMEMSIZE) return SCPE_REL; + if (addr >= MAXMEMSIZE) + return SCPE_REL; } if (addr < MEMSIZE) { *vptr = M[addr >> 1] & 0177777; return SCPE_OK; } -if (addr < IOPAGEBASE) return SCPE_NXM; +if (addr < IOPAGEBASE) + return SCPE_NXM; stat = iopageR (&iodata, addr, READC); *vptr = iodata; return stat; @@ -2872,15 +3042,18 @@ 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; + if (addr >= VASIZE) + return SCPE_NXM; addr = relocC (addr, sw); /* relocate */ - if (addr >= MAXMEMSIZE) return SCPE_REL; + if (addr >= MAXMEMSIZE) + return SCPE_REL; } if (addr < MEMSIZE) { M[addr >> 1] = val & 0177777; return SCPE_OK; } -if (addr < IOPAGEBASE) return SCPE_NXM; +if (addr < IOPAGEBASE) + return SCPE_NXM; return iopageW ((int32) val, addr, WRITEC); } @@ -2893,8 +3066,10 @@ REG *rptr; int32 i; rptr = find_reg ("R0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < 6; i++, rptr++) rptr->loc = (void *) ®FILE[i][rs]; +if (rptr == NULL) + return; +for (i = 0; i < 6; i++, rptr++) + rptr->loc = (void *) ®FILE[i][rs]; rptr->loc = (void *) &STACKFILE[cm]; return; } @@ -2907,12 +3082,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -2921,7 +3098,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -2939,14 +3117,17 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +if (di < 0) + di = di + hst_lnt; fprintf (st, "PC PSW src dst IR\n\n"); for (k = 0; k < lnt; k++) { /* print specified */ h = &hst[(di++) % hst_lnt]; /* entry pointer */ @@ -2961,7 +3142,8 @@ for (k = 0; k < lnt; k++) { /* print specified */ ((ir & 0007700) >= 0004000))) fprintf (st, " %06o ", h->dst); else fprintf (st, " "); - for (j = 0; j < HIST_ILNT; j++) sim_eval[j] = h->inst[j]; + for (j = 0; j < HIST_ILNT; j++) + sim_eval[j] = h->inst[j]; if ((fprint_sym (st, h->pc & ~HIST_VLD, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) fprintf (st, "(undefined) %06o", h->inst[0]); fputc ('\n', st); /* end line */ diff --git a/PDP11/pdp11_cpumod.c b/PDP11/pdp11_cpumod.c index 4624b0e2..c30d5a88 100644 --- a/PDP11/pdp11_cpumod.c +++ b/PDP11/pdp11_cpumod.c @@ -49,13 +49,15 @@ /* 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 */ @@ -328,8 +330,10 @@ t_stat REG_wr (int32 data, int32 pa, int32 access) { int32 reg = pa & 07; -if (access == WRITE) R[reg] = data; -else if (pa & 1) R[reg] = (R[reg] & 0377) | (data << 8); +if (access == WRITE) + R[reg] = data; +else if (pa & 1) + R[reg] = (R[reg] & 0377) | (data << 8); else R[reg] = (R[reg] & ~0377) | data; return SCPE_OK; } @@ -680,14 +684,19 @@ switch ((pa >> 1) & 017) { /* decode pa<4:1> */ 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; + 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 */ + if (CPUT (CPUT_73B)) /* must be 0 for 73B */ + *data = 0; else *data = HITMISS | 010; /* must be nz for 11/8X */ return SCPE_OK; @@ -812,12 +821,15 @@ 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? */ + if (JCSR & CSRJ_LTCI) /* force LTC int enb? */ + clk_fie = 1; else clk_fie = 0; - if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */ + if (JCSR & CSRJ_LTCD) /* force LTC reg nxm? */ + clk_fnxm = 1; else clk_fnxm = 0; t = CSRJ_LTCSEL (JCSR); /* get freq sel */ - if (t) clk_tps = clk_tps_map[t]; + if (t) + clk_tps = clk_tps_map[t]; else clk_tps = clk_default; return SCPE_OK; @@ -900,12 +912,15 @@ 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? */ + if (JCSR & CSRJ_LTCI) /* force LTC int enb? */ + clk_fie = 1; else clk_fie = 0; - if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */ + if (JCSR & CSRJ_LTCD) /* force LTC reg nxm? */ + clk_fnxm = 1; else clk_fnxm = 0; t = CSRJ_LTCSEL (JCSR); /* get freq sel */ - if (t) clk_tps = clk_tps_map[t]; + if (t) + clk_tps = clk_tps_map[t]; else clk_tps = clk_default; return SCPE_OK; @@ -1016,9 +1031,11 @@ int32 bit; if (toy_state == 0) { curr = time (NULL); /* get curr time */ - if (curr == (time_t) -1) return 0; /* error? */ + if (curr == (time_t) -1) /* error? */ + return 0; ctm = localtime (&curr); /* decompose */ - if (ctm == NULL) return 0; /* error? */ + if (ctm == NULL) /* error? */ + return 0; toy_data[TOY_HSEC] = 0x50; toy_data[TOY_SEC] = toy_set (ctm->tm_sec); toy_data[TOY_MIN] = toy_set (ctm->tm_min); @@ -1069,12 +1086,16 @@ return SCPE_OK; t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr != NULL) return SCPE_ARG; -if (val >= MOD_MAX) return SCPE_IERR; -if (val == (int32) cpu_model) return SCPE_OK; +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); -if (MEMSIZE > cpu_tab[val].maxm) return SCPE_INCOMP; +if (MEMSIZE > cpu_tab[val].maxm) + return SCPE_INCOMP; cpu_model = val; cpu_type = 1u << cpu_model; cpu_opt = cpu_tab[cpu_model].std; @@ -1090,8 +1111,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; } @@ -1100,16 +1122,20 @@ return SCPE_OK; t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val & cpu_tab[cpu_model].opt) == 0) return SCPE_ARG; +if (cptr) + return SCPE_ARG; +if ((val & cpu_tab[cpu_model].opt) == 0) + return SCPE_ARG; cpu_opt = cpu_opt | val; return SCPE_OK; } t_stat cpu_clr_opt (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val & cpu_tab[cpu_model].opt) == 0) return SCPE_ARG; +if (cptr) + return SCPE_ARG; +if ((val & cpu_tab[cpu_model].opt) == 0) + return SCPE_ARG; cpu_opt = cpu_opt & ~val; return SCPE_OK; } @@ -1122,15 +1148,20 @@ int32 mc = 0; uint32 i, clim; uint16 *nM; -if ((val <= 0) || (val > (int32) cpu_tab[cpu_model].maxm) || - ((val & 07777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1]; +if ((val <= 0) || + (val > (int32) cpu_tab[cpu_model].maxm) || + ((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 = (uint16 *) calloc (val >> 1, sizeof (uint16)); -if (nM == NULL) return SCPE_MEM; +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]; +for (i = 0; i < clim; i = i + 2) + nM[i >> 1] = M[i >> 1]; free (M); M = nM; MEMSIZE = val; @@ -1146,7 +1177,8 @@ t_stat cpu_set_bus (int32 opt) DEVICE *dptr; uint32 i, mask; -if (opt & BUS_U) mask = DEV_UBUS; /* Unibus variant? */ +if (opt & BUS_U) /* Unibus variant? */ + mask = DEV_UBUS; else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus devices? */ mask = DEV_QBUS | DEV_Q18; else mask = DEV_QBUS; /* must be 22b */ @@ -1155,7 +1187,8 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { !(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)); + if (sim_log) + fprintf (sim_log, "Disabling %s\n", sim_dname (dptr)); dptr->flags = dptr->flags | DEV_DIS; } } @@ -1172,7 +1205,8 @@ CCR = 0; HITMISS = 0; CPUERR = 0; MEMERR = 0; -if (!CPUT (CPUT_J)) MAINT = 0; +if (!CPUT (CPUT_J)) + MAINT = 0; MBRK = 0; WCS = 0; if (CPUT (CPUT_JB|CPUT_JE)) @@ -1186,8 +1220,10 @@ UCSR = 0; uba_last = 0; DR = 0; toy_state = 0; -for (i = 0; i < UBM_LNT_LW; i++) ub_map[i] = 0; -for (i = 0; i < TOY_LNT; i++) toy_data[i] = 0; +for (i = 0; i < UBM_LNT_LW; i++) + ub_map[i] = 0; +for (i = 0; i < TOY_LNT; i++) + toy_data[i] = 0; return SCPE_OK; } diff --git a/PDP11/pdp11_cr.c b/PDP11/pdp11_cr.c index 981fedf1..55e6b71a 100644 --- a/PDP11/pdp11_cr.c +++ b/PDP11/pdp11_cr.c @@ -440,7 +440,7 @@ static t_bool readCardImage ( FILE *fp, int c1, c2, c3, col; if (DEBUG_PRS (cr_dev)) - fprintf (sim_deb, "readCardImage pos %d\n", ftell (fp)); + fprintf (sim_deb, "readCardImage pos %d\n", (int) ftell (fp)); /* get card header bytes */ c1 = fgetc (fp); c2 = fgetc (fp); diff --git a/PDP11/pdp11_dc.c b/PDP11/pdp11_dc.c index 743c0391..1228538e 100644 --- a/PDP11/pdp11_dc.c +++ b/PDP11/pdp11_dc.c @@ -25,6 +25,9 @@ dci,dco DC11 terminal input/output + 19-Nov-2008 RMS Revised for common TMXR show routines + Revised to autoconfigure vectors + The simulator supports both hardwired and modem-like behavior. If modem control is not enabled, carrier detect, ring, and carrier change are never set. @@ -126,11 +129,7 @@ t_stat dci_svc (UNIT *uptr); t_stat dco_svc (UNIT *uptr); t_stat dcx_attach (UNIT *uptr, char *cptr); t_stat dcx_detach (UNIT *uptr); -t_stat dcx_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dcx_show (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dcx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat dcx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat dcx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc); void dcx_enbdis (int32 dis); void dci_clr_int (int32 ln); void dci_set_int (int32 ln); @@ -166,19 +165,20 @@ REG dci_reg[] = { }; MTAB dci_mod[] = { - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &dcx_summ }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &dcx_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &dcx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &dcx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dcx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &dcx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dcx_desc }, { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - &set_vec, &dcx_show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "lines", "LINES", - &dcx_set_lines, &dcx_show_lines }, + { MTAB_XTD|MTAB_VDV, 1, "VECTOR", NULL, + &set_vec, &show_vec_mux, (void *) &dcx_desc }, + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &dcx_set_lines, &tmxr_show_lines, (void *) &dcx_desc }, { 0 } }; @@ -187,7 +187,7 @@ DEVICE dci_dev = { 1, 10, 31, 1, 8, 8, NULL, NULL, &dcx_reset, NULL, &dcx_attach, &dcx_detach, - &dci_dib, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS + &dci_dib, DEV_FLTA | DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS }; /* DCO data structures @@ -423,7 +423,8 @@ if (dcx_ldsc[ln].conn) { /* connected? */ if (dcx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &dcx_ldsc[ln]; /* get line */ c = sim_tt_outcvt (dco_buf[ln], TT_GET_MODE (dco_unit[ln].flags)); - if (c >= 0) tmxr_putc_ln (lp, c); /* output char */ + if (c >= 0) /* output char */ + tmxr_putc_ln (lp, c); tmxr_poll_tx (&dcx_desc); /* poll xmt */ } else { @@ -554,43 +555,12 @@ sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat dcx_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < DCX_LINES; i++) t = t + (dcx_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat dcx_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < DCX_LINES; i++) t = t + (dcx_ldsc[i].conn != 0); -if (t) { - for (i = 0; i < DCX_LINES; i++) { - if (dcx_ldsc[i].conn) { - if (val) tmxr_fconns (st, &dcx_ldsc[i], i); - else tmxr_fstats (st, &dcx_ldsc[i], i); - } - } - } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - /* Enable/disable device */ void dcx_enbdis (int32 dis) { if (dis) { - dci_dev.flags = dco_dev.flags | DEV_DIS; + dci_dev.flags = dci_dev.flags | DEV_DIS; dco_dev.flags = dco_dev.flags | DEV_DIS; } else { @@ -600,13 +570,6 @@ else { return; } -/* SHOW VECTOR processor */ - -t_stat dcx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -return show_vec (st, uptr, dcx_desc.lines * 2, desc); -} - /* Change number of lines */ t_stat dcx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -614,12 +577,16 @@ t_stat dcx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = get_uint (cptr, 10, DCX_LINES, &r); -if ((r != SCPE_OK) || (newln == dcx_desc.lines)) return r; -if (newln == 0) return SCPE_ARG; +if ((r != SCPE_OK) || (newln == dcx_desc.lines)) + return r; +if (newln == 0) + return SCPE_ARG; if (newln < dcx_desc.lines) { - for (i = newln, t = 0; i < dcx_desc.lines; i++) t = t | dcx_ldsc[i].conn; + for (i = newln, t = 0; i < dcx_desc.lines; i++) + t = t | dcx_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < dcx_desc.lines; i++) { @@ -641,11 +608,3 @@ dcx_desc.lines = newln; dci_dib.lnt = newln * 010; /* upd IO page lnt */ return auto_config (dci_dev.name, newln); /* auto config */ } - -/* Show number of lines */ - -t_stat dcx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "lines=%d", dcx_desc.lines); -return SCPE_OK; -} diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index bfa55521..4255a53b 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -26,6 +26,7 @@ The author gratefully acknowledges the help of Max Burnet, Megan Gentry, and John Wilson in resolving questions about the PDP-11 + 19-Nov-08 RMS Moved I/O support routines to I/O library 16-May-08 RMS Added KE11A, DC11 support 02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas) 25-Jan-08 RMS Added RC11, KG11A support (from John Dundas) @@ -575,6 +576,8 @@ typedef struct pdp_dib DIB; #define IOLN_KE 020 #define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */ #define IOLN_TC 012 +#define IOBA_QDSS (IOPAGEBASE + 017400) /* QDSS */ +#define IOLN_QDSS 002 #define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */ #define IOLN_RK 020 #define IOBA_RC (IOPAGEBASE + 017440) /* RC11/RS64 */ @@ -823,14 +826,6 @@ int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf); int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf); int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (char *name, int32 nctrl); -t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp); - int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf); int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf); @@ -844,4 +839,6 @@ t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc); int32 clk_cosched (int32 wait); +#include "pdp11_io_lib.h" + #endif diff --git a/PDP11/pdp11_dl.c b/PDP11/pdp11_dl.c index 65ade265..00dff0ec 100644 --- a/PDP11/pdp11_dl.c +++ b/PDP11/pdp11_dl.c @@ -1,6 +1,6 @@ /* pdp11_dl.c: PDP-11 multiple terminal interface simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ dli,dlo DL11 terminal input/output + 19-Nov-2008 RMS Revised for common TMXR show routines + Revised to autoconfigure vectors 20-May-2008 RMS Added modem control support */ @@ -93,11 +95,7 @@ t_stat dli_svc (UNIT *uptr); t_stat dlo_svc (UNIT *uptr); t_stat dlx_attach (UNIT *uptr, char *cptr); t_stat dlx_detach (UNIT *uptr); -t_stat dlx_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dlx_show (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dlx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat dlx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc); void dlx_enbdis (int32 dis); void dli_clr_int (int32 ln, uint32 wd); void dli_set_int (int32 ln, uint32 wd); @@ -134,19 +132,20 @@ REG dli_reg[] = { }; MTAB dli_mod[] = { - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &dlx_summ }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &dlx_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &dlx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &dlx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dlx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &dlx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dlx_desc }, { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - &set_vec, &dlx_show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "lines", "LINES", - &dlx_set_lines, &dlx_show_lines }, + { MTAB_XTD|MTAB_VDV, 1, "VECTOR", NULL, + &set_vec, &show_vec_mux, (void *) &dlx_desc }, + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &dlx_set_lines, &tmxr_show_lines, (void *) &dlx_desc }, { 0 } }; @@ -155,7 +154,7 @@ DEVICE dli_dev = { 1, 10, 31, 1, 8, 8, NULL, NULL, &dlx_reset, NULL, &dlx_attach, &dlx_detach, - &dli_dib, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS + &dli_dib, DEV_FLTA | DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS }; /* DLO data structures @@ -258,7 +257,8 @@ TMLN *lp = &dlx_ldsc[ln]; switch ((PA >> 1) & 03) { /* decode PA<2:1> */ case 00: /* tti csr */ - if (PA & 1) return SCPE_OK; /* odd byte RO */ + if (PA & 1) /* odd byte RO */ + return SCPE_OK; if ((data & CSR_IE) == 0) dli_clr_int (ln, DLI_RCI); else if ((dli_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE) @@ -298,7 +298,8 @@ switch ((PA >> 1) & 03) { /* decode PA<2:1> */ return SCPE_OK; case 02: /* tto csr */ - if (PA & 1) return SCPE_OK; + if (PA & 1) + return SCPE_OK; if ((data & CSR_IE) == 0) dlo_clr_int (ln); else if ((dlo_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE) @@ -324,7 +325,8 @@ t_stat dli_svc (UNIT *uptr) { int32 ln, c, temp; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; sim_activate (uptr, tmxr_poll); /* continue poll */ ln = tmxr_poll_conn (&dlx_desc); /* look for connect */ if (ln >= 0) { /* got one? rcv enb */ @@ -376,7 +378,8 @@ if (dlx_ldsc[ln].conn) { /* connected? */ if (dlx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &dlx_ldsc[ln]; /* get line */ c = sim_tt_outcvt (dlo_buf[ln], TT_GET_MODE (dlo_unit[ln].flags)); - if (c >= 0) tmxr_putc_ln (lp, c); /* output char */ + if (c >= 0) /* output char */ + tmxr_putc_ln (lp, c); tmxr_poll_tx (&dlx_desc); /* poll xmt */ } else { @@ -426,7 +429,8 @@ return 0; void dlo_clr_int (int32 ln) { dlo_ireq &= ~(1 << ln); /* clr xmit int */ -if (dlo_ireq == 0) CLR_INT (DLO); /* all clr? */ +if (dlo_ireq == 0) /* all clr? */ + CLR_INT (DLO); else SET_INT (DLO); /* no, set intr */ return; } @@ -490,7 +494,8 @@ t_stat dlx_attach (UNIT *uptr, char *cptr) t_stat r; r = tmxr_attach (&dlx_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ +if (r != SCPE_OK) /* error */ + return r; sim_activate (uptr, tmxr_poll); /* start poll */ return SCPE_OK; } @@ -509,43 +514,12 @@ sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat dlx_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < DLX_LINES; i++) t = t + (dlx_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat dlx_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < DLX_LINES; i++) t = t + (dlx_ldsc[i].conn != 0); -if (t) { - for (i = 0; i < DLX_LINES; i++) { - if (dlx_ldsc[i].conn) { - if (val) tmxr_fconns (st, &dlx_ldsc[i], i); - else tmxr_fstats (st, &dlx_ldsc[i], i); - } - } - } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - /* Enable/disable device */ void dlx_enbdis (int32 dis) { if (dis) { - dli_dev.flags = dlo_dev.flags | DEV_DIS; + dli_dev.flags = dli_dev.flags | DEV_DIS; dlo_dev.flags = dlo_dev.flags | DEV_DIS; } else { @@ -555,13 +529,6 @@ else { return; } -/* SHOW VECTOR processor */ - -t_stat dlx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -return show_vec (st, uptr, dlx_desc.lines * 2, desc); -} - /* Change number of lines */ t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -569,12 +536,16 @@ t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = get_uint (cptr, 10, DLX_LINES, &r); -if ((r != SCPE_OK) || (newln == dlx_desc.lines)) return r; -if (newln == 0) return SCPE_ARG; +if ((r != SCPE_OK) || (newln == dlx_desc.lines)) + return r; +if (newln == 0) + return SCPE_ARG; if (newln < dlx_desc.lines) { - for (i = newln, t = 0; i < dlx_desc.lines; i++) t = t | dlx_ldsc[i].conn; + for (i = newln, t = 0; i < dlx_desc.lines; i++) + t = t | dlx_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < dlx_desc.lines; i++) { @@ -596,11 +567,3 @@ dlx_desc.lines = newln; dli_dib.lnt = newln * 010; /* upd IO page lnt */ return auto_config (dli_dev.name, newln); /* auto config */ } - -/* Show number of lines */ - -t_stat dlx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "lines=%d", dlx_desc.lines); -return SCPE_OK; -} diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c index 72652d91..a8a20535 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-2007, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ dz DZ11 terminal multiplexor + 29-Dec-08 RMS Added MTAB_NC to SET LOG command (found by Walter Mueller) + 19-Nov-08 RMS Revised for common TMXR show routines 18-Jun-07 RMS Added UNIT_IDLE flag 29-Oct-06 RMS Synced poll and clock 22-Nov-05 RMS Revised for new terminal processing routines @@ -175,9 +177,6 @@ void dz_clr_rxint (int32 dz); void dz_set_rxint (int32 dz); void dz_clr_txint (int32 dz); void dz_set_txint (int32 dz); -t_stat dz_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_show (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc); 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); @@ -197,8 +196,6 @@ DIB dz_dib = { UNIT dz_unit = { UDATA (&dz_svc, UNIT_IDLE|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) }, @@ -222,24 +219,25 @@ MTAB dz_mod[] = { { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &dz_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &dz_summ }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &dz_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &dz_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dz_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &dz_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &dz_desc }, { 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 }, + { MTAB_XTD|MTAB_VDV, DZ_LINES, "VECTOR", "VECTOR", + &set_vec, &show_vec_mux, (void *) &dz_desc }, #if !defined (VM_PDP10) { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", &set_addr_flt, NULL, NULL }, #endif - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &dz_setnl, NULL, &dz_nlreg }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "LOG", + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &dz_setnl, &tmxr_show_lines, (void *) &dz_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NC, 0, NULL, "LOG", &dz_set_log, NULL, &dz_desc }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "NOLOG", + { MTAB_XTD | MTAB_VDV | MTAB_NC, 0, NULL, "NOLOG", &dz_set_nolog, NULL, &dz_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "LOG", NULL, NULL, &dz_show_log, &dz_desc }, @@ -270,7 +268,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ 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 */ + if (!dz_rbuf[dz]) /* empty? re-enable */ + dz_sae[dz] = 1; tmxr_poll_rx (&dz_desc); /* poll input */ dz_update_rcvi (); /* update rx intr */ } @@ -305,16 +304,19 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ 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_CLR) /* clr? reset */ + dz_clear (dz, FALSE); if (data & CSR_MSE) /* MSE? start poll */ sim_activate (&dz_unit, clk_cosched (tmxr_poll)); else dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY); - if ((data & CSR_RIE) == 0) dz_clr_rxint (dz); /* RIE = 0? */ + if ((data & CSR_RIE) == 0) /* RIE = 0? */ + dz_clr_rxint (dz); 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? */ + if ((data & CSR_TIE) == 0) /* TIE = 0? */ + dz_clr_txint (dz); 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); @@ -324,7 +326,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ 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 */ + if (dz_lpr[dz] & LPR_RCVE) /* rcv enb? on */ + lp->rcve = 1; else lp->rcve = 0; /* else line off */ tmxr_poll_rx (&dz_desc); /* poll input */ dz_update_rcvi (); /* update rx intr */ @@ -367,7 +370,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ line = (dz * DZ_LINES) + CSR_GETTL (dz_csr[dz]); lp = &dz_ldsc[line]; /* get line desc */ c = sim_tt_outcvt (dz_tdr[dz], TT_GET_MODE (dz_unit.flags)); - if (c >= 0) tmxr_putc_ln (lp, c); /* store char */ + if (c >= 0) /* store char */ + tmxr_putc_ln (lp, c); tmxr_poll_tx (&dz_desc); /* poll output */ dz_update_xmti (); /* update int */ } @@ -399,7 +403,7 @@ if (t) { /* any enabled? */ 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 */ + 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 */ @@ -420,8 +424,10 @@ 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 # */ + if (c & SCPE_BREAK) /* break? frame err */ + c = RBUF_VALID | RBUF_FRME; + if (c) /* or in line # */ + c = c | (i << RBUF_V_RLINE); } /* end for */ return c; } @@ -492,7 +498,8 @@ return; 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? */ +if (dz_rxi == 0) /* all clr? */ + CLR_INT (DZRX); else SET_INT (DZRX); /* no, set intr */ return; } @@ -520,7 +527,8 @@ 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? */ +if (dz_txi == 0) /* all clr? */ + CLR_INT (DZTX); else SET_INT (DZTX); /* no, set intr */ return; } @@ -554,7 +562,8 @@ 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 */ +if (flag) /* INIT? clr all */ + dz_tcr[dz] = 0; else dz_tcr[dz] &= ~0377; /* else save dtr */ dz_tdr[dz] = 0; dz_sae[dz] = 1; /* alarm on */ @@ -562,7 +571,8 @@ 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 */ + if (!dz_ldsc[line].conn) /* set xmt enb */ + dz_ldsc[line].xmte = 1; dz_ldsc[line].rcve = 0; /* clr rcv enb */ } return SCPE_OK; @@ -572,7 +582,8 @@ t_stat dz_reset (DEVICE *dptr) { int32 i, ndev; -for (i = 0; i < DZ_MUXES; i++) dz_clear (i, TRUE); /* init muxes */ +for (i = 0; i < DZ_MUXES; i++) /* init muxes */ + dz_clear (i, TRUE); dz_rxi = dz_txi = 0; /* clr master int */ CLR_INT (DZRX); CLR_INT (DZTX); @@ -590,15 +601,18 @@ 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 (r != SCPE_OK) /* error? */ + return r; 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_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"); + if (sim_log) + fprintf (sim_log, "Auto disconnect activated\n"); } } return SCPE_OK; @@ -611,37 +625,6 @@ t_stat dz_detach (UNIT *uptr) return tmxr_detach (&dz_desc, uptr); } -/* Show summary processor */ - -t_stat dz_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < dz_desc.lines; i++) { /* get num conn */ - if (dz_ldsc[i].conn) t = t + 1; - } -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat dz_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < dz_desc.lines; i++) { /* loop thru conn */ - if (dz_ldsc[i].conn) { - t = 1; - if (val) tmxr_fconns (st, &dz_ldsc[i], i); - else tmxr_fstats (st, &dz_ldsc[i], i); - } - } -if (t == 0) fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - /* SET LINES processor */ t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -649,12 +632,16 @@ t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t, ndev; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = (int32) get_uint (cptr, 10, (DZ_MUXES * DZ_LINES), &r); -if ((r != SCPE_OK) || (newln == dz_desc.lines)) return r; -if ((newln == 0) || (newln % DZ_LINES)) return SCPE_ARG; +if ((r != SCPE_OK) || (newln == dz_desc.lines)) + return r; +if ((newln == 0) || (newln % DZ_LINES)) + return SCPE_ARG; if (newln < dz_desc.lines) { - for (i = newln, t = 0; i < dz_desc.lines; i++) t = t | dz_ldsc[i].conn; + for (i = newln, t = 0; i < dz_desc.lines; i++) + t = t | dz_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < dz_desc.lines; i++) { @@ -672,13 +659,6 @@ ndev = ((dz_dev.flags & DEV_DIS)? 0: (dz_desc.lines / DZ_LINES)); return auto_config (dz_dev.name, ndev); /* auto config */ } -/* SHOW VECTOR processor */ - -t_stat dz_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -return show_vec (st, uptr, ((dz_desc.lines * 2) / DZ_LINES), desc); -} - /* SET LOG processor */ t_stat dz_set_log (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -687,12 +667,15 @@ char *tptr; t_stat r; int32 ln; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; tptr = strchr (cptr, '='); -if ((tptr == NULL) || (*tptr == 0)) return SCPE_ARG; +if ((tptr == NULL) || (*tptr == 0)) + return SCPE_ARG; *tptr++ = 0; ln = (int32) get_uint (cptr, 10, (DZ_MUXES * DZ_LINES), &r); -if ((r != SCPE_OK) || (ln >= dz_desc.lines)) return SCPE_ARG; +if ((r != SCPE_OK) || (ln >= dz_desc.lines)) + return SCPE_ARG; return tmxr_set_log (NULL, ln, tptr, desc); } @@ -703,9 +686,11 @@ t_stat dz_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc) t_stat r; int32 ln; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; ln = (int32) get_uint (cptr, 10, (DZ_MUXES * DZ_LINES), &r); -if ((r != SCPE_OK) || (ln >= dz_desc.lines)) return SCPE_ARG; +if ((r != SCPE_OK) || (ln >= dz_desc.lines)) + return SCPE_ARG; return tmxr_set_nolog (NULL, ln, NULL, desc); } diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c index dc2f9564..1f18ac9a 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -299,12 +299,14 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ case 2: /* STFPS */ FPS = FPS & FPS_RW; - if (dstspec <= 07) R[dstspec] = FPS; + if (dstspec <= 07) + R[dstspec] = FPS; else WriteW (FPS, GeteaW (dstspec)); break; case 3: /* STST */ - if (dstspec <= 07) R[dstspec] = FEC; + if (dstspec <= 07) + R[dstspec] = FEC; else WriteI ((FEC << 16) | FEA, GeteaFP (dstspec, LONG), dstspec, LONG); break; @@ -326,7 +328,8 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ case 2: /* ABSf */ ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; + 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); @@ -334,7 +337,8 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ case 3: /* NEGf */ ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; + 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); @@ -355,8 +359,10 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ 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); + 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); @@ -364,8 +370,10 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ 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); + 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); @@ -374,8 +382,10 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ 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 (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? */ @@ -385,7 +395,8 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ } 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; + F_LT (fsrc, fac)) + FPS = FPS ^ FPS_N; break; case 015: /* LDEXP */ @@ -395,11 +406,13 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ newV = 0; if ((dst > 0177) && (dst <= 0177600)) { if (dst < 0100000) { - if (fpnotrap (FEC_OVFLO)) fac = zero_fac; + if (fpnotrap (FEC_OVFLO)) + fac = zero_fac; newV = FPS_V; } else { - if (fpnotrap (FEC_UNFLO)) fac = zero_fac; + if (fpnotrap (FEC_UNFLO)) + fac = zero_fac; } } F_STORE (qdouble, fac, FR[ac]); @@ -413,23 +426,28 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ V = 0; C = 0; FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | (Z << PSW_V_Z); - if (dstspec <= 07) R[dstspec] = dst; + 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; + 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; + 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); + if ((FPS & (FPS_D + FPS_T)) == 0) + roundfp11 (&fac); } F_STORE (qdouble, fac, FR[ac]); FPS = setfcc (FPS, fac.h, 0); @@ -448,30 +466,35 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ i = FP_BIAS + 16; } C = 0; - if (exp <= FP_BIAS) dst = 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 (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; + if (sign) + dst = -dst; } } N = GET_SIGN_L (dst); Z = (dst == 0); V = 0; - if (C) fpnotrap (FEC_ICVT); + 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; + if (dstspec <= 07) + R[dstspec] = (dst >> 16) & 0177777; else WriteI (dst, GeteaFP (dstspec, leni), dstspec, leni); break; @@ -503,7 +526,8 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ 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; + 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); @@ -557,27 +581,32 @@ switch (spec >> 3) { /* case on spec */ return (R[reg] | ds); case 2: /* (R)+ */ - if (reg == 7) len = 2; + if (reg == 7) + len = 2; R[reg] = ((adr = R[reg]) + len) & 0177777; - if (update_MM) MMR1 = (len << 3) | reg; + 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; + 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 (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 (update_MM) + MMR1 = 0360 | reg; if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); adr = ReadW (adr | ds); @@ -610,7 +639,8 @@ return 0; uint32 ReadI (int32 VA, int32 spec, int32 len) { -if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16); +if ((len == WORD) || (spec == 027)) + return (ReadW (VA) << 16); return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777))); } @@ -663,7 +693,8 @@ return; void WriteI (int32 data, int32 VA, int32 spec, int32 len) { WriteW ((data >> 16) & 0177777, VA); -if ((len == WORD) || (spec == 027)) return; +if ((len == WORD) || (spec == 027)) + return; WriteW (data & 0177777, (VA & ~0177777) | ((VA + 2) & 0177777)); return; } @@ -687,10 +718,12 @@ if (spec <= 07) { return; } WriteW ((fptr->h >> FP_V_F0) & 0177777, VA); -if (spec == 027) return; +if (spec == 027) + return; exta = VA & ~0177777; WriteW ((fptr->h >> FP_V_F1) & 0177777, exta | ((VA + 2) & 0177777)); -if (len == LONG) return; +if (len == LONG) + return; WriteW ((fptr->l >> FP_V_F2) & 0177777, exta | ((VA + 4) & 0177777)); WriteW ((fptr->l >> FP_V_F3) & 0177777, exta | ((VA + 6) & 0177777)); return; @@ -704,10 +737,12 @@ int32 reg, exta; fpac_t fac, fsrc; reg = IR & 07; /* isolate reg */ -if (reg == 7) exta = isenable; /* choose I,D */ +if (reg == 7) /* choose I,D */ + exta = isenable; else exta = dsenable; if (IR & 000740) { /* defined? */ - if (CPUT (CPUT_03)) ReadW (exta | R[reg]); /* 11/03 reads word */ + if (CPUT (CPUT_03)) /* 11/03 reads word */ + ReadW (exta | R[reg]); ABORT (TRAP_ILL); } FEC = 0; /* no errors */ @@ -732,7 +767,8 @@ switch ((IR >> 3) & 3) { /* case IR<5:3> */ break; case 1: /* FSUB */ - if (fsrc.h != 0) fsrc.h = fsrc.h ^ FP_SIGN; /* invert sign */ + if (fsrc.h != 0) /* invert sign */ + fsrc.h = fsrc.h ^ FP_SIGN; addfp11 (&fac, &fsrc); break; @@ -757,8 +793,10 @@ if (FEC == 0) { /* no err? */ 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 if (FEC == FEC_OVFLO) /* ovf? trap set */ + V = 1; +else if (FEC == FEC_UNFLO) /* unf? trap set */ + V = N = 1; else return SCPE_IERR; /* what??? */ return SCPE_OK; } @@ -788,15 +826,19 @@ 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 */ +if (fsrcexp == 0) /* fsrc = 0? no op */ + return 0; ediff = facexp - fsrcexp; /* exponent diff */ -if (ediff >= 60) return 0; /* too big? no op */ +if (ediff >= 60) /* too big? no op */ + return 0; F_GET_FRAC_P (facp, facfrac); /* get fractions */ F_GET_FRAC_P (fsrcp, fsrcfrac); F_LSH_GUARD (facfrac); /* guard fractions */ F_LSH_GUARD (fsrcfrac); if (GET_SIGN (facp->h) != GET_SIGN (fsrcp->h)) { /* signs different? */ - if (ediff) { F_RSH_V (fsrcfrac, ediff, fsrcfrac); } /* sub, shf fsrc */ + if (ediff) { /* sub, shf fsrc */ + F_RSH_V (fsrcfrac, ediff, fsrcfrac); + } F_SUB (fsrcfrac, facfrac, facfrac); /* sub fsrc from fac */ if ((facfrac.h | facfrac.l) == 0) { /* result zero? */ *facp = zero_fac; /* no overflow */ @@ -933,7 +975,8 @@ if (facexp > ((FPS & FPS_D)? FP_BIAS + 56: FP_BIAS + 24)) { 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; +if ((fsrcfrac.h | fsrcfrac.l) == 0) + *fracp = zero_fac; else { F_LSH_V (fsrcfrac, facexp - FP_BIAS, fsrcfrac); fsrcexp = FP_BIAS; @@ -996,7 +1039,8 @@ 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; + if (mpy.h & 1) + result.h = result.h + mpc.h; F_RSH_1 (result); mpy.h = mpy.h >> 1; } @@ -1059,7 +1103,8 @@ 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? */ + if (qd) /* double or single? */ + quo.l = quo.l | 1; else quo.h = quo.h | 1; } F_LSH_1 (facfrac); /* shift divd */ @@ -1095,8 +1140,10 @@ return round_and_pack (facp, facexp, &quo, 1); int32 setfcc (int32 oldst, int32 result, int32 newV) { oldst = (oldst & ~FPS_CC) | newV; -if (GET_SIGN (result)) oldst = oldst | FPS_N; -if (GET_EXP (result) == 0) oldst = oldst | FPS_Z; +if (GET_SIGN (result)) + oldst = oldst | FPS_N; +if (GET_EXP (result) == 0) + oldst = oldst | FPS_Z; return oldst; } @@ -1116,7 +1163,8 @@ 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 */ + if (fpnotrap (FEC_OVFLO)) /* if no int, clear */ + *fptr = zero_fac; else *fptr = outf; /* return rounded */ return FPS_V; /* overflow */ } @@ -1158,10 +1206,12 @@ facp->l = frac.l & FP_FRACL; facp->h = (facp->h & FP_SIGN) | ((exp & FP_M_EXP) << FP_V_EXP) | (frac.h & FP_FRACH); if (exp > 0377) { - if (fpnotrap (FEC_OVFLO)) *facp = zero_fac; + if (fpnotrap (FEC_OVFLO)) + *facp = zero_fac; return FPS_V; } -if ((exp <= 0) && (fpnotrap (FEC_UNFLO))) *facp = zero_fac; +if ((exp <= 0) && (fpnotrap (FEC_UNFLO))) + *facp = zero_fac; return 0; } @@ -1178,10 +1228,12 @@ int32 fpnotrap (int32 code) static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV }; if ((code >= FEC_ICVT) && (code <= FEC_UNDFV) && - ((FPS & test_code[code >> 1]) == 0)) return TRUE; + ((FPS & test_code[code >> 1]) == 0)) + return TRUE; FPS = FPS | FPS_ER; FEC = code; FEA = (backup_PC - 2) & 0177777; -if ((FPS & FPS_ID) == 0) setTRAP (TRAP_FPE); +if ((FPS & FPS_ID) == 0) + setTRAP (TRAP_FPE); return FALSE; } diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c index e0fdc32d..0e25886a 100644 --- a/PDP11/pdp11_hk.c +++ b/PDP11/pdp11_hk.c @@ -1,6 +1,6 @@ /* pdp11_hk.c - RK611/RK06/RK07 disk controller - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -366,8 +366,6 @@ void hk_go (int32 drv); t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - /* HK data structures hk_dev HK device descriptor @@ -525,8 +523,10 @@ switch (j) { /* decode PA<4:1> */ case 007: /* HKAS */ *data = hkof; - for (i = 0; i < HK_NUMDR; i++) - if (hkds[i] & DS_ATA) *data = *data | (AS_U0 << i); + for (i = 0; i < HK_NUMDR; i++) { + if (hkds[i] & DS_ATA) + *data = *data | (AS_U0 << i); + } break; case 010: /* HKDC */ @@ -578,10 +578,10 @@ 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; + } if (DEBUG_PRI (hk_dev, HKDEB_RWR)) fprintf (sim_deb, ">>HK%d write: reg%d=%o\n", drv, j, data); @@ -599,17 +599,19 @@ switch (j) { /* decode PA<4:1> */ 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]); + 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? */ + if (data & CS1_DONE) /* write to DONE+IE? */ + SET_INT (HK); } 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 (SC02C) + hkspr = (hkspr & ~CS1_M_UAE) | GET_UAE (hkcs1); if ((data & CS1_GO) && !(hkcs1 & CS1_ERR)) /* go? */ hk_go (drv); break; @@ -627,7 +629,8 @@ switch (j) { /* decode PA<4:1> */ break; case 004: /* HKCS2 */ - if (data & CS2_CLR) hk_reset (&hk_dev); /* init? */ + if (data & CS2_CLR) /* init? */ + hk_reset (&hk_dev); else hkcs2 = (hkcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR; drv = GET_UNIT (hkcs2); break; @@ -642,7 +645,8 @@ switch (j) { /* decode PA<4:1> */ case 011: /* spare */ hkspr = data; - if (SC02C) hkcs1 = PUT_UAE (hkcs1, hkspr & 03); /* SC02C? upd UAE */ + if (SC02C) /* SC02C? upd UAE */ + hkcs1 = PUT_UAE (hkcs1, hkspr & 03); break; case 012: /* HKDB */ @@ -686,19 +690,19 @@ static uint8 fnc_cyl[16] = { }; fnc = GET_FNC (hkcs1); -if (DEBUG_PRI (hk_dev, HKDEB_OPS)) fprintf (sim_deb, - ">>HK%d strt: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, fnc, hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc); +if (DEBUG_PRI (hk_dev, HKDEB_OPS)) + fprintf (sim_deb, ">>HK%d strt: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", + drv, fnc, hkcs1, hkcs2, hkds[drv], hker[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 (fnc != FNC_NOP) /* !nop, clr msg sel */ + hkmr = hkmr & ~MR_MS; if (uptr->flags & UNIT_DIS) { /* nx unit? */ hkcs2 = hkcs2 | CS2_NED; /* set error flag */ update_hkcs (CS1_DONE, drv); /* done */ return; } -if (fnc_cdt[fnc] && - (((hkcs1 & CS1_DT) != 0) != /* need dtype match? */ - ((uptr->flags & UNIT_DTYPE) != 0))) { +if (fnc_cdt[fnc] && /* need dtype match? */ + (((hkcs1 & CS1_DT) != 0) != ((uptr->flags & UNIT_DTYPE) != 0))) { hk_cmderr (ER_DTY, drv); /* type error */ return; } @@ -710,7 +714,8 @@ if (fnc_att[fnc] && !(uptr->flags & UNIT_ATT)) { /* need attached? */ hk_cmderr (ER_UNS, drv); /* unsafe */ return; } -if (fnc_rdy[fnc] && sim_is_active (uptr)) return; /* need inactive? */ +if (fnc_rdy[fnc] && sim_is_active (uptr)) /* need inactive? */ + return; if (fnc_cyl[fnc] && /* need valid cyl */ ((GET_CY (hkdc) >= HK_CYL (uptr)) || /* bad cylinder */ (GET_SF (hkda) >= HK_NUMSF) || /* bad surface */ @@ -770,7 +775,7 @@ switch (fnc) { /* case on function */ 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 */ + sim_activate (uptr, hk_rwait + (hk_swait * t)); /* schedule */ uptr->FNC = fnc; /* save function */ uptr->CYL = hkdc; /* update cyl */ return; @@ -837,7 +842,8 @@ switch (fnc) { /* case on function */ dc = (fnc == FNC_SEEK)? hkdc: 0; /* get cyl */ hk_dif[drv] = dc - uptr->CYL; /* cyl diff */ t = abs (hk_dif[drv]) * hk_swait; /* |cyl diff| */ - if (t < hk_min2wait) t = hk_min2wait; /* min time */ + if (t < hk_min2wait) /* min time */ + t = hk_min2wait; uptr->CYL = dc; /* save cyl */ sim_activate (uptr, t); /* schedule */ update_hkcs (CS1_DONE, drv); /* done */ @@ -861,7 +867,8 @@ switch (fnc) { /* case on function */ } case FNC_WCHK: /* write check */ case FNC_READ: /* read */ - if (SC02C) ba = ((hkspr & XM_MMASK) << 16) | hkba; /* 22b addr? */ + if (SC02C) /* 22b addr? */ + ba = ((hkspr & XM_MMASK) << 16) | hkba; 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 */ @@ -883,7 +890,8 @@ switch (fnc) { /* case on function */ wc = 0; /* NXM, no xfr */ hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */ } - for (i = 0; i < wc; i++) hkxb[i] = comp; + for (i = 0; i < wc; i++) + hkxb[i] = comp; } else { /* normal */ if (t = Map_ReadW (ba, wc << 1, hkxb)) { /* get buf */ @@ -893,7 +901,8 @@ switch (fnc) { /* case on function */ 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 */ + for (i = wc; i < awc; i++) /* fill buf */ + hkxb[i] = 0; if (wc && !err) { /* write buf */ fxwrite (hkxb, sizeof (uint16), wc, uptr->fileref); err = ferror (uptr->fileref); @@ -902,7 +911,8 @@ switch (fnc) { /* case on function */ 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 */ + for ( ; i < wc; i++) /* fill buf */ + hkxb[i] = 0; if (hkcs2 & CS2_UAI) { /* no addr inc? */ if (t = Map_WriteW (ba, 2, &hkxb[wc - 1])) { wc = 0; /* NXM, no xfr */ @@ -920,7 +930,8 @@ switch (fnc) { /* case on function */ else { /* wchk */ i = fxread (hkxb, sizeof (uint16), wc, uptr->fileref); err = ferror (uptr->fileref); - for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */ + for ( ; i < wc; i++) /* fill buf */ + hkxb[i] = 0; awc = wc; for (wc = 0; wc < awc; wc++) { /* loop thru buf */ if (Map_ReadW (ba, 2, &comp)) { /* read word */ @@ -931,7 +942,8 @@ switch (fnc) { /* case on function */ hkcs2 = hkcs2 | CS2_WCE; /* set error */ break; } - if ((hkcs2 & CS2_UAI) == 0) ba = ba + 2; + if ((hkcs2 & CS2_UAI) + == 0) ba = ba + 2; } } /* end else wchk */ @@ -975,7 +987,8 @@ 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 (flag & CS1_DONE) /* clear go */ + hkcs1 = hkcs1 & ~CS1_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? */ @@ -990,9 +1003,8 @@ if (hker[drv] | (hkcs1 & (CS1_PAR | CS1_CTO)) | /* if err, set ERR */ (hkcs2 & CS2_ERR)) hkcs1 = hkcs1 | CS1_ERR; if ((flag & CS1_DONE) && /* set done && debug? */ (DEBUG_PRI (hk_dev, HKDEB_OPS))) - fprintf (sim_deb, - ">>HK%d done: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc); + fprintf (sim_deb, ">>HK%d done: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", + drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc); return; } @@ -1008,8 +1020,10 @@ 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 (hker[drv]) /* err? set ATA */ + hkds[drv] = hkds[drv] | DS_ATA; + if (hk_off[drv]) /* offset? set OF */ + hkds[drv] = hkds[drv] | DS_OF; if (hk_unit[drv].flags & UNIT_WPRT) /* write locked? */ hkds[drv] = hkds[drv] | DS_WRL; /* set WRL */ } @@ -1017,7 +1031,8 @@ 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; +if (hk_unit[drv].flags & UNIT_RK07) + hkds[drv] = hkds[drv] | DS_DT; return; } @@ -1066,18 +1081,22 @@ switch (msg) { ((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); + 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; + 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; + 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); @@ -1148,15 +1167,18 @@ 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; + 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; +if (hkxb == NULL) + hkxb = (uint16 *) calloc (HK_MAXFR, sizeof (uint16)); +if (hkxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -1169,7 +1191,8 @@ t_stat r; uptr->capac = HK_SIZE (uptr); r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ +if (r != SCPE_OK) /* error? */ + return r; drv = (uint32) (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 */ @@ -1180,10 +1203,12 @@ update_hkcs (CS1_DI, drv); /* upd ctlr status */ p = sim_fsize (uptr->fileref); /* get file size */ if (p == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; + 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 ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; if (p > (RK06_SIZE * sizeof (uint16))) { uptr->flags = uptr->flags | UNIT_RK07; uptr->capac = RK07_SIZE; @@ -1201,7 +1226,8 @@ t_stat hk_detach (UNIT *uptr) { uint32 drv; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; drv = (uint32) (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? */ @@ -1218,7 +1244,8 @@ return detach_unit (uptr); t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = val? RK07_SIZE: RK06_SIZE; return SCPE_OK; } @@ -1278,7 +1305,8 @@ t_stat hk_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 saved_PC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & CS2_M_UNIT; M[BOOT_CSR >> 1] = hk_dib.ba & DMASK; saved_PC = BOOT_ENTRY; diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c index c4e1c5e7..4ddea2a0 100644 --- a/PDP11/pdp11_io.c +++ b/PDP11/pdp11_io.c @@ -23,6 +23,7 @@ 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-08 RMS Moved I/O support routines to I/O library 16-May-08 RMS Added multiple DC11 support Renamed DL11 in autoconfigure 02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas) @@ -67,12 +68,10 @@ extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp); /* I/O data structures */ -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]; +t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); +t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); int32 int_vec[IPL_HLVL][32]; /* int req to vector */ - int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ static const int32 pirq_bit[7] = { @@ -126,7 +125,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); } @@ -142,7 +142,8 @@ for (i = IPL_HLVL - 1; i > nipl; i--) { /* loop thru lvls */ 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](); + if (int_ack[i][j]) + vec = int_ack[i][j](); else vec = int_vec[i][j]; return vec; /* return vector */ } /* end if t */ @@ -234,18 +235,23 @@ 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 */ + if (!ADDR_IS_MEM (ma)) /* NXM? err */ + return (lim - ba); + if (ma & 1) /* get byte */ + *buf++ = (M[ma >> 1] >> 8) & 0377; 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 = cpu_memsize; /* no, strt ok? */ + if (ADDR_IS_MEM (lim)) /* end ok? */ + alim = lim; + else if (ADDR_IS_MEM (ba)) /* no, strt ok? */ + alim = cpu_memsize; else return bc; /* no, err */ for ( ; ba < alim; ba++) { /* by bytes */ - if (ba & 1) *buf++ = (M[ba >> 1] >> 8) & 0377; /* get byte */ + if (ba & 1) + *buf++ = (M[ba >> 1] >> 8) & 0377; /* get byte */ else *buf++ = M[ba >> 1] & 0377; } return (lim - alim); @@ -261,14 +267,17 @@ 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 */ + if (!ADDR_IS_MEM (ma)) /* NXM? err */ + return (lim - ba); *buf++ = M[ma >> 1]; } return 0; } else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */ + if (ADDR_IS_MEM (lim)) /* end ok? */ + alim = lim; + else if (ADDR_IS_MEM (ba)) /* no, strt ok? */ + alim = cpu_memsize; else return bc; /* no, err */ for ( ; ba < alim; ba = ba + 2) { /* by words */ *buf++ = M[ba >> 1]; @@ -286,7 +295,8 @@ 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 (!ADDR_IS_MEM (ma)) /* NXM? err */ + return (lim - ba); if (ma & 1) M[ma >> 1] = (M[ma >> 1] & 0377) | ((uint16) *buf++ << 8); else M[ma >> 1] = (M[ma >> 1] & ~0377) | *buf++; @@ -294,12 +304,14 @@ if (cpu_bme) { /* map enabled? */ return 0; } else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */ + if (ADDR_IS_MEM (lim)) /* end ok? */ + alim = lim; + else if (ADDR_IS_MEM (ba)) /* no, strt ok? */ + alim = cpu_memsize; else return bc; /* no, err */ for ( ; ba < alim; ba++) { /* by bytes */ - if (ba & 1) M[ba >> 1] = (M[ba >> 1] & 0377) | - ((uint16) *buf++ << 8); + 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); @@ -315,14 +327,17 @@ 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 */ + if (!ADDR_IS_MEM (ma)) /* NXM? err */ + return (lim - ba); M[ma >> 1] = *buf++; } return 0; } else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */ + if (ADDR_IS_MEM (lim)) /* end ok? */ + alim = lim; + else if (ADDR_IS_MEM (ba)) /* no, strt ok? */ + alim = cpu_memsize; else return bc; /* no, err */ for ( ; ba < alim; ba = ba + 2) { /* by words */ M[ba >> 1] = *buf++; @@ -331,197 +346,6 @@ else { /* physical */ } } -/* 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 (NULL, 0); -} - -/* Show autoconfiguration status */ - -t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "autoconfiguration %s", (autcon_enb? "on": "off")); -return SCPE_OK; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newba = 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; -} - -/* Show device address */ - -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08o", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08o", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr != NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (NULL, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newvec = get_uint (cptr, 8, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec == VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -autcon_enb = 0; /* autoconfig off */ -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { - fprintf (st, "vector=%o", vec); - if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); - } -return SCPE_OK; -} - -/* 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; - } -return; -} - -/* Build Unibus tables */ - -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 (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 */ - } -return SCPE_OK; -} - /* Build tables from device list */ t_stat build_dib_tab (void) @@ -535,7 +359,8 @@ 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 */ +if (r = cpu_build_dib ()) /* build CPU entries */ + return r; 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? */ @@ -551,172 +376,3 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ } /* end for */ return SCPE_OK; } - -/* Show IO space */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -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 */ -return SCPE_OK; -} - -/* Autoconfiguration - - 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). - - A minus number of vectors indicates a field that should be calculated - but not placed in the DIB (RQ, TQ dynamic vectors) */ - -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -typedef struct { - char *dnam[AUTO_MAXC]; - int32 numc; - int32 numv; - uint32 amod; - uint32 vmod; - uint32 fixa[AUTO_MAXC]; - uint32 fixv[AUTO_MAXC]; - } AUTO_CON; - -AUTO_CON auto_tab[] = { - { { "DCI" }, DCX_LINES, 2, 0, 8, { 0 } }, /* DC11 - fx CSRs */ - { { "DLI" }, DLX_LINES, 2, 0, 8, { 0 } }, /* KL11/DL11/DLV11 - 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 (char *name, int32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -AUTO_CON *autp; -DEVICE *dptr; -DIB *dibp; -uint32 j, k, vmask, amask; - -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_io_lib.c b/PDP11/pdp11_io_lib.c new file mode 100644 index 00000000..7ca23fb9 --- /dev/null +++ b/PDP11/pdp11_io_lib.c @@ -0,0 +1,521 @@ +/* pdp11_io_lib.c: Unibus/Qbus common support routines + + Copyright (c) 1993-2008, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#if defined (VM_PDP10) /* PDP10 version */ +#include "pdp10_defs.h" + +#elif defined (VM_VAX) /* VAX version */ +#include "vax_defs.h" + +#else /* PDP-11 version */ +#include "pdp11_defs.h" +#endif +#include "sim_sock.h" +#include "sim_tmxr.h" + +extern FILE *sim_log; +extern DEVICE *sim_devices[]; +extern int32 autcon_enb; +extern int32 int_vec[IPL_HLVL][32]; +extern int32 (*int_ack[IPL_HLVL][32])(void); +extern t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); +extern t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); + +extern t_stat build_dib_tab (void); + +static DIB *iodibp[IOPAGESIZE >> 1]; + +/* 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 (NULL, 0); +} + +/* Show autoconfiguration status */ + +t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "autoconfiguration "); +fprintf (st, autcon_enb? "enabled": "disabled"); +return SCPE_OK; +} + +/* Change device address */ + +t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newba; +t_stat r; + +if (cptr == NULL) + return SCPE_ARG; +if ((val == 0) || (uptr == NULL)) + return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) + return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) + return SCPE_IERR; +newba = (uint32) get_uint (cptr, DEV_RDX, IOPAGEBASE+IOPAGEMASK, &r); /* get new */ +if (r != SCPE_OK) + return r; +if ((newba <= IOPAGEBASE) || /* > IO page base? */ + (newba % ((uint32) val))) /* check modulus */ + return SCPE_ARG; +dibp->ba = newba; /* store */ +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ +return SCPE_OK; +} + +/* Show device address */ + +t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +DEVICE *dptr; +DIB *dibp; + +if (uptr == NULL) + return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) + return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) + return SCPE_IERR; +fprintf (st, "address="); +fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); +if (dibp->lnt > 1) { + fprintf (st, "-"); + fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT); + } +if (dptr->flags & DEV_FLTA) + fprintf (st, "*"); +return SCPE_OK; +} + +/* Set address floating */ + +t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; + +if (cptr != NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) + return SCPE_IERR; +dptr->flags = dptr->flags | DEV_FLTA; /* floating */ +return auto_config (NULL, 0); /* autoconfigure */ +} + +/* Change device vector */ + +t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newvec; +t_stat r; + +if (cptr == NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) + return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) + return SCPE_IERR; +newvec = (uint32) get_uint (cptr, DEV_RDX, VEC_Q + 01000, &r); +if ((r != SCPE_OK) || (newvec == VEC_Q) || + ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || + (newvec & ((dibp->vnum > 1)? 07: 03))) + return SCPE_ARG; +dibp->vec = newvec; +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ +return SCPE_OK; +} + +/* Show device vector */ + +t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 vec, numvec; + +if (uptr == NULL) + return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) + return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) + return SCPE_IERR; +vec = dibp->vec; +if (arg) + numvec = arg; +else numvec = dibp->vnum; +if (vec == 0) + fprintf (st, "no vector"); +else { + fprintf (st, "vector="); + fprint_val (st, (t_value) vec, DEV_RDX, 16, PV_LEFT); + if (numvec > 1) { + fprintf (st, "-"); + fprint_val (st, (t_value) vec + (4 * (numvec - 1)), DEV_RDX, 16, PV_LEFT); + } + } +return SCPE_OK; +} + +/* Show vector for terminal multiplexor */ + +t_stat show_vec_mux (FILE *st, UNIT *uptr, int32 arg, void *desc) +{ +TMXR *mp = (TMXR *) desc; + +if ((mp == NULL) || (arg == 0)) + return SCPE_IERR; +return show_vec (st, uptr, ((mp->lines * 2) / arg), desc); +} + +/* 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; + } +return; +} + +/* Build Unibus tables */ + +t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp) +{ +int32 i, idx, vec, ilvl, ibit; + +if ((dptr == NULL) || (dibp == NULL)) /* validate args */ + return SCPE_IERR; +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 \n", sim_dname (dptr)); + fprint_val (stdout, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); + if (sim_log) { + fprintf (sim_log, "Device %s address conflict at \n", sim_dname (dptr)); + fprint_val (sim_log, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); + } + return SCPE_STOP; + } + if (dibp->rd) /* set rd dispatch */ + iodispR[idx] = dibp->rd; + if (dibp->wr) /* set wr dispatch */ + iodispW[idx] = dibp->wr; + iodibp[idx] = dibp; /* remember DIB */ + } +return SCPE_OK; +} + +/* Show IO space */ + +t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +uint32 i, j; +DEVICE *dptr; +DIB *dibp; + +if (build_dib_tab ()) /* build IO page */ + return SCPE_OK; +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 */ + fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); + fprintf (st, " - "); + fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT); + fprintf (st, "%c\t%s\n", /* print block entry */ + (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', + dptr? sim_dname (dptr): "CPU"); + } /* end if */ + } /* end for i */ +return SCPE_OK; +} + +/* Autoconfiguration + + 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). + + A minus number of vectors indicates a field that should be calculated + but not placed in the DIB (RQ, TQ dynamic vectors) */ + +#define AUTO_MAXC 4 +#define AUTO_CSRBASE 0010 +#define AUTO_VECBASE 0300 + +typedef struct { + char *dnam[AUTO_MAXC]; + int32 numc; + int32 numv; + uint32 amod; + uint32 vmod; + uint32 fixa[AUTO_MAXC]; + uint32 fixv[AUTO_MAXC]; + } AUTO_CON; + +AUTO_CON auto_tab[] = { + { { "DCI" }, DCX_LINES, 2, 0, 8, { 0 } }, /* DC11 - fx CSRs */ + { { "DLI" }, DLX_LINES, 2, 0, 8, { 0 } }, /* KL11/DL11/DLV11 - fx CSRs */ + { { 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 (char *name, int32 nctrl) +{ +uint32 csr = IOPAGEBASE + AUTO_CSRBASE; +uint32 vec = VEC_Q + AUTO_VECBASE; +AUTO_CON *autp; +DEVICE *dptr; +DIB *dibp; +uint32 j, k, vmask, amask; + +if (autcon_enb == 0) /* enabled? */ + return SCPE_OK; +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++) { + if (autp->dnam[j] == NULL) /* no device? */ + continue; + dptr = find_dev (autp->dnam[j]); /* find ctrl */ + if ((dptr == NULL) || /* enabled, floating? */ + (dptr->flags & DEV_DIS) || + !(dptr->flags & DEV_FLTA)) + continue; + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if (dibp == NULL) /* not there??? */ + return SCPE_IERR; + 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) /* flt CSR? gap */ + csr = csr + 2; + } /* end for i */ +return SCPE_OK; +} + +/* Factory bad block table creation routine + + This routine writes a DEC standard 044 compliant bad block table on the + last track of the specified unit. The bad block table consists of 10 + repetitions of the same table, formatted as follows: + + words 0-1 pack id number + words 2-3 cylinder/sector/surface specifications + : + words n-n+1 end of table (-1,-1) + + Inputs: + uptr = pointer to unit + sec = number of sectors per surface + wds = number of words per sector + Outputs: + sta = status code +*/ + +t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) +{ +int32 i; +t_addr da; +uint16 *buf; + +if ((sec < 2) || (wds < 16)) + return SCPE_ARG; +if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; +if (uptr->flags & UNIT_RO) + return SCPE_RO; +if (!get_yn ("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 = (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++) + sim_fwrite (buf, sizeof (uint16), wds, uptr->fileref); +free (buf); +if (ferror (uptr->fileref)) + return SCPE_IOERR; +return SCPE_OK; +} diff --git a/PDP11/pdp11_io_lib.h b/PDP11/pdp11_io_lib.h new file mode 100644 index 00000000..f12bbda0 --- /dev/null +++ b/PDP11/pdp11_io_lib.h @@ -0,0 +1,44 @@ +/* pdp11_io_lib.h: Unibus/Qbus common support routines header file + + Copyright (c) 1993-2008, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#ifndef _PDP11_IO_LIB_H_ +#define _PDP11_IO_LIB_H_ 0 + +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 set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc); +t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc); +t_stat show_vec_mux (FILE *st, UNIT *uptr, int32 arg, void *desc); +t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat auto_config (char *name, int32 nctrl); +t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); +void init_ubus_tab (void); +t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp); + +#endif diff --git a/PDP11/pdp11_lp.c b/PDP11/pdp11_lp.c index 691ca6ce..c535daed 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -123,7 +123,8 @@ DEVICE lpt_dev = { t_stat lpt_rd (int32 *data, int32 PA, int32 access) { -if ((PA & 02) == 0) *data = lpt_csr & LPTCSR_IMP; /* csr */ +if ((PA & 02) == 0) /* csr */ + *data = lpt_csr & LPTCSR_IMP; else *data = lpt_unit.buf; /* buffer */ return SCPE_OK; } @@ -131,14 +132,17 @@ 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); + 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 */ +else { /* buffer */ + if ((PA & 1) == 0) + lpt_unit.buf = data & 0177; lpt_csr = lpt_csr & ~CSR_DONE; CLR_INT (LPT); if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || @@ -151,7 +155,8 @@ return SCPE_OK; t_stat lpt_svc (UNIT *uptr) { lpt_csr = lpt_csr | CSR_ERR | CSR_DONE; -if (lpt_csr & CSR_IE) SET_INT (LPT); +if (lpt_csr & CSR_IE) + SET_INT (LPT); if ((uptr->flags & UNIT_ATT) == 0) return IORETURN (lpt_stopioe, SCPE_UNATT); fputc (uptr->buf & 0177, uptr->fileref); @@ -169,7 +174,8 @@ 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; +if ((lpt_unit.flags & UNIT_ATT) == 0) + lpt_csr = lpt_csr | CSR_ERR; CLR_INT (LPT); sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; @@ -181,7 +187,8 @@ t_stat reason; lpt_csr = lpt_csr & ~CSR_ERR; reason = attach_unit (uptr, cptr); -if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR; +if ((lpt_unit.flags & UNIT_ATT) == 0) + lpt_csr = lpt_csr | CSR_ERR; return reason; } diff --git a/PDP11/pdp11_mscp.h b/PDP11/pdp11_mscp.h index 4590ed7a..4e3c9698 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-2005, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a diff --git a/PDP11/pdp11_pclk.c b/PDP11/pdp11_pclk.c index f2ff1470..f83f5e83 100644 --- a/PDP11/pdp11_pclk.c +++ b/PDP11/pdp11_pclk.c @@ -233,8 +233,9 @@ switch ((PA >> 1) & 03) { 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 */ - } + if (data & CSR_FIX) /* fix? tick */ + pclk_tick (); + } else if (((old_csr & CSR_GO) == 0) || /* run 0 -> 1? */ (rv != CSR_GETRATE (old_csr))) { /* rate change? */ sim_cancel (&pclk_unit); /* cancel */ @@ -267,8 +268,10 @@ 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 */ + if (pclk_csr & CSR_IE) /* if IE, set int */ + SET_INT (PCLK); + if (pclk_csr & CSR_MODE) /* if rpt, reload */ + pclk_ctr = pclk_csb; else { pclk_csb = 0; /* else clr ctr */ pclk_csr = pclk_csr & ~CSR_GO; /* and clr go */ @@ -284,7 +287,8 @@ t_stat pclk_svc (UNIT *uptr) int32 rv; pclk_tick (); /* tick clock */ -if ((pclk_csr & CSR_GO) == 0) return SCPE_OK; /* done? */ +if ((pclk_csr & CSR_GO) == 0) /* done? */ + return SCPE_OK; rv = CSR_GETRATE (pclk_csr); /* get rate */ sim_activate (&pclk_unit, sim_rtcn_calb (rate[rv], TMR_PCLK)); return SCPE_OK; @@ -307,7 +311,8 @@ return SCPE_OK; t_stat pclk_set_line (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val == UNIT_LINE50HZ) rate[2] = 50; +if (val == UNIT_LINE50HZ) + rate[2] = 50; else rate[2] = 60; return SCPE_OK; } diff --git a/PDP11/pdp11_pt.c b/PDP11/pdp11_pt.c index 24875900..62a6d46d 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -190,8 +190,10 @@ 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); + 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) { @@ -223,7 +225,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); @@ -242,7 +245,8 @@ t_stat ptr_reset (DEVICE *dptr) { ptr_unit.buf = 0; ptr_csr = 0; -if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR; +if ((ptr_unit.flags & UNIT_ATT) == 0) + ptr_csr = ptr_csr | CSR_ERR; CLR_INT (PTR); sim_cancel (&ptr_unit); return SCPE_OK; @@ -253,7 +257,8 @@ t_stat ptr_attach (UNIT *uptr, char *cptr) t_stat reason; reason = attach_unit (uptr, cptr); -if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR; +if ((ptr_unit.flags & UNIT_ATT) == 0) + ptr_csr = ptr_csr | CSR_ERR; else ptr_csr = ptr_csr & ~CSR_ERR; return reason; } @@ -287,15 +292,18 @@ 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); + 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; + 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? */ @@ -312,7 +320,8 @@ return SCPE_NXM; /* can't get here */ t_stat ptp_svc (UNIT *uptr) { ptp_csr = ptp_csr | CSR_ERR | CSR_DONE; -if (ptp_csr & CSR_IE) SET_INT (PTP); +if (ptp_csr & CSR_IE) + SET_INT (PTP); if ((ptp_unit.flags & UNIT_ATT) == 0) return IORETURN (ptp_stopioe, SCPE_UNATT); if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { @@ -331,7 +340,8 @@ t_stat ptp_reset (DEVICE *dptr) { ptp_unit.buf = 0; ptp_csr = CSR_DONE; -if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR; +if ((ptp_unit.flags & UNIT_ATT) == 0) + ptp_csr = ptp_csr | CSR_ERR; CLR_INT (PTP); sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; @@ -342,7 +352,8 @@ t_stat ptp_attach (UNIT *uptr, char *cptr) t_stat reason; reason = attach_unit (uptr, cptr); -if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR; +if ((ptp_unit.flags & UNIT_ATT) == 0) + ptp_csr = ptp_csr | CSR_ERR; else ptp_csr = ptp_csr & ~CSR_ERR; return reason; } diff --git a/PDP11/pdp11_rf.c b/PDP11/pdp11_rf.c index 246957d6..cd2055ed 100644 --- a/PDP11/pdp11_rf.c +++ b/PDP11/pdp11_rf.c @@ -1,6 +1,6 @@ /* pdp11_rf.c: RF11 fixed head disk simulator - Copyright (c) 2006, Robert M Supnik + Copyright (c) 2006-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -246,9 +246,10 @@ int32 t, fnc; switch ((PA >> 1) & 07) { /* decode PA<3:1> */ case 0: /* RFCS */ - if (access == WRITEB) data = (PA & 1)? - (rf_cs & 0377) | (data << 8): (rf_cs & ~0377) | data; - if (data & RFCS_CLR) rf_reset (&rf_dev); /* clear? */ + if (access == WRITEB) + data = (PA & 1)? (rf_cs & 0377) | (data << 8): (rf_cs & ~0377) | data; + if (data & RFCS_CLR) /* clear? */ + rf_reset (&rf_dev); if ((data & RFCS_IE) == 0) /* int disable? */ CLR_INT (RF); /* clr int request */ else if ((rf_cs & (RFCS_DONE + RFCS_IE)) == RFCS_DONE) @@ -258,7 +259,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ ((fnc = GET_FUNC (rf_cs)) != RFNC_NOP)) { rf_unit.FUNC = fnc; /* save function */ t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new loc */ - if (t < 0) t = t + RF_NUMWD; /* wrap around? */ + if (t < 0) /* wrap around? */ + t = t + RF_NUMWD; sim_activate (&rf_unit, t * rf_time); /* schedule op */ rf_cs &= ~(RFCS_WCHK|RFCS_DPAR|RFCS_NED|RFCS_WLK|RFCS_MXFR|RFCS_DONE); CLR_INT (RF); @@ -269,26 +271,26 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ break; case 1: /* RFWC */ - if (access == WRITEB) data = (PA & 1)? - (rf_wc & 0377) | (data << 8): (rf_wc & ~0377) | data; + if (access == WRITEB) + data = (PA & 1)? (rf_wc & 0377) | (data << 8): (rf_wc & ~0377) | data; rf_wc = data; break; case 2: /* RFCMA */ - if (access == WRITEB) data = (PA & 1)? - (rf_cma & 0377) | (data << 8): (rf_cma & ~0377) | data; + if (access == WRITEB) + data = (PA & 1)? (rf_cma & 0377) | (data << 8): (rf_cma & ~0377) | data; rf_cma = data & RFCMA_RW; break; case 3: /* RFDA */ - if (access == WRITEB) data = (PA & 1)? - (rf_da & 0377) | (data << 8): (rf_da & ~0377) | data; + if (access == WRITEB) + data = (PA & 1)? (rf_da & 0377) | (data << 8): (rf_da & ~0377) | data; rf_da = data; break; case 4: /* RFDAE */ - if (access == WRITEB) data = (PA & 1)? - (rf_dae & 0377) | (data << 8): (rf_dae & ~0377) | data; + if (access == WRITEB) + data = (PA & 1)? (rf_dae & 0377) | (data << 8): (rf_dae & ~0377) | data; rf_dae = (rf_dae & ~RFDAE_W) | (data & RFDAE_W); break; @@ -364,7 +366,8 @@ do { } fbuf[da] = dat; /* write word */ rf_dbr = dat; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; } } da = (da + 1) & 017777777; /* incr disk addr */ @@ -460,7 +463,8 @@ t_stat rf_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 saved_PC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_CSR >> 1] = (rf_dib.ba & DMASK) + 012; saved_PC = BOOT_ENTRY; return SCPE_OK; @@ -475,7 +479,8 @@ uint32 ds_bytes = RF_DKSIZE * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; + if (p >= RF_NUMDK) + p = RF_NUMDK - 1; uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); } @@ -487,8 +492,10 @@ return attach_unit (uptr, cptr); t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (val < 0) + return SCPE_IERR; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * RF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; diff --git a/PDP11/pdp11_rh.c b/PDP11/pdp11_rh.c index f5413fb6..8e632683 100644 --- a/PDP11/pdp11_rh.c +++ b/PDP11/pdp11_rh.c @@ -295,24 +295,30 @@ int32 ofs, dat, mb, drv; t_stat r; mb = mba_map_pa (pa, &ofs); /* get mb number */ -if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ +if ((mb < 0) || (ofs < 0)) /* valid? */ + return SCPE_NXM; drv = GET_UNIT (massbus[mb].cs2); /* get drive */ mba_upd_cs1 (0, 0, mb); /* update CS1 */ if (ofs & EXT) { /* external? */ - if (!mbregR[mb]) return SCPE_NXM; /* device there? */ + if (!mbregR[mb]) /* device there? */ + return SCPE_NXM; 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? */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; return SCPE_OK; } switch (ofs) { /* case on reg */ case CS1_OF: /* CS1 */ - if (!mbregR[mb]) return SCPE_NXM; /* nx device? */ + if (!mbregR[mb]) /* nx device? */ + return SCPE_NXM; r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */ - if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); *val = massbus[mb].cs1 | dat; break; @@ -355,16 +361,20 @@ t_stat r; t_bool cs1dt; mb = mba_map_pa (pa, &ofs); /* get mb number */ -if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ +if ((mb < 0) || (ofs < 0)) /* valid? */ + return SCPE_NXM; drv = GET_UNIT (massbus[mb].cs2); /* get drive */ if (ofs & EXT) { /* external? */ - if (!mbregW[mb]) return SCPE_NXM; /* device there? */ + if (!mbregW[mb]) /* device there? */ + return SCPE_NXM; 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? */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; mba_upd_cs1 (0, 0, mb); /* update status */ return SCPE_OK; } @@ -373,8 +383,10 @@ 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 (!mbregW[mb]) /* device exist? */ + return SCPE_NXM; + if ((access == WRITEB) && (pa & 1)) + val = val << 8; if (val & CS1_TRE) { /* error clear? */ massbus[mb].cs1 &= ~CS1_TRE; /* clr CS1 */ massbus[mb].cs2 &= ~CS2_ERR; /* clr CS2<15:8> */ @@ -393,8 +405,10 @@ switch (ofs) { /* case on reg */ 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? */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */ massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */ @@ -409,48 +423,55 @@ switch (ofs) { /* case on reg */ break; case WC_OF: /* WC */ - if (access == WRITEB) val = (pa & 1)? + if (access == WRITEB) + val = (pa & 1)? (massbus[mb].wc & 0377) | (val << 8): (massbus[mb].wc & ~0377) | val; massbus[mb].wc = val; break; case BA_OF: /* BA */ - if (access == WRITEB) val = (pa & 1)? + if (access == WRITEB) + val = (pa & 1)? (massbus[mb].ba & 0377) | (val << 8): (massbus[mb].ba & ~0377) | val; massbus[mb].ba = val & ~BA_MBZ; break; case CS2_OF: /* CS2 */ - if ((access == WRITEB) && (pa & 1)) val = val << 8; - if (val & CS2_CLR) mba_reset (&mba_dev[mb]); /* init? */ + if ((access == WRITEB) && (pa & 1)) + val = val << 8; + if (val & CS2_CLR) /* init? */ + mba_reset (&mba_dev[mb]); else { if ((val & ~massbus[mb].cs2) & (CS2_PE | CS2_MXF)) cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) val = (massbus[mb].cs2 & /* merge val */ - ((pa & 1)? 0377: 0177400)) | val; + if (access == WRITEB) /* merge val */ + val = (massbus[mb].cs2 & ((pa & 1)? 0377: 0177400)) | val; massbus[mb].cs2 = (massbus[mb].cs2 & ~CS2_RW) | (val & CS2_RW) | CS2_IR | CS2_OR; } break; case DB_OF: /* DB */ - if (access == WRITEB) val = (pa & 1)? + if (access == WRITEB) + val = (pa & 1)? (massbus[mb].db & 0377) | (val << 8): (massbus[mb].db & ~0377) | val; massbus[mb].db = val; break; case BAE_OF: /* BAE */ - if ((access == WRITEB) && (pa & 1)) break; + if ((access == WRITEB) && (pa & 1)) + break; massbus[mb].bae = val & ~AE_MBZ; massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_UAE) | /* update CS1 */ ((massbus[mb].bae << CS1_V_UAE) & CS1_UAE); break; case CS3_OF: /* CS3 */ - if ((access == WRITEB) && (pa & 1)) break; + if ((access == WRITEB) && (pa & 1)) + break; massbus[mb].cs3 = (massbus[mb].cs3 & ~CS3_RW) | (val & CS3_RW); massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_IE) | /* update CS1 */ (massbus[mb].cs3 & CS1_IE); @@ -479,19 +500,23 @@ int32 i, j, ba, mbc, pbc; uint32 pa; bc = bc & ~1; /* bc even */ -if (mb >= MBA_NUM) return 0; /* valid MBA? */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ -if (bc > mbc) bc = mbc; /* use smaller */ +if (bc > mbc) /* use smaller */ + bc = mbc; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ + if (RH11 && cpu_bme) /* map addr */ + pa = Map_Addr (ba); 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 */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; for (j = 0; j < pbc; j = j + 2) { /* loop by words */ *buf++ = M[pa >> 1]; /* fetch word */ if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ @@ -514,19 +539,23 @@ int32 i, j, ba, mbc, pbc; uint32 pa; bc = bc & ~1; /* bc even */ -if (mb >= MBA_NUM) return 0; /* valid MBA? */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ -if (bc > mbc) bc = mbc; /* use smaller */ +if (bc > mbc) /* use smaller */ + bc = mbc; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ + if (RH11 && cpu_bme) /* map addr */ + pa = Map_Addr (ba); 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 */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; for (j = 0; j < pbc; j = j + 2) { /* loop by words */ M[pa >> 1] = *buf++; /* put word */ if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ @@ -549,10 +578,12 @@ int32 i, j, ba, mbc, pbc; uint32 pa; bc = bc & ~1; /* bc even */ -if (mb >= MBA_NUM) return 0; /* valid MBA? */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ -if (bc > mbc) bc = mbc; /* use smaller */ +if (bc > mbc) /* use smaller */ + bc = mbc; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ else pa = ba; @@ -561,7 +592,8 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ break; } pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; for (j = 0; j < pbc; j = j + 2) { /* loop by words */ massbus[mb].db = *buf++; /* get dev word */ if (M[pa >> 1] != massbus[mb].db) { /* miscompare? */ @@ -594,7 +626,8 @@ return; void mba_upd_ata (uint32 mb, uint32 val) { -if (val) mba_upd_cs1 (CS1_SC, 0, mb); +if (val) + mba_upd_cs1 (CS1_SC, 0, mb); else mba_upd_cs1 (0, CS1_SC, mb); return; } @@ -607,7 +640,8 @@ return; int32 mba_get_bc (uint32 mb) { -if (mb >= MBA_NUM) return 0; +if (mb >= MBA_NUM) + return 0; return ((0200000 - massbus[mb].wc) << 1); } @@ -615,7 +649,8 @@ int32 mba_get_csr (uint32 mb) { DIB *dibp; -if (mb >= MBA_NUM) return 0; +if (mb >= MBA_NUM) + return 0; dibp = (DIB *) mba_dev[mb].ctxt; return dibp->ba; } @@ -624,7 +659,8 @@ void mba_set_int (uint32 mb) { DIB *dibp; -if (mb >= MBA_NUM) return; +if (mb >= MBA_NUM) + return; dibp = (DIB *) mba_dev[mb].ctxt; int_req[dibp->vloc >> 5] |= (1 << (dibp->vloc & 037)); return; @@ -634,7 +670,8 @@ void mba_clr_int (uint32 mb) { DIB *dibp; -if (mb >= MBA_NUM) return; +if (mb >= MBA_NUM) + return; dibp = (DIB *) mba_dev[mb].ctxt; int_req[dibp->vloc >> 5] &= ~(1 << (dibp->vloc & 037)); return; @@ -642,12 +679,15 @@ return; void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb) { -if (mb >= MBA_NUM) return; +if (mb >= MBA_NUM) + return; if ((set & ~massbus[mb].cs1) & CS1_DONE) /* DONE 0 to 1? */ massbus[mb].iff = (massbus[mb].cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ massbus[mb].cs1 = (massbus[mb].cs1 & ~(clr | CS1_MCPE | CS1_MBZ | CS1_DRV)) | set; -if (massbus[mb].cs2 & CS2_ERR) massbus[mb].cs1 = massbus[mb].cs1 | CS1_TRE | CS1_SC; -else if (massbus[mb].cs1 & CS1_TRE) massbus[mb].cs1 = massbus[mb].cs1 | CS1_SC; +if (massbus[mb].cs2 & CS2_ERR) + massbus[mb].cs1 = massbus[mb].cs1 | CS1_TRE | CS1_SC; +else if (massbus[mb].cs1 & CS1_TRE) + massbus[mb].cs1 = massbus[mb].cs1 | CS1_SC; if (massbus[mb].iff || ((massbus[mb].cs1 & CS1_SC) && (massbus[mb].cs1 & CS1_DONE) && @@ -659,7 +699,8 @@ return; void mba_set_cs2 (uint32 flag, uint32 mb) { -if (mb >= MBA_NUM) return; +if (mb >= MBA_NUM) + return; massbus[mb].cs2 = massbus[mb].cs2 | flag; mba_upd_cs1 (0, 0, mb); return; @@ -701,7 +742,8 @@ for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */ *ofs = mba_mapofs[uo]; /* map thru PROM */ return i; /* return ctrl idx */ } - else if (RH11) return -1; /* RH11? done */ + else if (RH11) /* RH11? done */ + return -1; else { /* RH70 */ uo = (pa - (ba + (lnt - 4))) >> 1; /* offset relative */ *ofs = BAE_OF + uo; /* to BAE */ @@ -719,7 +761,8 @@ t_stat mba_reset (DEVICE *dptr) uint32 mb; mb = dptr - mba_dev; -if (mb >= MBA_NUM) return SCPE_NOFNC; +if (mb >= MBA_NUM) + return SCPE_NOFNC; massbus[mb].cs1 = CS1_DONE; massbus[mb].wc = 0; massbus[mb].ba = 0; @@ -729,7 +772,8 @@ massbus[mb].bae= 0; massbus[mb].cs3 = 0; massbus[mb].iff = 0; mba_clr_int (mb); -if (mbabort[mb]) mbabort[mb] (); +if (mbabort[mb]) + mbabort[mb] (); return SCPE_OK; } @@ -737,8 +781,10 @@ return SCPE_OK; void mba_set_enbdis (uint32 mb, t_bool dis) { -if (mb >= MBA_NUM) return; /* valid MBA? */ -if (dis) mba_dev[mb].flags |= DEV_DIS; +if (mb >= MBA_NUM) /* valid MBA? */ + return; +if (dis) + mba_dev[mb].flags |= DEV_DIS; else mba_dev[mb].flags &= ~DEV_DIS; return; } @@ -750,9 +796,11 @@ t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr = find_dev_from_unit (uptr); DIB *dibp; -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; fprintf (st, "Massbus adapter %d", dibp->ba); return SCPE_OK; } @@ -777,9 +825,11 @@ t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp) { uint32 idx; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +if ((dptr == NULL) || (dibp == NULL)) /* validate args */ + return SCPE_IERR; idx = dibp->ba; /* Mbus # */ -if (idx >= MBA_NUM) return SCPE_STOP; +if (idx >= MBA_NUM) + return SCPE_STOP; if ((mbregR[idx] && dibp->rd && /* conflict? */ (mbregR[idx] != dibp->rd)) || (mbregW[idx] && dibp->wr && @@ -787,15 +837,18 @@ if ((mbregR[idx] && dibp->rd && /* conflict? */ (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); + 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 */ +if (dibp->rd) /* set rd dispatch */ + mbregR[idx] = dibp->rd; +if (dibp->wr) /* set wr dispatch */ + mbregW[idx] = dibp->wr; +if (dibp->ack[0]) /* set abort dispatch */ + mbabort[idx] = dibp->ack[0]; return SCPE_OK; } diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c index cb77801e..ccee5026 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -302,8 +302,10 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ rkds = rkds | RKDS_RDY; if (!sim_is_active (uptr)) /* idle? */ rkds = rkds | RKDS_RWS; - if (uptr->flags & UNIT_WPRT) rkds = rkds | RKDS_WLK; - if (GET_SECT (rkda) == (rkds & RKDS_SC)) rkds = rkds | RKDS_ON_SC; + 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; @@ -313,8 +315,10 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ case 2: /* RKCS */ rkcs = rkcs & RKCS_REAL; - if (rker) rkcs = rkcs | RKCS_ERR; /* update err flags */ - if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; + if (rker) /* update err flags */ + rkcs = rkcs | RKCS_ERR; + if (rker & RKER_HARD) + rkcs = rkcs | RKCS_HERR; *data = rkcs; return SCPE_OK; @@ -348,8 +352,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ case 2: /* RKCS */ rkcs = rkcs & RKCS_REAL; - if (access == WRITEB) data = (PA & 1)? - (rkcs & 0377) | (data << 8): (rkcs & ~0377) | data; + 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 */ @@ -364,21 +368,22 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ return SCPE_OK; case 3: /* RKWC */ - if (access == WRITEB) data = (PA & 1)? - (rkwc & 0377) | (data << 8): (rkwc & ~0377) | data; + 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; + 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; + 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; @@ -405,7 +410,8 @@ if (func == RKCS_CTLRESET) { /* control reset? */ return; } rker = rker & ~RKER_SOFT; /* clear soft errors */ -if (rker == 0) rkcs = rkcs & ~RKCS_ERR; /* redo summary */ +if (rker == 0) /* redo summary */ + rkcs = rkcs & ~RKCS_ERR; rkcs = rkcs & ~RKCS_SCP; /* clear sch compl*/ rk_clr_done (); /* clear done */ last_drv = GET_DRIVE (rkda); /* get drive no */ @@ -483,7 +489,8 @@ 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); + if (rkcs & CSR_DONE) + SET_INT (RK); } else { rkintq = 0; /* clear queue */ @@ -533,7 +540,8 @@ if (wc && (err == 0)) { /* seek ok? */ 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 */ + for ( ; i < wc; i++) /* fill buf */ + rkxb[i] = 0; } if (rkcs & RKCS_INH) { /* incr inhibit? */ if (t = Map_WriteW (ma, 2, &rkxb[wc - 1])) { /* store last */ @@ -555,7 +563,8 @@ if (wc && (err == 0)) { /* seek ok? */ rker = rker | RKER_NXM; /* NXM? set flag */ wc = 0; /* no transfer */ } - for (i = 0; i < wc; i++) rkxb[i] = comp; /* all words same */ + for (i = 0; i < wc; i++) /* all words same */ + rkxb[i] = comp; } else { /* normal fetch */ if (t = Map_ReadW (ma, wc << 1, rkxb)) { /* get buf */ @@ -565,7 +574,8 @@ if (wc && (err == 0)) { /* seek ok? */ } 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 */ + for (i = wc; i < awc; i++) /* end of blk */ + rkxb[i] = 0; fxwrite (rkxb, sizeof (int16), awc, uptr->fileref); err = ferror (uptr->fileref); } @@ -577,7 +587,8 @@ if (wc && (err == 0)) { /* seek ok? */ wc = 0; /* no transfer */ break; } - for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ + for ( ; i < wc; i++) /* fill buf */ + rkxb[i] = 0; awc = wc; /* save wc */ for (wc = 0, cma = ma; wc < awc; wc++) { /* loop thru buf */ if (Map_ReadW (cma, 2, &comp)) { /* mem wd */ @@ -586,9 +597,11 @@ if (wc && (err == 0)) { /* seek ok? */ } if (comp != rkxb[wc]) { /* match to disk? */ rker = rker | RKER_WCE; /* no, err */ - if (rkcs & RKCS_SSE) break; + if (rkcs & RKCS_SSE) + break; } - if (!(rkcs & RKCS_INH)) cma = cma + 2; /* next mem addr */ + if (!(rkcs & RKCS_INH)) /* next mem addr */ + cma = cma + 2; } /* end for */ break; /* end wcheck */ @@ -598,7 +611,8 @@ if (wc && (err == 0)) { /* seek ok? */ } /* end else */ rkwc = (rkwc + wc) & 0177777; /* final word count */ -if (!(rkcs & RKCS_INH)) ma = ma + (wc << 1); /* final byte addr */ +if (!(rkcs & RKCS_INH)) /* final byte addr */ + ma = ma + (wc << 1); 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? */ @@ -629,8 +643,10 @@ void rk_set_done (int32 error) rkcs = rkcs | CSR_DONE; /* set done */ if (error != 0) { rker = rker | error; /* update error */ - if (rker) rkcs = rkcs | RKCS_ERR; /* update err flags */ - if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; + if (rker) /* update err flags */ + rkcs = rkcs | RKCS_ERR; + if (rker & RKER_HARD) + rkcs = rkcs | RKCS_HERR; } if (rkcs & CSR_IE) { /* int enable? */ rkintq = rkintq | RK_CTLI; /* set ctrl int */ @@ -658,7 +674,8 @@ 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 */ + if (rkintq) /* queue next */ + SET_INT (RK); rkds = (rkds & ~RKDS_ID) | /* id drive */ (((i == 0)? last_drv: i - 1) << RKDS_V_ID); return rk_dib.vec; /* return vector */ @@ -685,8 +702,10 @@ for (i = 0; i < RK_NUMDR; i++) { 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; +if (rkxb == NULL) + rkxb = (uint16 *) calloc (RK_MAXFR, sizeof (uint16)); +if (rkxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -729,7 +748,8 @@ t_stat rk_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 saved_PC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & RK_M_NUMDR; M[BOOT_CSR >> 1] = (rk_dib.ba & DMASK) + 012; saved_PC = BOOT_ENTRY; diff --git a/PDP11/pdp11_rl.c b/PDP11/pdp11_rl.c index 78b7aeef..46fc1657 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -213,7 +213,6 @@ t_stat rl_boot (int32 unitno, DEVICE *dptr); t_stat rl_attach (UNIT *uptr, char *cptr); t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); /* RL11 data structures @@ -304,9 +303,11 @@ 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; + if (rlcs & RLCS_ALLERR) + rlcs = rlcs | RLCS_ERR; uptr = rl_dev.units + GET_DRIVE (rlcs); - if (sim_is_active (uptr)) rlcs = rlcs & ~RLCS_DRDY; + if (sim_is_active (uptr)) + rlcs = rlcs & ~RLCS_DRDY; else rlcs = rlcs | RLCS_DRDY; /* see if ready */ *data = rlcs; break; @@ -326,7 +327,8 @@ switch ((PA >> 1) & 07) { /* decode PA<2:1> */ break; case 4: /* RLBAE */ - if (UNIBUS) return SCPE_NXM; /* not in RL11 */ + if (UNIBUS) /* not in RL11 */ + return SCPE_NXM; *data = rlbae & RLBAE_IMP; break; } /* end switch */ @@ -343,17 +345,20 @@ 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; + 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; + 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; + 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); + if ((data & CSR_IE) == 0) + CLR_INT (RL); else if ((rlcs & (CSR_DONE + CSR_IE)) == CSR_DONE) SET_INT (RL); return SCPE_OK; @@ -372,11 +377,13 @@ switch ((PA >> 1) & 07) { /* decode PA<2:1> */ newc = curr + offs; /* out */ maxc = (uptr->flags & UNIT_RL02)? RL_NUMCY * 2: RL_NUMCY; - if (newc >= maxc) newc = maxc - 1; + if (newc >= maxc) + newc = maxc - 1; } else { newc = curr - offs; /* in */ - if (newc < 0) newc = 0; + if (newc < 0) + newc = 0; } uptr->TRK = (newc << RLDA_V_CYL) | /* put on track */ ((rlda & RLDA_SK_HD)? RLDA_HD1: RLDA_HD0); @@ -389,26 +396,28 @@ switch ((PA >> 1) & 07) { /* decode PA<2:1> */ break; /* end case RLCS */ case 1: /* RLBA */ - if (access == WRITEB) data = (PA & 1)? - (rlba & 0377) | (data << 8): (rlba & ~0377) | data; + 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; + 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; + 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; + if (UNIBUS) /* not in RL11 */ + return SCPE_NXM; + if (PA & 1) + return SCPE_OK; rlbae = data & RLBAE_IMP; rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); break; @@ -435,11 +444,14 @@ 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; + 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; + 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; @@ -481,13 +493,15 @@ 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? */ +if (wc > maxwc) /* track overrun? */ + wc = maxwc; 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 */ + for ( ; i < wc; i++) /* fill buffer */ + rlxb[i] = 0; if (t = Map_WriteW (ma, wc << 1, rlxb)) { /* store buffer */ rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ wc = wc - t; /* adjust wc */ @@ -501,7 +515,8 @@ if ((func == RLCS_WRITE) && (err == 0)) { /* write? */ } 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 */ + for (i = wc; i < awc; i++) /* end of blk */ + rlxb[i] = 0; fxwrite (rlxb, sizeof (int16), awc, uptr->fileref); err = ferror (uptr->fileref); } @@ -510,7 +525,8 @@ if ((func == RLCS_WRITE) && (err == 0)) { /* 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 */ + for ( ; i < wc; i++) /* fill buffer */ + rlxb[i] = 0; 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 */ @@ -523,7 +539,8 @@ if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */ } /* end wcheck */ rlmp = (rlmp + wc) & 0177777; /* final word count */ -if (rlmp != 0) rlcs = rlcs | RLCS_ERR | RLCS_INCMP; /* completed? */ +if (rlmp != 0) /* completed? */ + rlcs = rlcs | RLCS_ERR | RLCS_INCMP; ma = ma + (wc << 1); /* final byte addr */ rlbae = (ma >> 16) & RLBAE_IMP; /* upper 6b */ rlba = ma & RLBA_IMP; /* lower 16b */ @@ -544,7 +561,8 @@ return SCPE_OK; void rl_set_done (int32 status) { rlcs = rlcs | status | CSR_DONE; /* set done */ -if (rlcs & CSR_IE) SET_INT (RL); +if (rlcs & CSR_IE) + SET_INT (RL); else CLR_INT (RL); return; } @@ -567,8 +585,10 @@ for (i = 0; i < RL_NUMDR; i++) { sim_cancel (uptr); uptr->STAT = 0; } -if (rlxb == NULL) rlxb = (uint16 *) calloc (RL_MAXFR, sizeof (uint16)); -if (rlxb == NULL) return SCPE_MEM; +if (rlxb == NULL) + rlxb = (uint16 *) calloc (RL_MAXFR, sizeof (uint16)); +if (rlxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -581,14 +601,17 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; 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 */ + if (uptr->flags & UNIT_RO) /* if ro, done */ + return SCPE_OK; return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ +if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; if (p > (RL01_SIZE * sizeof (int16))) { uptr->flags = uptr->flags | UNIT_RL02; uptr->capac = RL02_SIZE; @@ -604,7 +627,8 @@ return SCPE_OK; t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; return SCPE_OK; } @@ -674,7 +698,8 @@ int32 i; extern uint16 *M; extern int32 saved_PC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & RLCS_M_DRIVE; M[BOOT_CSR >> 1] = rl_dib.ba & DMASK; saved_PC = BOOT_ENTRY; diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c index 627f07e6..1ae0bbe7 100644 --- a/PDP11/pdp11_rp.c +++ b/PDP11/pdp11_rp.c @@ -1,6 +1,6 @@ /* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 Massbus disk controller - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -372,8 +372,6 @@ t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); int32 rp_abort (void); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - /* RP data structures rp_dev RP device descriptor @@ -495,7 +493,8 @@ if (uptr->flags & UNIT_DIS) { /* nx disk */ } 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 */ +if (drv_tab[dtype].ctrl == RM_CTRL) /* RM? convert */ + ofs = ofs + RM_OF; switch (ofs) { /* decode offset */ @@ -517,8 +516,10 @@ switch (ofs) { /* decode offset */ 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); + 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 */ @@ -590,7 +591,8 @@ int32 dtype; UNIT *uptr; uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) return MBE_NXD; /* nx disk */ +if (uptr->flags & UNIT_DIS) /* nx disk */ + return MBE_NXD; 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); @@ -599,13 +601,15 @@ if ((ofs != RP_AS_OF) && sim_is_active (uptr)) { /* unit busy? */ 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 */ +if (drv_tab[dtype].ctrl == RM_CTRL) /* RM? convert */ + ofs = ofs + RM_OF; 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 */ + if (data & CS1_GO) /* start op */ + return rp_go (drv); break; case RP_DA_OF: case RM_DA_OF: /* RPDA */ @@ -661,9 +665,9 @@ int32 dc, fnc, dtype, t; UNIT *uptr; 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]); +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 */ @@ -721,7 +725,8 @@ switch (fnc) { /* case on function */ } rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ t = abs (dc - uptr->CYL); /* cyl diff */ - if (t == 0) t = 1; /* min time */ + if (t == 0) /* min time */ + t = 1; sim_activate (uptr, rp_swait * t); /* schedule */ uptr->CYL = dc; /* save cylinder */ return SCPE_OK; @@ -781,7 +786,8 @@ 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 */ + if (fnc >= FNC_XFER) /* xfr? set done */ + mba_set_don (rp_dib.ba); rp_update_ds (DS_ATA, drv); /* set attn */ return (rp_stopioe? SCPE_UNATT: SCPE_OK); } @@ -835,7 +841,8 @@ switch (fnc) { /* case on function */ 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 */ + for (i = wc; i < awc; i++) /* fill buf */ + rpxb[i] = 0; if (wc && !err) { /* write buf */ fxwrite (rpxb, sizeof (uint16), awc, uptr->fileref); err = ferror (uptr->fileref); @@ -844,13 +851,15 @@ switch (fnc) { /* case on function */ 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 */ + for (i = awc; i < wc; i++) /* fill buf */ + rpxb[i] = 0; 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; + 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; @@ -873,9 +882,9 @@ switch (fnc) { /* case on function */ 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]); +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]); return SCPE_OK; } @@ -896,8 +905,10 @@ 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; @@ -907,14 +918,18 @@ return; void rp_update_ds (int32 flag, int32 drv) { -if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0; +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; +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; +if (rper1[drv] | rper2[drv] | rper3[drv]) + rpds[drv] = rpds[drv] | DS_ERR; else rpds[drv] = rpds[drv] & ~DS_ERR; rpds[drv] = rpds[drv] | flag; -if (flag & DS_ATA) mba_upd_ata (rp_dib.ba, 1); +if (flag & DS_ATA) + mba_upd_ata (rp_dib.ba, 1); return; } @@ -930,9 +945,11 @@ 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; + 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; @@ -947,8 +964,10 @@ for (i = 0; i < RP_NUMDR; i++) { rmmr2[i] = 0; rmhr[i] = 0; } -if (rpxb == NULL) rpxb = (uint16 *) calloc (RP_MAXFR, sizeof (uint16)); -if (rpxb == NULL) return SCPE_MEM; +if (rpxb == NULL) + rpxb = (uint16 *) calloc (RP_MAXFR, sizeof (uint16)); +if (rpxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -961,7 +980,8 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; 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); @@ -969,11 +989,13 @@ rper1[drv] = 0; 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; + 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 ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; 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); @@ -990,7 +1012,8 @@ t_stat rp_detach (UNIT *uptr) { int32 drv; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; 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 */ @@ -1003,7 +1026,8 @@ t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 dtype = GET_DTYPE (val); -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = drv_tab[dtype].size; return SCPE_OK; } @@ -1056,7 +1080,8 @@ extern int32 saved_PC; extern uint16 *M; UNIT *uptr = rp_dev.units + unitno; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +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) diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index 730d4b8d..3def339a 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -1,6 +1,6 @@ /* pdp11_rq.c: MSCP disk controller simulator - Copyright (c) 2002-2007, Robert M Supnik + Copyright (c) 2002-2008, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a @@ -1003,15 +1003,18 @@ int32 cidx = rq_map_pa ((uint32) PA); MSC *cp = rq_ctxmap[cidx]; DEVICE *dptr = rq_devmap[cidx]; -if (cidx < 0) return SCPE_IERR; +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? */ + if (cp->csta == CST_S3_PPB) /* waiting for poll? */ + rq_step4 (cp); 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); + 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); } @@ -1031,13 +1034,15 @@ int32 cidx = rq_map_pa ((uint32) PA); MSC *cp = rq_ctxmap[cidx]; DEVICE *dptr = rq_devmap[cidx]; -if (cidx < 0) return SCPE_IERR; +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); + if (DEBUG_PRD (dptr)) + fprintf (sim_deb, ">>RQ%c: initialization started\n", + 'A' + cp->cnum); break; case 1: /* SA */ @@ -1085,11 +1090,14 @@ 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; +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 (lnt > SA_COMM_MAX) /* paranoia */ + lnt = SA_COMM_MAX; +for (i = 0; i < (lnt >> 1); i++) /* clr buffer */ + zero[i] = 0; 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 */ @@ -1131,7 +1139,8 @@ if (cp->csta < CST_UP) { /* still init? */ 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 */ + if (dibp->vec) /* if nz, bias */ + dibp->vec = dibp->vec + VEC_Q; 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 */ @@ -1161,18 +1170,20 @@ if (cp->csta < CST_UP) { /* still init? */ break; case CST_S3_PPA: /* need purge test */ - if (cp->saw) rq_fatal (cp, PE_PPF); /* data not zero? */ + if (cp->saw) /* data not zero? */ + rq_fatal (cp, PE_PPF); 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); + 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); + if ((cp->saw & SA_S4H_LF) + && cp->perr) rq_plf (cp, cp->perr); cp->perr = 0; } break; @@ -1183,15 +1194,18 @@ if (cp->csta < CST_UP) { /* still init? */ 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; + 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 (!rq_mscp (cp, pkt, FALSE)) /* process */ + return SCPE_OK; } if ((pkt == 0) && cp->pip) { /* polling? */ - if (!rq_getpkt (cp, &pkt)) return SCPE_OK; /* get host pkt */ + if (!rq_getpkt (cp, &pkt)) /* get host pkt */ + return SCPE_OK; if (pkt) { /* got one? */ if (DEBUG_PRD (dptr)) { - fprintf (sim_deb, ">>RQ%c: cmd=%04X, mod=%04X, unit=%d, ", + 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", @@ -1203,11 +1217,13 @@ if ((pkt == 0) && cp->pip) { /* polling? */ 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 */ + if (!rq_mscp (cp, pkt, TRUE)) /* proc, q non-seq */ + return SCPE_OK; } 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 */ + if (!rq_putpkt (cp, pkt, TRUE)) /* ill cmd */ + return SCPE_OK; } else return rq_fatal (cp, PE_ICI); /* no, term thread */ } /* end if pkt */ @@ -1215,9 +1231,11 @@ if ((pkt == 0) && cp->pip) { /* polling? */ } /* 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 host */ + if (!rq_putpkt (cp, pkt, FALSE)) /* send to host */ + return SCPE_OK; } /* end if resp q */ -if (pkt) sim_activate (uptr, rq_qtime); /* more to do? */ +if (pkt) /* more to do? */ + sim_activate (uptr, rq_qtime); return SCPE_OK; /* done */ } @@ -1236,7 +1254,8 @@ for (i = 0; i < RQ_NUMDR; i++) { /* poll */ 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; + if (!rq_una (cp, i)) + return SCPE_OK; } nuptr->flags = nuptr->flags & ~UNIT_ATP; } @@ -1337,7 +1356,8 @@ if (uptr = rq_getucb (cp, lu)) { /* get unit */ 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; + 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); @@ -1410,11 +1430,13 @@ if (cp->pak[pkt].d[CMD_MOD] & MD_NXU) { /* next unit? */ 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 if (uptr->flags & UNIT_ONL) /* online */ + sts = ST_SUC; 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? */ + if (drv_tab[dtyp].rcts) /* ctrl bad blk? */ + rbpar = 1; 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; @@ -1608,13 +1630,16 @@ if ((uptr->flags & UNIT_ONL) == 0) /* not online? */ 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 (bc & 1) /* odd byte cnt? */ + return (ST_HST | SB_HST_OC); +if (bc & 0xF0000000) /* 'reasonable' bc? */ + return (ST_CMD | I_BCNT); /* 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 (bc != RQ_NUMBY) /* bc must be 512 */ + return (ST_CMD | I_BCNT); } else if ((lbn + ((bc + (RQ_NUMBY - 1)) / RQ_NUMBY)) > maxlbn) return (ST_CMD | I_BCNT); /* spiral to RCT */ @@ -1644,7 +1669,8 @@ 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??? */ +if ((cp == NULL) || (pkt == 0)) /* what??? */ + return STOP_RQ; tbc = (bc > RQ_MAXFR)? RQ_MAXFR: bc; /* trim cnt to max */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ @@ -1669,9 +1695,11 @@ if ((cmd == OP_ERS) || (cmd == OP_WR)) { /* write op? */ 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 */ + for (i = 0; i < wwc; i++) /* clr buf */ + rqxb[i] = 0; err = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) sim_fwrite (rqxb, sizeof (int16), wwc, uptr->fileref); + if (!err) + sim_fwrite (rqxb, sizeof (int16), wwc, uptr->fileref); err = ferror (uptr->fileref); /* end if erase */ } @@ -1679,9 +1707,11 @@ 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; + 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); + if (!err) + sim_fwrite (rqxb, sizeof (int16), wwc, uptr->fileref); err = ferror (uptr->fileref); } if (t) { /* nxm? */ @@ -1697,7 +1727,8 @@ 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 */ + for ( ; i < (tbc >> 1); i++) /* fill */ + rqxb[i] = 0; err = ferror (uptr->fileref); } if ((cmd == OP_RD) && !err) { /* read? */ @@ -1741,7 +1772,8 @@ 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 */ +if (bc) /* more? resched */ + sim_activate (uptr, rq_xtime); else rq_rw_end (cp, uptr, 0, ST_SUC); /* done! */ return SCPE_OK; } @@ -1765,7 +1797,8 @@ 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 (!rq_putpkt (cp, pkt, TRUE)) /* send pkt */ + return ERR; if (uptr->pktq) /* more to do? */ sim_activate (dptr->units + RQ_QUEUE, rq_qtime); /* activate thread */ return OK; @@ -1778,13 +1811,16 @@ 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 */ +if ((cp->cflgs & CF_THS) == 0) /* logging? */ + return OK; +if (!rq_deqf (cp, &pkt)) /* get log pkt */ + return ERR; 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 */ +if (drv_tab[dtyp].flgs & RQDF_SDI) /* SDI? ovhd @ end */ + t = 0; 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 */ @@ -1827,8 +1863,10 @@ 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 */ +if ((cp->cflgs & CF_THS) == 0) /* logging? */ + return OK; +if (!rq_deqf (cp, &pkt)) /* get log pkt */ + return ERR; 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]; @@ -1854,7 +1892,8 @@ t_bool rq_plf (MSC *cp, uint32 err) { int32 pkt; -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ +if (!rq_deqf (cp, &pkt)) /* get log pkt */ + return ERR; 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 */ @@ -1880,8 +1919,10 @@ 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 */ +if (uptr == NULL) /* huh? */ + return OK; +if (!rq_deqf (cp, &pkt)) /* get log pkt */ + return ERR; cp->pak[pkt].d[RSP_REFL] = 0; /* ref = 0 */ cp->pak[pkt].d[RSP_REFH] = 0; cp->pak[pkt].d[RSP_UN] = lu; @@ -1901,7 +1942,8 @@ return rq_putpkt (cp, pkt, TRUE); t_bool rq_deqf (MSC *cp, int32 *pkt) { -if (cp->freq == 0) return rq_fatal (cp, PE_NSR); /* no free pkts?? */ +if (cp->freq == 0) /* no free pkts?? */ + return rq_fatal (cp, PE_NSR); cp->pbsy = cp->pbsy + 1; /* cnt busy pkts */ *pkt = cp->freq; /* head of list */ cp->freq = cp->pak[cp->freq].link; /* next */ @@ -1912,13 +1954,15 @@ int32 rq_deqh (MSC *cp, int32 *lh) { int32 ptr = *lh; /* head of list */ -if (ptr) *lh = cp->pak[ptr].link; /* next */ +if (ptr) /* next */ + *lh = cp->pak[ptr].link; return ptr; } void rq_enqh (MSC *cp, int32 *lh, int32 pkt) { -if (pkt == 0) return; /* any pkt? */ +if (pkt == 0) /* any pkt? */ + return; cp->pak[pkt].link = *lh; /* link is old lh */ *lh = pkt; /* pkt is new lh */ return; @@ -1926,12 +1970,15 @@ return; void rq_enqt (MSC *cp, int32 *lh, int32 pkt) { -if (pkt == 0) return; /* any pkt? */ +if (pkt == 0) /* any pkt? */ + return; cp->pak[pkt].link = 0; /* it will be tail */ -if (*lh == 0) *lh = pkt; /* if empty, enqh */ +if (*lh == 0) /* if empty, enqh */ + *lh = pkt; else { uint32 ptr = *lh; /* chase to end */ - while (cp->pak[ptr].link) ptr = cp->pak[ptr].link; + while (cp->pak[ptr].link) + ptr = cp->pak[ptr].link; cp->pak[ptr].link = pkt; /* enq at tail */ } return; @@ -1945,12 +1992,14 @@ t_bool rq_getpkt (MSC *cp, int32 *pkt) { uint32 addr, desc; -if (!rq_getdesc (cp, &cp->cq, &desc)) return ERR; /* get cmd desc */ +if (!rq_getdesc (cp, &cp->cq, &desc)) /* get cmd desc */ + return ERR; 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 */ +if (!rq_deqf (cp, pkt)) /* get cmd pkt */ + return ERR; 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)) @@ -1968,13 +2017,16 @@ 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 (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 (pkt == 0) /* any packet? */ + return OK; +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)) /* get rsp desc */ + return ERR; if ((desc & UQ_DESC_OWN) == 0) { /* not valid? */ - if (qt) rq_enqt (cp, &cp->rspq, pkt); /* normal? q tail */ + if (qt) /* normal? q tail */ + rq_enqt (cp, &cp->rspq, pkt); else rq_enqh (cp, &cp->rspq, pkt); /* resp q call */ sim_activate (dptr->units + RQ_QUEUE, rq_qtime); /* activate q thrd */ return OK; @@ -1991,7 +2043,8 @@ 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 */ +if (cp->pbsy == 0) /* idle? strt hst tmr */ + cp->hat = cp->htmo; return rq_putdesc (cp, &cp->rq, desc); /* release desc */ } @@ -2025,13 +2078,15 @@ 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 */ + if (ring->lnt <= 4) /* lnt = 1? intr */ + rq_ring_int (cp, ring); 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 (prvd & UQ_DESC_OWN) + rq_ring_int (cp, ring); } } ring->idx = (ring->idx + 4) & (ring->lnt - 1); @@ -2048,7 +2103,8 @@ UNIT *uptr; if ((lu < cp->ubase) || (lu >= (cp->ubase + RQ_NUMDR))) return NULL; uptr = dptr->units + (lu % RQ_NUMDR); -if (uptr->flags & UNIT_DIS) return NULL; +if (uptr->flags & UNIT_DIS) + return NULL; return uptr; } @@ -2107,7 +2163,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 */ + (cp->s1dat & SA_S1H_VEC)) /* ved set? int */ + rq_setint (cp); return; } @@ -2119,7 +2176,8 @@ 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 */ +if (cp->s1dat & SA_S1H_VEC) /* if enb, intr */ + rq_setint (cp); return; } @@ -2193,7 +2251,8 @@ t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc) { uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ -if (drv_tab[dtyp].flgs & RQDF_RO) return SCPE_NOFNC; /* not on read only */ +if (drv_tab[dtyp].flgs & RQDF_RO) /* not on read only */ + return SCPE_NOFNC; return SCPE_OK; } @@ -2203,8 +2262,10 @@ t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc) { uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ -if (drv_tab[dtyp].flgs & RQDF_RO) fprintf (st, "read only"); -else if (uptr->flags & UNIT_WPRT) fprintf (st, "write locked"); +if (drv_tab[dtyp].flgs & RQDF_RO) + fprintf (st, "read only"); +else if (uptr->flags & UNIT_WPRT) + fprintf (st, "write locked"); else fprintf (st, "write enabled"); return SCPE_OK; } @@ -2219,11 +2280,14 @@ t_stat r; if ((val < 0) || ((val != RA8U_DTYPE) && cptr)) return SCPE_ARG; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +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; + 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); @@ -2247,8 +2311,10 @@ MSC *cp = rq_ctxmap[uptr->cnum]; t_stat r; r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; -if (cp->csta == CST_UP) uptr->flags = uptr->flags | UNIT_ATP; +if (r != SCPE_OK) + return r; +if (cp->csta == CST_UP) + uptr->flags = uptr->flags | UNIT_ATP; return SCPE_OK; } @@ -2259,7 +2325,8 @@ t_stat rq_detach (UNIT *uptr) t_stat r; r = detach_unit (uptr); /* detach unit */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP); /* clr onl, atn pend */ uptr->uf = 0; /* clr unit flgs */ return SCPE_OK; @@ -2275,9 +2342,11 @@ 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 (rq_devmap[i] == dptr) + cidx = i; } -if (cidx < 0) return SCPE_IERR; /* not found??? */ +if (cidx < 0) /* not found??? */ + return SCPE_IERR; cp = rq_ctxmap[cidx]; /* get context */ cp->cnum = cidx; /* init index */ @@ -2291,7 +2360,8 @@ 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? */ +if (UNIBUS) /* Unibus? */ + cp->sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; 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 */ @@ -2301,9 +2371,11 @@ 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; + 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; + 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 */ @@ -2317,8 +2389,10 @@ for (i = 0; i < (RQ_NUMDR + 2); i++) { /* init units */ 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; +if (rqxb == NULL) + rqxb = (uint16 *) calloc (RQ_MAXFR >> 1, sizeof (uint16)); +if (rqxb == NULL) + return SCPE_MEM; return auto_config (0, 0); /* run autoconfig */ } @@ -2405,7 +2479,8 @@ extern int32 saved_PC; extern uint16 *M; DIB *dibp = (DIB *) dptr->ctxt; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & 3; M[BOOT_CSR >> 1] = dibp->ba & DMASK; saved_PC = BOOT_ENTRY; @@ -2513,7 +2588,8 @@ if (cp->csta != CST_UP) { return SCPE_OK; } if (val & RQ_SH_RI) { - if (cp->pip) fprintf (st, "Polling in progress, host timer = %d\n", cp->hat); + if (cp->pip) + fprintf (st, "Polling in progress, host timer = %d\n", cp->hat); else fprintf (st, "Host timer = %d\n", cp->hat); fprintf (st, "Command "); rq_show_ring (st, &cp->cq); @@ -2523,8 +2599,10 @@ 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); + 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"); diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c index 6cd580cc..73d60a39 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -275,7 +275,8 @@ switch ((PA >> 1) & 1) { /* decode PA<1> */ } /* end switch func */ return SCPE_OK; } /* end if GO */ - if ((data & RXCS_IE) == 0) CLR_INT (RX); + 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); @@ -331,7 +332,8 @@ switch (rx_state) { /* case on state */ return SCPE_IERR; /* done */ case EMPTY: /* empty buffer */ - if (rx_bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ + if (rx_bptr >= RX_NUMBY) /* done all? */ + rx_done (0, 0); else { rx_dbr = rx_buf[rx_bptr]; /* get next */ rx_bptr = rx_bptr + 1; @@ -342,7 +344,8 @@ switch (rx_state) { /* case on state */ 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 */ + if (rx_bptr < RX_NUMBY) /* more? set xfer */ + rx_csr = rx_csr | RXCS_TR; else rx_done (0, 0); /* else done */ break; @@ -374,7 +377,8 @@ switch (rx_state) { /* case on state */ 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_WRDEL) /* del data? */ + rx_esr = rx_esr | RXES_DD; if (func == RXCS_READ) { /* read? */ for (i = 0; i < RX_NUMBY; i++) rx_buf[i] = fbuf[da + i]; @@ -387,7 +391,8 @@ switch (rx_state) { /* case on state */ 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; + if (da > uptr->hwmark) + uptr->hwmark = da; } rx_done (0, 0); /* done */ break; @@ -411,7 +416,8 @@ switch (rx_state) { /* case on state */ 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; + if ((rx_unit[1].flags & UNIT_ATT) == 0) + rx_ecode = 0020; break; } /* end case state */ @@ -432,8 +438,10 @@ 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? */ +if (new_ecode > 0) /* test for error */ + rx_csr = rx_csr | RXCS_ERR; +if (new_ecode < 0) /* don't update? */ + return; rx_ecode = new_ecode; /* update ecode */ rx_dbr = rx_esr; /* update RXDB */ return; @@ -451,7 +459,8 @@ 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? */ +if (dptr->flags & DEV_DIS) /* disabled? */ + sim_cancel (&rx_unit[0]); 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)); @@ -510,7 +519,8 @@ int32 i; extern int32 saved_PC; extern uint16 *M; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & RX_M_NUMDR; M[BOOT_CSR >> 1] = rx_dib.ba & DMASK; saved_PC = BOOT_ENTRY; diff --git a/PDP11/pdp11_ry.c b/PDP11/pdp11_ry.c index 8b42dd03..23a86595 100644 --- a/PDP11/pdp11_ry.c +++ b/PDP11/pdp11_ry.c @@ -1,6 +1,6 @@ /* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -322,7 +322,8 @@ switch ((PA >> 1) & 1) { /* decode PA<1> */ } /* end switch func */ return SCPE_OK; } /* end if GO */ - if ((data & RYCS_IE) == 0) CLR_INT (RY); + 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); @@ -396,7 +397,8 @@ switch (ry_state) { /* case on state */ break; } if (func == RYCS_FILL) { /* fill? read */ - for (i = 0; i < RY_NUMBY; i++) rx2xb[i] = 0; + 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); @@ -437,7 +439,8 @@ switch (ry_state) { /* case on state */ 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_WRDEL) /* del data? */ + ry_esr = ry_esr | RYES_DD; if (func == RYCS_READ) { /* read? */ for (i = 0; i < bps; i++) rx2xb[i] = fbuf[da + i]; @@ -450,7 +453,8 @@ switch (ry_state) { /* case on state */ for (i = 0; i < bps; i++) /* write */ fbuf[da + i] = rx2xb[i]; da = da + bps; - if (da > uptr->hwmark) uptr->hwmark = da; + if (da > uptr->hwmark) + uptr->hwmark = da; } ry_done (0, 0); /* done */ break; @@ -465,9 +469,11 @@ switch (ry_state) { /* case on state */ break; case SDXFR: /* erase disk */ - for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0; + 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; + if (ry_csr & RYCS_DEN) + uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; ry_done (0, 0); break; @@ -511,7 +517,8 @@ switch (ry_state) { /* case on state */ 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; + if ((ry_unit[1].flags & UNIT_ATT) == 0) + ry_ecode = 0020; break; } /* end case state */ @@ -528,9 +535,11 @@ 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 */ +if (ry_csr & CSR_IE) /* if ie, intr */ + SET_INT (RY); ry_esr = (ry_esr | esr_flags) & ~(RYES_USEL|RYES_DDEN|RYES_DRDY); -if (drv) ry_esr = ry_esr | RYES_USEL; /* updates RYES */ +if (drv) /* updates RYES */ + ry_esr = ry_esr | RYES_USEL; if (ry_unit[drv].flags & UNIT_ATT) { ry_esr = ry_esr | RYES_DRDY; if (ry_unit[drv].flags & UNIT_DEN) @@ -556,7 +565,8 @@ 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? */ +if (dptr->flags & UNIT_DIS) /* disabled? */ + sim_cancel (&ry_unit[0]); 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)); @@ -572,7 +582,8 @@ t_stat ry_attach (UNIT *uptr, char *cptr) uint32 sz; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { - if (sz > RX_SIZE) 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; @@ -583,7 +594,8 @@ return attach_unit (uptr, cptr); t_stat ry_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = val? RY_SIZE: RX_SIZE; return SCPE_OK; } @@ -667,7 +679,8 @@ extern uint16 *M; if ((ry_unit[unitno & RX_M_NUMDR].flags & UNIT_DEN) == 0) return SCPE_NOFNC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & RX_M_NUMDR; M[BOOT_CSR >> 1] = ry_dib.ba & DMASK; saved_PC = BOOT_ENTRY; diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c index eae91e78..ed6ce6e1 100644 --- a/PDP11/pdp11_stddev.c +++ b/PDP11/pdp11_stddev.c @@ -265,8 +265,10 @@ 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); + 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); @@ -286,12 +288,15 @@ t_stat tti_svc (UNIT *uptr) int32 c; sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; +if (c & SCPE_BREAK) /* break? */ + uptr->buf = 0; else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); uptr->pos = uptr->pos + 1; tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); +if (tti_csr & CSR_IE) + SET_INT (TTI); return SCPE_OK; } @@ -329,15 +334,18 @@ 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); + 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; + 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); @@ -362,7 +370,8 @@ if (c >= 0) { } } tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) SET_INT (TTO); +if (tto_csr & CSR_IE) + SET_INT (TTO); uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -397,21 +406,26 @@ return SCPE_OK; 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? */ +if (clk_fnxm) /* not there??? */ + return SCPE_NXM; +if (CPUT (HAS_LTCM)) /* monitor bit? */ + *data = clk_csr & CLKCSR_IMP; 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 (PA & 1) return SCPE_OK; +if (clk_fnxm) /* not there??? */ + return SCPE_NXM; +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 */ + ((clk_csr & CSR_DONE) == 0)) /* clr intr */ + CLR_INT (CLK); return SCPE_OK; } @@ -422,7 +436,8 @@ t_stat clk_svc (UNIT *uptr) int32 t; clk_csr = clk_csr | CSR_DONE; /* set done */ -if ((clk_csr & CSR_IE) || clk_fie) SET_INT (CLK); +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 */ @@ -434,7 +449,8 @@ return SCPE_OK; int32 clk_inta (void) { -if (CPUT (CPUT_24)) clk_csr = clk_csr & ~CSR_DONE; +if (CPUT (CPUT_24)) + clk_csr = clk_csr & ~CSR_DONE; return clk_dib.vec; } @@ -452,7 +468,8 @@ return (t? t - 1: wait); t_stat clk_reset (DEVICE *dptr) { -if (CPUT (HAS_LTCR)) clk_fie = clk_fnxm = 0; /* reg there? */ +if (CPUT (HAS_LTCR)) /* reg there? */ + clk_fie = clk_fnxm = 0; else clk_fie = clk_fnxm = 1; /* no, BEVENT */ clk_tps = clk_default; /* set default tps */ clk_csr = CSR_DONE; /* set done */ @@ -468,8 +485,10 @@ return SCPE_OK; t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; clk_tps = clk_default = val; return SCPE_OK; } diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index c89f36d4..17ac0423 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -23,6 +23,7 @@ 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-08 RMS Moved I/O support routines to I/O library 15-May-08 RMS Added KE11-A, DC11 support Renamed DL11 04-Feb-08 RMS Modified to allow -A, -B use with 8b devices @@ -257,54 +258,6 @@ do { /* block loop */ return SCPE_CSUM; } -/* Factory bad block table creation routine - - This routine writes a DEC standard 044 compliant bad block table on the - last track of the specified unit. The bad block table consists of 10 - repetitions of the same table, formatted as follows: - - words 0-1 pack id number - words 2-3 cylinder/sector/surface specifications - : - words n-n+1 end of table (-1,-1) - - Inputs: - uptr = pointer to unit - sec = number of sectors per surface - wds = number of words per sector - Outputs: - sta = status code -*/ - -t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) -{ -int32 i, da; -uint16 *buf; - -if ((sec < 2) || (wds < 16)) - return SCPE_ARG; -if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; -if (uptr->flags & UNIT_RO) - return SCPE_RO; -if (!get_yn ("Create bad block table on last track? [N]", FALSE)) - return SCPE_OK; -da = (uptr->capac - (sec * wds)) * sizeof (uint16); -if (fseek (uptr->fileref, da, SEEK_SET)) - return SCPE_IOERR; -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 (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 */ @@ -621,7 +574,8 @@ if (sw & SWMASK ('B')) { /* byte? */ fprintf (of, "%o", c1); return 0; } -if (bflag) return SCPE_ARG; /* 16b only */ +if (bflag) /* 16b only */ + return SCPE_ARG; if (sw & SWMASK ('C')) { /* character? */ c1 = val[0] & 0177; @@ -631,7 +585,8 @@ if (sw & SWMASK ('C')) { /* character? */ return -1; } if (sw & SWMASK ('R')) { /* radix 50? */ - if (val[0] > 0174777) return SCPE_ARG; /* max value */ + if (val[0] > 0174777) /* max value */ + return SCPE_ARG; c3 = val[0] % 050; c2 = (val[0] / 050) % 050; c1 = val[0] / (050 * 050); @@ -639,7 +594,8 @@ if (sw & SWMASK ('R')) { /* radix 50? */ r50_to_asc[c2], r50_to_asc[c3]); return -1; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +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 */ @@ -763,7 +719,8 @@ int32 get_reg (char *cptr, const char *strings[], char mchar) { int32 i; -if (*(cptr + 2) != mchar) return -1; +if (*(cptr + 2) != mchar) + return -1; for (i = 0; i < 8; i++) { if (strncmp (cptr, strings[i], 2) == 0) return i; @@ -856,7 +813,8 @@ if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */ pflag = pflag | A_MIN; cptr++; } -else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1; +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) @@ -984,7 +942,8 @@ if (sw & SWMASK ('B')) { /* byte? */ (val[0] & ~0377) | by; return 0; } -if (bflag) return SCPE_ARG; +if (bflag) + return SCPE_ARG; if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ if (cptr[0] == 0) /* must have 1 char */ @@ -1029,7 +988,8 @@ switch (j) { /* case on class */ if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG; if ((pflag & A_REL) == 0) { - if (cflag) disp = (disp - addr) & 0177777; + if (cflag) + disp = (disp - addr) & 0177777; else return SCPE_ARG; } if ((disp & 1) || (disp > 0400) && (disp < 0177402)) @@ -1039,14 +999,16 @@ switch (j) { /* case on class */ case I_V_SOB: /* sob */ cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; + 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; + if (cflag) + disp = (disp - addr) & 0177777; else return SCPE_ARG; } if ((disp & 1) || ((disp > 2) && (disp < 0177604))) diff --git a/PDP11/pdp11_ta.c b/PDP11/pdp11_ta.c index c7db6abf..822a2a30 100644 --- a/PDP11/pdp11_ta.c +++ b/PDP11/pdp11_ta.c @@ -1,6 +1,6 @@ /* pdp11_ta.c: PDP-11 cassette tape simulator - Copyright (c) 2007, Robert M Supnik + Copyright (c) 2007-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -235,11 +235,13 @@ switch ((PA >> 1) & 01) { /* decode PA<1> */ ta_cs = (ta_cs & ~TACS_W) | (data & TACS_W); /* merge new */ if ((data & CSR_GO) && !ta_busy ()) /* go, not busy? */ ta_go (); /* start operation */ - if (ta_cs & TACS_ILBS) ta_cs &= ~TACS_TR; /* ILBS inhibits TR */ + if (ta_cs & TACS_ILBS) /* ILBS inhibits TR */ + ta_cs &= ~TACS_TR; break; case 1: /* TADB */ - if (PA & 1) break; /* ignore odd byte */ + if (PA & 1) /* ignore odd byte */ + break; ta_odb = data; /* return byte */ ta_cs &= ~TACS_TR; /* clear tra req */ break; @@ -296,9 +298,9 @@ if ((fnc != TACS_REW) && !(flg & OP_WRI)) { /* spc/read cmd? */ if (uptr->UST) /* skip file gap */ sim_tape_rdrecr (uptr, ta_xb, &t, TA_MAXFR); else sim_tape_rdrecf (uptr, ta_xb, &t, TA_MAXFR); - if (DEBUG_PRS (ta_dev)) fprintf (sim_deb, - ">>TA skip gap: op=%o, old_sta = %o, pos=%d\n", - fnc, uptr->UST, uptr->pos); + if (DEBUG_PRS (ta_dev)) + fprintf (sim_deb, ">>TA skip gap: op=%o, old_sta = %o, pos=%d\n", + fnc, uptr->UST, uptr->pos); } } else uptr->UST = 0; @@ -332,7 +334,8 @@ switch (uptr->FNC) { /* case on function */ case TACS_READ: /* read start */ st = sim_tape_rdrecf (uptr, ta_xb, &ta_blnt, TA_MAXFR); /* get rec */ - if (st == MTSE_RECE) ta_cs |= TACS_ERR|TACS_CRC; /* rec in err? */ + if (st == MTSE_RECE) /* rec in err? */ + ta_cs |= TACS_ERR|TACS_CRC; else if (st != MTSE_OK) { /* other error? */ r = ta_map_err (uptr, st); /* map error */ break; @@ -365,12 +368,14 @@ switch (uptr->FNC) { /* case on function */ case TACS_READ|TACS_3RD: /* second read CRC */ if (ta_bptr != ta_blnt) { /* partial read? */ crc = ta_crc (ta_xb, ta_bptr + 2); /* actual CRC */ - if (crc != 0) ta_cs |= TACS_ERR|TACS_CRC; /* must be zero */ + if (crc != 0) /* must be zero */ + ta_cs |= TACS_ERR|TACS_CRC; } break; /* read done */ case TACS_WRITE: /* write start */ - for (i = 0; i < TA_MAXFR; i++) ta_xb[i] = 0; /* clear buffer */ + for (i = 0; i < TA_MAXFR; i++) /* clear buffer */ + ta_xb[i] = 0; ta_set_tr (); /* set tra req */ uptr->FNC |= TACS_2ND; /* next state */ sim_activate (uptr, ta_ctime); /* sched next char */ @@ -438,9 +443,9 @@ switch (uptr->FNC) { /* case on function */ ta_cs |= TACS_RDY; /* set ready */ ta_updsta (uptr); /* update status */ -if (DEBUG_PRS (ta_dev)) fprintf (sim_deb, - ">>TA done: op=%o, status = %o, pos=%d\n", - uptr->FNC, ta_cs, uptr->pos); +if (DEBUG_PRS (ta_dev)) + fprintf (sim_deb, ">>TA done: op=%o, status = %o, pos=%d\n", + uptr->FNC, ta_cs, uptr->pos); return r; } @@ -452,8 +457,10 @@ if (uptr == NULL) { /* unit specified? */ if ((uptr = ta_busy ()) == NULL) /* use busy */ uptr = ta_dev.units + GET_UNIT (ta_cs); /* use sel unit */ } -else if (ta_cs & TACS_EOF) uptr->UST |= UST_GAP; /* save EOF */ -if (uptr->flags & UNIT_ATT) ta_cs &= ~TACS_EMP; /* attached? */ +else if (ta_cs & TACS_EOF) /* save EOF */ + uptr->UST |= UST_GAP; +if (uptr->flags & UNIT_ATT) /* attached? */ + ta_cs &= ~TACS_EMP; else ta_cs |= TACS_EMP|TACS_RDY; /* no, empty, ready */ if ((ta_cs & TACS_IE) && /* int enabled? */ (ta_cs & (TACS_TR|TACS_RDY))) /* req or ready? */ @@ -466,9 +473,11 @@ return ta_cs; void ta_set_tr (void) { -if (ta_cs & TACS_TR) ta_cs |= (TACS_ERR|TACS_TIM); /* flag still set? */ +if (ta_cs & TACS_TR) /* flag still set? */ + ta_cs |= (TACS_ERR|TACS_TIM); else ta_cs |= TACS_TR; /* set xfr req */ -if (ta_cs & TACS_IE) SET_INT (TA); /* if ie, int req */ +if (ta_cs & TACS_IE) /* if ie, int req */ + SET_INT (TA); return; } @@ -481,7 +490,8 @@ UNIT *uptr; for (u = 0; u < TA_NUMDR; u++) { /* loop thru units */ uptr = ta_dev.units + u; - if (sim_is_active (uptr)) return uptr; + if (sim_is_active (uptr)) + return uptr; } return NULL; } @@ -496,7 +506,8 @@ crc = 0; for (i = 0; i < cnt; i++) { crc = crc ^ (((uint32) buf[i]) << 8); for (j = 0; j < 8; j++) { - if (crc & 1) crc = (crc >> 1) ^ 0xA001; + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; else crc = crc >> 1; } } @@ -521,7 +532,8 @@ switch (st) { case MTSE_IOERR: /* IO error */ ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */ - if (ta_stopioe) return SCPE_IOERR; + if (ta_stopioe) + return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ @@ -564,8 +576,10 @@ for (u = 0; u < TA_NUMDR; u++) { /* loop thru units */ sim_cancel (uptr); /* cancel activity */ sim_tape_reset (uptr); /* reset tape */ } -if (ta_xb == NULL) ta_xb = (uint8 *) calloc (TA_MAXFR + 2, sizeof (uint8)); -if (ta_xb == NULL) return SCPE_MEM; +if (ta_xb == NULL) + ta_xb = (uint8 *) calloc (TA_MAXFR + 2, sizeof (uint8)); +if (ta_xb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -576,7 +590,8 @@ t_stat ta_attach (UNIT *uptr, char *cptr) t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; ta_updsta (NULL); uptr->UST = 0; return r; @@ -588,7 +603,8 @@ t_stat ta_detach (UNIT* uptr) { t_stat r; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check attached */ +if (!(uptr->flags & UNIT_ATT)) /* check attached */ + return SCPE_OK; r = sim_tape_detach (uptr); ta_updsta (NULL); uptr->UST = 0; diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c index d1ea2d65..1b67b4ce 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -265,7 +265,8 @@ #define LOG_BL 0x4 #define DT_SETDONE tccm = tccm | CSR_DONE; \ - if (tccm & CSR_IE) SET_INT (DTA) + if (tccm & CSR_IE) \ + SET_INT (DTA) #define DT_CLRDONE tccm = tccm & ~CSR_DONE; \ CLR_INT (DTA) #define ABS(x) (((x) < 0)? (-(x)): (x)) @@ -412,13 +413,15 @@ 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 */ + if (mot >= DTS_ATSF) /* set/clr speed */ + tcst = tcst | STA_UPS; else tcst = tcst & ~STA_UPS; *data = tcst; break; case 001: /* TCCM */ - if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; /* set/clr error */ + if (tcst & STA_ALLERR) /* set/clr error */ + tccm = tccm | CSR_ERR; else tccm = tccm & ~CSR_ERR; *data = tccm; break; @@ -452,15 +455,17 @@ j = (PA >> 1) & 017; /* get reg offset */ switch (j) { case 000: /* TCST */ - if ((access == WRITEB) && (PA & 1)) break; + 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); + 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); @@ -468,7 +473,8 @@ switch (j) { 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); + 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? */ @@ -484,11 +490,13 @@ switch (j) { ((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); + 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; + if (tcst & STA_ALLERR) + tccm = tccm | CSR_ERR; } break; @@ -570,7 +578,8 @@ if (new_fnc == FNC_SSEL) { /* stop unit? */ } if (prev_mot == DTS_STOP) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -586,7 +595,8 @@ if (prev_dir ^ new_dir) { /* dir chg? */ } if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* cancel cur */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -621,7 +631,8 @@ int32 fnc, dir, blk, unum, relpos, newpos; uint32 oldpos; oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ +if (dt_setpos (uptr)) /* update pos */ + return; uptr->STATE = newsta; /* update state */ fnc = DTS_GETFNC (uptr->STATE); /* set variables */ dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; @@ -639,23 +650,27 @@ sim_cancel (uptr); /* cancel cur op */ switch (fnc) { /* case function */ case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ + if (dir) /* rev? < start */ + newpos = -1000; 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")); + 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; + if (dir) + newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); break; } @@ -665,10 +680,11 @@ switch (fnc) { /* case function */ 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 (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", @@ -679,7 +695,8 @@ switch (fnc) { /* case function */ 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; + if (dir) + newpos = DTU_FWDEZ (uptr) - DT_WSIZE; else newpos = DT_EZLIN + (DT_WSIZE - 1); } else { @@ -689,7 +706,8 @@ switch (fnc) { /* case function */ dt_seterr (uptr, STA_BLKM); return; } - if (dir) newpos = DT_BLK2LN (blk + 1, uptr) - DT_CSMLN - DT_WSIZE; + 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? */ @@ -735,7 +753,8 @@ 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 */ +if (ut == 0) /* no time gone? exit */ + return FALSE; uptr->LASTT = new_time; /* update last time */ switch (mot & ~DTS_DIR) { /* case on motion */ @@ -760,7 +779,8 @@ switch (mot & ~DTS_DIR) { /* case on motion */ break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ +if (mot & DTS_DIR) /* update pos */ + uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { @@ -875,8 +895,10 @@ switch (fnc) { /* at speed, check fnc * } 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 (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); @@ -899,7 +921,8 @@ switch (fnc) { /* at speed, check fnc * case FNC_WRIT: /* write */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - if (dt_substate) tcdt = 0; /* wc ovf? fill */ + if (dt_substate) /* wc ovf? fill */ + tcdt = 0; else { ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ if (Map_ReadW (ma, 2, &wbuf)) { /* fetch word */ @@ -909,12 +932,15 @@ switch (fnc) { /* at speed, check fnc * tcdt = wbuf; /* get word */ tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ tcba = (tcba + 2) & DMASK; - if (tcba <= 1) tccm = CSR_INCMEX (tccm); + 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 (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? */ @@ -939,7 +965,8 @@ switch (fnc) { /* at speed, check fnc * dat = fbuf[ba]; /* get tape word */ } else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ + if (dir) /* rev? comp obv */ + dat = dt_comobv (dat); tcdt = dat & DMASK; /* low 16b */ tcst = (tcst & ~STA_M_XD) | ((dat >> 16) & STA_M_XD); sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -958,10 +985,12 @@ switch (fnc) { /* at speed, check fnc * (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 */ + if (dir) /* rev? comp obv */ + dat = dt_comobv (dat); ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ fbuf[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + if (ba >= uptr->hwmark) + uptr->hwmark = ba + 1; } /* else /* ignore hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -990,7 +1019,8 @@ if (!(tccm & CSR_DONE)) { /* not done? */ } if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ sim_cancel (uptr); /* cancel activity */ - if (dt_setpos (uptr)) return; /* update position */ + if (dt_setpos (uptr)) /* update position */ + return; sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); /* state = decel */ } @@ -1006,7 +1036,8 @@ 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 */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -1020,7 +1051,8 @@ void dt_schedez (UNIT *uptr, int32 dir) { int32 newpos; -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ +if (dir) /* rev? rev ez */ + newpos = DT_EZLIN - DT_WSIZE; else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); return; @@ -1059,8 +1091,10 @@ 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 == DT_BLKWD) /* fwd blknum */ + return blk; +if (wrd == DT_CSMWD) /* rev csum */ + return 077; 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 */ @@ -1080,7 +1114,8 @@ for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ 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 */ + if (dt_setpos (uptr)) /* update pos */ + continue; sim_cancel (uptr); sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); @@ -1152,7 +1187,8 @@ int32 i; extern int32 saved_PC; dt_unit[unitno].pos = DT_EZLIN; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & DT_M_NUMDR; M[BOOT_CSR >> 1] = (dt_dib.ba & DMASK) + 02; saved_PC = BOOT_ENTRY; @@ -1177,7 +1213,8 @@ int32 u = uptr - dt_dev.units; t_stat r; r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* fail? */ +if (r != SCPE_OK) /* fail? */ + return r; if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; /* default 16b */ if (sim_switches & SWMASK ('T')) /* att 12b? */ @@ -1187,7 +1224,7 @@ if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ else if (!(sim_switches & SWMASK ('A')) && /* autosize? */ ((sz = sim_fsize (uptr->fileref)) > D16_FILSIZ)) { if (sz <= D8_FILSIZ) - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; + uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; else uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); } } @@ -1199,15 +1236,19 @@ if (uptr->filebuf == NULL) { /* can't alloc? */ } 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"); +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; + 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); @@ -1221,8 +1262,10 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */ 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; + if (k == 0) + break; + for ( ; k < D18_BSIZE; k++) + pdp11b[k] = 0; for (k = 0; k < D18_BSIZE; k++) fbuf[ba++] = pdp11b[k]; } @@ -1252,13 +1295,15 @@ uint16 pdp11b[D18_BSIZE]; uint32 ba, k, *fbuf; int32 u = uptr - dt_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +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); + if (tccm & CSR_IE) + SET_INT (DTA); } uptr->STATE = uptr->pos = 0; } @@ -1276,7 +1321,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ ba = ba + 2; } /* end loop blk */ fxwrite (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; + if (ferror (uptr->fileref)) + break; } /* end loop file */ } /* end if 12b */ else if (uptr->flags & UNIT_11FMT) { /* 16b? */ @@ -1284,7 +1330,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ 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; + if (ferror (uptr->fileref)) + break; } /* end loop file */ } /* end if 16b */ else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */ diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c index 0be12fe1..e6af932c 100644 --- a/PDP11/pdp11_tm.c +++ b/PDP11/pdp11_tm.c @@ -1,6 +1,6 @@ /* pdp11_tm.c: PDP-11 magnetic tape simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -311,7 +311,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ 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; + if ((tm_cmd & MTC_DONE) == 0) + tm_sta = tm_sta | STA_ILL; else { if (access == WRITEB) data = (PA & 1)? (tm_cmd & 0377) | (data << 8): @@ -326,25 +327,27 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ 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? */ + if (data & MTC_GO) /* new function? */ + tm_go (uptr); } tm_updcsta (uptr); /* update status */ break; case 2: /* MTBRC */ - if (access == WRITEB) data = (PA & 1)? - (tm_bc & 0377) | (data << 8): (tm_bc & ~0377) | data; + 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; + 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; + if ((access == WRITEB) && (PA & 1)) + return SCPE_OK; tm_db = data & 0377; break; } /* end switch */ @@ -363,10 +366,10 @@ 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; - } + 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? */ @@ -403,8 +406,7 @@ 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); + 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 */ @@ -421,19 +423,23 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ 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, tm_bc, uptr->pos); +if (DEBUG_PRS (tm_dev)) + fprintf (sim_deb, ">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", + f, xma, tm_bc, 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? */ + st = sim_tape_rdrecf (uptr, tmxb, &tbc, MT_MAXFR); /* read rec */ + if (st == MTSE_RECE) /* rec in error? */ + tm_sta = tm_sta | STA_PAR; 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 (tbc > cbc) /* wrong size? */ + tm_sta = tm_sta | STA_RLE; + if (tbc < cbc) /* use smaller */ + cbc = tbc; 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 */ @@ -447,7 +453,8 @@ switch (f) { /* case on function */ 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 (cbc == 0) /* no xfr? done */ + break; } if (st = sim_tape_wrrecf (uptr, tmxb, cbc)) /* write rec, err? */ r = tm_map_err (uptr, st); /* map error */ @@ -487,9 +494,9 @@ tm_cmd = (tm_cmd & ~MTC_EMA) | ((xma >> (16 - MTC_V_EMA)) & MTC_EMA); tm_ca = xma & 0177777; /* update mem addr */ tm_set_done (); /* set done */ tm_updcsta (uptr); /* update status */ -if (DEBUG_PRS (tm_dev)) fprintf (sim_deb, - ">>TM: sta=%o, ma=%o, bc=%o, pos=%d\n", - tm_sta, tm_ca, tm_bc, uptr->pos); +if (DEBUG_PRS (tm_dev)) + fprintf (sim_deb, ">>TM: sta=%o, ma=%o, bc=%o, pos=%d\n", + tm_sta, tm_ca, tm_bc, uptr->pos); return r; } @@ -498,12 +505,16 @@ return r; int32 tm_updcsta (UNIT *uptr) { tm_sta = (tm_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); -if (sim_tape_eot (uptr)) tm_sta = tm_sta | STA_EOT; -if (sim_is_active (uptr)) tm_sta = tm_sta & ~STA_TUR; +if (sim_tape_eot (uptr)) + tm_sta = tm_sta | STA_EOT; +if (sim_is_active (uptr)) + tm_sta = tm_sta & ~STA_TUR; else tm_sta = tm_sta | STA_TUR; -if (tm_sta & STA_EFLGS) tm_cmd = tm_cmd | MTC_ERR; +if (tm_sta & STA_EFLGS) + tm_cmd = tm_cmd | MTC_ERR; else tm_cmd = tm_cmd & ~MTC_ERR; -if ((tm_cmd & MTC_IE) == 0) CLR_INT (TM); +if ((tm_cmd & MTC_IE) == 0) + CLR_INT (TM); return tm_sta; } @@ -512,7 +523,8 @@ return tm_sta; void tm_set_done (void) { tm_cmd = tm_cmd | MTC_DONE; -if (tm_cmd & MTC_IE) SET_INT (TM); +if (tm_cmd & MTC_IE) + SET_INT (TM); return; } @@ -534,7 +546,8 @@ switch (st) { case MTSE_IOERR: /* IO error */ tm_sta = tm_sta | STA_PAR; /* parity error */ - if (tm_stopioe) return SCPE_IOERR; + if (tm_stopioe) + return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ @@ -575,13 +588,15 @@ 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); + 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; +if (tmxb == NULL) + tmxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); +if (tmxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -593,9 +608,11 @@ t_stat r; int32 u = uptr - tm_dev.units; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->USTAT = STA_ONL | STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); +if (u == GET_UNIT (tm_cmd)) + tm_updcsta (uptr); return r; } @@ -605,9 +622,12 @@ t_stat tm_detach (UNIT* uptr) { int32 u = uptr - tm_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (!sim_is_active (uptr)) uptr->USTAT = 0; -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); +if (!(uptr->flags & UNIT_ATT)) + return SCPE_OK; +if (!sim_is_active (uptr)) + uptr->USTAT = 0; +if (u == GET_UNIT (tm_cmd)) + tm_updcsta (uptr); return sim_tape_detach (uptr); } @@ -621,7 +641,8 @@ if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) uptr->USTAT = uptr->USTAT | STA_WLK; else uptr->USTAT = uptr->USTAT & ~STA_WLK; -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); +if (u == GET_UNIT (tm_cmd)) + tm_updcsta (uptr); return SCPE_OK; } diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c index b819efdd..7479f513 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-2007, Robert M Supnik + Copyright (c) 2002-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -477,7 +477,8 @@ 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? */ + if (tq_csta == CST_S3_PPB) /* waiting for poll? */ + tq_step4 (); else if (tq_csta == CST_UP) { /* if up */ tq_pip = 1; /* poll host */ sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); @@ -498,8 +499,9 @@ 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 ()); + if (DEBUG_PRS (tq_dev)) + fprintf (sim_deb, ">>TQ: initialization started, time=%.0f\n", + sim_gtime ()); break; case 1: /* SA */ @@ -529,11 +531,14 @@ 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; +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 (lnt > SA_COMM_MAX) /* paranoia */ + lnt = SA_COMM_MAX; +for (i = 0; i < (lnt >> 1); i++) /* clr buffer */ + zero[i] = 0; 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 */ @@ -572,7 +577,8 @@ if (tq_csta < CST_UP) { /* still init? */ 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 */ + if (tq_dib.vec) /* if nz, bias */ + tq_dib.vec = tq_dib.vec + VEC_Q; 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 */ @@ -602,18 +608,20 @@ if (tq_csta < CST_UP) { /* still init? */ break; case CST_S3_PPA: /* need purge test */ - if (tq_saw) tq_fatal (PE_PPF); /* data not zero? */ + if (tq_saw) /* data not zero? */ + tq_fatal (PE_PPF); 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"); + 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); + if ((tq_saw & SA_S4H_LF) && tq_perr) + tq_plf (tq_perr); tq_perr = 0; } break; @@ -623,12 +631,15 @@ if (tq_csta < CST_UP) { /* still init? */ 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; + 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 (!tq_mscp (pkt, FALSE)) /* process */ + return SCPE_OK; } if ((pkt == 0) && tq_pip) { /* polling? */ - if (!tq_getpkt (&pkt)) return SCPE_OK; /* get host pkt */ + if (!tq_getpkt (&pkt)) /* get host pkt */ + return SCPE_OK; if (pkt) { /* got one? */ if (DEBUG_PRS (tq_dev)) { UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); @@ -637,7 +648,8 @@ if ((pkt == 0) && tq_pip) { /* polling? */ 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); + if (up) + fprintf (sim_deb, ", pos=%d, obj=%d\n", up->pos, up->objp); else fprintf (sim_deb, "\n"); fflush (sim_deb); } @@ -645,11 +657,13 @@ if ((pkt == 0) && tq_pip) { /* polling? */ 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 */ + if (!tq_mscp (pkt, TRUE)) /* proc, q non-seq */ + return SCPE_OK; } 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 */ + if (!tq_putpkt (pkt, TRUE)) /* ill cmd */ + return SCPE_OK; } else return tq_fatal (PE_ICI); /* no, term thread */ } /* end if pkt */ @@ -657,9 +671,11 @@ if ((pkt == 0) && tq_pip) { /* polling? */ } /* 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 host */ + if (!tq_putpkt (pkt, FALSE)) /* send to host */ + return SCPE_OK; } /* end if resp q */ -if (pkt) sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* more to do? */ +if (pkt) /* more to do? */ + sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); return SCPE_OK; /* done */ } @@ -676,7 +692,8 @@ for (i = 0; i < TQ_NUMDR; i++) { /* poll */ 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; + if (!tq_una (nuptr)) + return SCPE_OK; } nuptr->flags = nuptr->flags & ~UNIT_ATP; } @@ -811,7 +828,8 @@ if (uptr = tq_getucb (lu)) { /* get unit */ 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; + 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); @@ -829,14 +847,16 @@ uint32 sts; UNIT *uptr; if (uptr = tq_getucb (lu)) { /* unit exist? */ - if (uptr->flags & UNIT_SXC) sts = ST_SXC; /* ser exc pending? */ + if (uptr->flags & UNIT_SXC) /* ser exc pending? */ + sts = ST_SXC; 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? */ + if (mdf & MD_UNL) /* unload? */ + tq_detach (uptr); } else sts = ST_OFL | SB_OFL_NV; /* no, offline */ } @@ -884,7 +904,8 @@ if (tq_pkt[pkt].d[CMD_MOD] & MD_NXU) { /* next unit? */ 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 if (uptr->flags & UNIT_ONL) /* online */ + sts = ST_SUC; 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 */ @@ -1094,7 +1115,8 @@ 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_SXC) /* ser exc pend? */ + return ST_SXC; 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? */ @@ -1126,7 +1148,8 @@ 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 (pkt == 0) /* what??? */ + return SCPE_IERR; 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; @@ -1149,7 +1172,8 @@ 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 */ + if (mdf & MD_REV) /* read record */ + sts = tq_rdbufr (uptr, &tbc); else sts = tq_rdbuff (uptr, &tbc); if (sts == ST_DRV) { /* read error? */ PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ @@ -1249,13 +1273,15 @@ switch (cmd) { /* case on command */ else sts = tq_spacef (uptr, nrec, &skrec, FALSE); } else { /* skip tmk, rec */ - if (mdf & MD_REV) sts = tq_skipfr (uptr, ntmk, &sktmk); + 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; + if (sts == ST_TMK) + sktmk = sktmk + 1; } } PUTP32 (pkt, POS_RCL, skrec); /* #rec skipped */ @@ -1290,10 +1316,14 @@ int32 pkt = uptr->cpkt; /* packet */ uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ uint32 lnt = RW_LNT_T; /* assume rw */ -if (cmd == OP_ERG) lnt = ERG_LNT; /* set pkt lnt */ -else if (cmd == OP_ERS) lnt = ERS_LNT; -else if (cmd == OP_WTM) lnt = WTM_LNT; -else if (cmd == OP_POS) lnt = POS_LNT; +if (cmd == OP_ERG) /* set pkt lnt */ + lnt = ERG_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? */ @@ -1301,7 +1331,8 @@ if (lnt > ERG_LNT) { /* xfer cmd? */ 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 (!tq_putpkt (pkt, TRUE)) /* send pkt */ + return ERR; if (uptr->pktq) /* more to do? */ sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* activate thread */ return OK; @@ -1373,7 +1404,8 @@ while (*skipped < cnt) { /* loop */ return ST_LED; } uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */ - if (qrec) return ST_TMK; /* rec spc? stop */ + if (qrec) /* rec spc? stop */ + return ST_TMK; } else uptr->flags = uptr->flags & ~UNIT_TMK; /* clr TM seen */ *skipped = *skipped + 1; /* # obj skipped */ @@ -1388,8 +1420,10 @@ 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; + if (st == ST_TMK) /* count files */ + *skipped = *skipped + 1; + else if (st != ST_SUC) + return st; } return ST_SUC; } @@ -1405,7 +1439,8 @@ while (*skipped < cnt) { /* loop */ 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? */ + if ((st == MTSE_TMK) && qrec) /* tape mark, stop? */ + return ST_TMK; *skipped = *skipped + 1; /* # obj skipped */ } return ST_SUC; @@ -1418,8 +1453,10 @@ 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? */ + if (st == ST_TMK) /* tape mark? */ + *skipped = *skipped + 1; + else if (st != 0) /* error? */ + return st; } return ST_SUC; } @@ -1436,7 +1473,8 @@ if (st == MTSE_TMK) { /* tape mark? */ uptr->objp = uptr->objp + 1; /* update obj cnt */ return ST_TMK; } -if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */ +if (st != MTSE_OK) /* other error? */ + return tq_map_status (uptr, st); uptr->flags = uptr->flags & ~UNIT_TMK; /* clr tape mark */ uptr->objp = uptr->objp + 1; /* upd obj cnt */ return ST_SUC; @@ -1452,7 +1490,8 @@ if (st == MTSE_TMK) { /* tape mark? */ uptr->objp = uptr->objp - 1; /* update obj cnt */ return ST_TMK; } -if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */ +if (st != MTSE_OK) /* other error? */ + return tq_map_status (uptr, st); uptr->objp = uptr->objp - 1; /* upd obj cnt */ return ST_SUC; } @@ -1464,8 +1503,10 @@ 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 */ +if ((tq_cflgs & CF_THS) == 0) /* logging? */ + return OK; +if (!tq_deqf (&pkt)) /* get log pkt */ + return ERR; tpkt = uptr->cpkt; /* rw pkt */ lu = tq_pkt[tpkt].d[CMD_UN]; /* unit # */ @@ -1498,8 +1539,10 @@ 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 */ +if ((tq_cflgs & CF_THS) == 0) /* logging? */ + return OK; +if (!tq_deqf (&pkt)) /* get log pkt */ + return ERR; 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 */ @@ -1523,7 +1566,8 @@ t_bool tq_plf (uint32 err) { int32 pkt; -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ +if (!tq_deqf (&pkt)) /* get log pkt */ + return ERR; 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 */ @@ -1545,7 +1589,8 @@ int32 tq_una (UNIT *uptr) int32 pkt; uint32 lu; -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ +if (!tq_deqf (&pkt)) /* get log pkt */ + return ERR; 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; @@ -1565,7 +1610,8 @@ return tq_putpkt (pkt, TRUE); t_bool tq_deqf (int32 *pkt) { -if (tq_freq == 0) return tq_fatal (PE_NSR); /* no free pkts?? */ +if (tq_freq == 0) /* no free pkts?? */ + return tq_fatal (PE_NSR); tq_pbsy = tq_pbsy + 1; /* cnt busy pkts */ *pkt = tq_freq; /* head of list */ tq_freq = tq_pkt[tq_freq].link; /* next */ @@ -1576,13 +1622,15 @@ int32 tq_deqh (int32 *lh) { int32 ptr = *lh; /* head of list */ -if (ptr) *lh = tq_pkt[ptr].link; /* next */ +if (ptr) /* next */ + *lh = tq_pkt[ptr].link; return ptr; } void tq_enqh (int32 *lh, int32 pkt) { -if (pkt == 0) return; /* any pkt? */ +if (pkt == 0) /* any pkt? */ + return; tq_pkt[pkt].link = *lh; /* link is old lh */ *lh = pkt; /* pkt is new lh */ return; @@ -1590,12 +1638,15 @@ return; void tq_enqt (int32 *lh, int32 pkt) { -if (pkt == 0) return; /* any pkt? */ +if (pkt == 0) /* any pkt? */ + return; tq_pkt[pkt].link = 0; /* it will be tail */ -if (*lh == 0) *lh = pkt; /* if empty, enqh */ +if (*lh == 0) /* if empty, enqh */ + *lh = pkt; else { uint32 ptr = *lh; /* chase to end */ - while (tq_pkt[ptr].link) ptr = tq_pkt[ptr].link; + while (tq_pkt[ptr].link) + ptr = tq_pkt[ptr].link; tq_pkt[ptr].link = pkt; /* enq at tail */ } return; @@ -1609,12 +1660,14 @@ t_bool tq_getpkt (int32 *pkt) { uint32 addr, desc; -if (!tq_getdesc (&tq_cq, &desc)) return ERR; /* get cmd desc */ +if (!tq_getdesc (&tq_cq, &desc)) /* get cmd desc */ + return ERR; if ((desc & UQ_DESC_OWN) == 0) { /* none */ *pkt = 0; /* pkt = 0 */ return OK; /* no error */ } -if (!tq_deqf (pkt)) return ERR; /* get cmd pkt */ +if (!tq_deqf (pkt)) /* get cmd pkt */ + return ERR; 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)) @@ -1631,18 +1684,22 @@ t_bool tq_putpkt (int32 pkt, t_bool qt) { uint32 addr, desc, lnt, cr; -if (pkt == 0) return OK; /* any packet? */ +if (pkt == 0) /* any packet? */ + return OK; 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); + 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 (!tq_getdesc (&tq_rq, &desc)) /* get rsp desc */ + return ERR; if ((desc & UQ_DESC_OWN) == 0) { /* not valid? */ - if (qt) tq_enqt (&tq_rspq, pkt); /* normal? q tail */ + if (qt) /* normal? q tail */ + tq_enqt (&tq_rspq, pkt); else tq_enqh (&tq_rspq, pkt); /* resp q call */ sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* activate q thrd */ return OK; @@ -1659,7 +1716,8 @@ 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 */ +if (tq_pbsy == 0) /* idle? strt hst tmr */ + tq_hat = tq_htmo; return tq_putdesc (&tq_rq, desc); /* release desc */ } @@ -1693,14 +1751,16 @@ 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 */ + if (ring->lnt <= 4) /* lnt = 1? intr */ + tq_ring_int (ring); 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 (prvd & UQ_DESC_OWN) + tq_ring_int (ring); } } ring->idx = (ring->idx + 4) & (ring->lnt - 1); @@ -1714,9 +1774,11 @@ UNIT *tq_getucb (uint32 lu) { UNIT *uptr; -if (lu >= TQ_NUMDR) return NULL; +if (lu >= TQ_NUMDR) + return NULL; uptr = tq_dev.units + lu; -if (uptr->flags & UNIT_DIS) return NULL; +if (uptr->flags & UNIT_DIS) + return NULL; return uptr; } @@ -1738,9 +1800,12 @@ 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->flags & UNIT_POL) /* note pos lost */ + t = t | EF_PLS; + if (uptr->flags & UNIT_SXC) /* note ser exc */ + t = t | EF_SXC; + if (TEST_EOT (uptr)) /* note EOT */ + t = t | EF_EOT; } return t; } @@ -1785,7 +1850,8 @@ return; void tq_init_int (void) { -if ((tq_s1dat & SA_S1H_IE) && tq_dib.vec) SET_INT (TQ); +if ((tq_s1dat & SA_S1H_IE) && tq_dib.vec) + SET_INT (TQ); return; } @@ -1797,7 +1863,8 @@ 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 */ +if (tq_dib.vec) /* if enb, intr */ + SET_INT (TQ); return; } @@ -1812,7 +1879,8 @@ 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); +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 */ @@ -1827,9 +1895,10 @@ t_stat tq_attach (UNIT *uptr, char *cptr) t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -if (tq_csta == CST_UP) uptr->flags = (uptr->flags | UNIT_ATP) & - ~(UNIT_SXC | UNIT_POL | UNIT_TMK); +if (r != SCPE_OK) + return r; +if (tq_csta == CST_UP) + uptr->flags = (uptr->flags | UNIT_ATP) & ~(UNIT_SXC | UNIT_POL | UNIT_TMK); return SCPE_OK; } @@ -1840,7 +1909,8 @@ t_stat tq_detach (UNIT *uptr) t_stat r; r = sim_tape_detach (uptr); /* detach unit */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP | UNIT_SXC | UNIT_POL | UNIT_TMK); uptr->uf = 0; /* clr unit flgs */ return SCPE_OK; @@ -1856,7 +1926,8 @@ 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? */ +if (UNIBUS) /* Unibus? */ + tq_sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; 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 */ @@ -1866,9 +1937,11 @@ 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; + 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; + 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 */ @@ -1883,8 +1956,10 @@ for (i = 0; i < TQ_NUMDR + 2; i++) { /* init units */ 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; +if (tqxb == NULL) + tqxb = (uint8 *) calloc (TQ_MAXFR, sizeof (uint8)); +if (tqxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -2003,7 +2078,8 @@ int32 i; extern int32 saved_PC; extern uint16 *M; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & 3; M[BOOT_CSR >> 1] = tq_dib.ba & DMASK; saved_PC = BOOT_ENTRY; @@ -2107,7 +2183,8 @@ if (tq_csta != CST_UP) { return SCPE_OK; } if (val & TQ_SH_RI) { - if (tq_pip) fprintf (st, "Polling in progress, host timer = %d\n", tq_hat); + if (tq_pip) + fprintf (st, "Polling in progress, host timer = %d\n", tq_hat); else fprintf (st, "Host timer = %d\n", tq_hat); fprintf (st, "Command "); tq_show_ring (st, &tq_cq); @@ -2117,8 +2194,10 @@ 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); + 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"); @@ -2152,11 +2231,13 @@ t_stat r; if ((val < 0) || (val > TQU_TYPE) || ((val != TQU_TYPE) && cptr)) return SCPE_ARG; for (i = 0; i < TQ_NUMDR; i++) { - if (tq_unit[i].flags & UNIT_ATT) return SCPE_ALATT; + if (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; + if ((r != SCPE_OK) || (cap < TQU_MINC)) + return SCPE_ARG; drv_tab[TQU_TYPE].cap = ((t_addr) cap) << 20; } tq_typ = val; diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c index 9cb8b94c..6aae9e28 100644 --- a/PDP11/pdp11_ts.c +++ b/PDP11/pdp11_ts.c @@ -1,6 +1,6 @@ /* pdp11_ts.c: TS11/TSV05 magnetic tape simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -417,7 +417,8 @@ switch ((PA >> 1) & 01) { /* decode PA<1> */ case 1: /* TSSR */ if (PA & 1) { /* TSDBX */ - if (UNIBUS) return SCPE_OK; /* not in TS11 */ + if (UNIBUS) /* not in TS11 */ + return SCPE_OK; if (tssr & TSSR_SSR) { /* ready? */ tsdbx = data; /* save */ if (data & TSDBX_BOOT) { @@ -427,7 +428,8 @@ switch ((PA >> 1) & 01) { /* decode PA<1> */ } else tssr = tssr | TSSR_RMR; /* no, err */ } - else if (access == WRITE) ts_reset (&ts_dev); /* reset */ + else if (access == WRITE) /* reset */ + ts_reset (&ts_dev); break; } @@ -483,7 +485,8 @@ t_mtrlnt tbc; do { fc = (fc - 1) & DMASK; /* decr wc */ - if (upd) msgrfc = fc; + 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 */ @@ -498,7 +501,8 @@ t_mtrlnt tbc; t_bool tmkprv = FALSE; msgrfc = fc; -if (sim_tape_bot (uptr) && (wchopt & WCH_ENB)) tmkprv = TRUE; +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? */ @@ -509,7 +513,8 @@ do { XS0_TMK | XS0_LET, TC2)); tmkprv = TRUE; /* flag tmk */ } - else if (st != MTSE_OK) return ts_map_status (st); + 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); @@ -523,7 +528,8 @@ t_mtrlnt tbc; do { fc = (fc - 1) & DMASK; /* decr wc */ - if (upd) msgrfc = fc; + 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 */ @@ -548,7 +554,8 @@ do { XS0_TMK | XS0_LET, TC2)); tmkprv = TRUE; /* flag tmk */ } - else if (st != MTSE_OK) return ts_map_status (st); + 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); @@ -563,8 +570,10 @@ 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 */ +if (st != MTSE_OK) /* error? */ + return ts_map_status (st); +if (fc == 0) /* byte count */ + fc = 0200000; tsba = (cmdadh << 16) | cmdadl; /* buf addr */ wbc = (tbc > fc)? fc: tbc; /* cap buf size */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ @@ -588,8 +597,10 @@ else { } 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? */ +if (msgrfc) /* buf too big? */ + return (XTC (XS0_RLS, TC2)); +if (tbc > wbc) /* rec too big? */ + return (XTC (XS0_RLL, TC2)); return 0; } @@ -601,8 +612,10 @@ 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 */ +if (st != MTSE_OK) /* error? */ + return ts_map_status (st); +if (fc == 0) /* byte count */ + fc = 0200000; tsba = (cmdadh << 16) | cmdadl + fc; /* buf addr */ wbc = (tbc > fc)? fc: tbc; /* cap buf size */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ @@ -615,8 +628,10 @@ for (i = wbc; i > 0; i--) { /* copy buffer */ } 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? */ +if (msgrfc) /* buf too big? */ + return (XTC (XS0_RLS, TC2)); +if (tbc > wbc) /* rec too big? */ + return (XTC (XS0_RLL, TC2)); return 0; } @@ -627,7 +642,8 @@ uint32 wa; t_stat st; msgrfc = fc; -if (fc == 0) fc = 0200000; /* byte count */ +if (fc == 0) /* byte count */ + fc = 0200000; tsba = (cmdadh << 16) | cmdadl; /* buf addr */ if (cmdhdr & CMD_SWP) { /* swapped? */ for (i = 0; i < fc; i++) { /* copy mem to buf */ @@ -703,13 +719,15 @@ if (ts_bcmd) { /* boot? */ tssr = ts_updtssr (tssr | TSSR_SSR); } else tssr = ts_updtssr (tssr | TSSR_SSR | TC3); - if (cmdhdr & CMD_IE) SET_INT (TS); + 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); + if (cmdhdr & CMD_IE) + SET_INT (TS); ts_ownc = ts_ownm = 0; /* CPU owns all */ return SCPE_OK; } @@ -741,15 +759,15 @@ if ((fnc_flg[fnc] & FLG_MO) && /* mot+(vck|!att)? */ } 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; - } + 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; - } + 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; @@ -759,7 +777,8 @@ 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 */ + if (!sim_tape_bot (uptr)) /* set if tape moves */ + msgxs0 = msgxs0 | XS0_MOT; sim_tape_rewind (uptr); /* rewind */ case FNC_WSSM: /* write mem */ case FNC_GSTA: /* get status */ @@ -781,8 +800,8 @@ switch (fnc) { /* case on func */ } 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); + 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); @@ -795,12 +814,14 @@ switch (fnc) { /* case on func */ case 00: /* msg buf rls */ tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */ - if (wchopt & WCH_ERI) SET_INT (TS); + 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 */ + if (!sim_tape_bot (uptr)) /* if tape moves */ + msgxs0 = msgxs0 | XS0_MOT; sim_tape_detach (uptr); /* unload */ ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); break; @@ -814,7 +835,8 @@ switch (fnc) { /* case on func */ return SCPE_OK; case 04: /* rewind */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ + if (!sim_tape_bot (uptr)) /* if tape moves */ + msgxs0 = msgxs0 | XS0_MOT; sim_tape_rewind (uptr); ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND); break; @@ -927,7 +949,8 @@ return SCPE_OK; int32 ts_updtssr (int32 t) { t = (t & ~TSSR_EMA) | ((tsba >> (16 - TSSR_V_EMA)) & TSSR_EMA); -if (ts_unit.flags & UNIT_ATT) t = t & ~TSSR_OFL; +if (ts_unit.flags & UNIT_ATT) + t = t & ~TSSR_OFL; else t = t | TSSR_OFL; return (t & ~TSSR_MBZ); } @@ -937,14 +960,16 @@ 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_wrp (&ts_unit)) + t = t | XS0_WLK; if (sim_tape_bot (&ts_unit)) t = (t | XS0_BOT) & ~XS0_EOT; if (sim_tape_eot (&ts_unit)) t = (t | XS0_EOT) & ~XS0_BOT; } else t = t & ~XS0_EOT; -if (cmdhdr & CMD_IE) t = t | XS0_IE; +if (cmdhdr & CMD_IE) + t = t | XS0_IE; return t; } @@ -972,7 +997,8 @@ 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 (wchxopt & WCHX_HDS) /* update XS4 */ + msgxs4 = msgxs4 | XS4_HDS; if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */ msghdr = msg; msglnt = wchlnt - 4; /* exclude hdr, bc */ @@ -987,7 +1013,8 @@ if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */ } } tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0)); -if (cmdhdr & CMD_IE) SET_INT (TS); +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", @@ -1007,13 +1034,18 @@ ts_ownc = ts_ownm = 0; ts_bcmd = 0; ts_qatn = 0; tssr = ts_updtssr (TSSR_NBA | TSSR_SSR); -for (i = 0; i < CMD_PLNT; i++) tscmdp[i] = 0; -for (i = 0; i < WCH_PLNT; i++) tswchp[i] = 0; -for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0; +for (i = 0; i < CMD_PLNT; i++) + tscmdp[i] = 0; +for (i = 0; i < WCH_PLNT; i++) + tswchp[i] = 0; +for (i = 0; i < MSG_PLNT; i++) + tsmsgp[i] = 0; msgxs0 = ts_updxs0 (XS0_VCK); CLR_INT (TS); -if (tsxb == NULL) tsxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); -if (tsxb == NULL) return SCPE_MEM; +if (tsxb == NULL) + tsxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); +if (tsxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -1024,9 +1056,11 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; tssr = tssr & ~TSSR_OFL; /* clr offline */ -if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */ +if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) /* attn msg? */ + return r; if (ts_ownm) { /* own msg buf? */ ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */ SET_INT (TS); /* set interrupt */ @@ -1042,11 +1076,14 @@ t_stat ts_detach (UNIT* uptr) { t_stat r; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; r = sim_tape_detach (uptr); /* detach unit */ -if (r != SCPE_OK) return r; /* error? */ +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 ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) /* attn msg? */ + return r; if (ts_ownm) { /* own msg buf? */ ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */ SET_INT (TS); /* set interrupt */ diff --git a/PDP11/pdp11_tu.c b/PDP11/pdp11_tu.c index 5bd3bc6c..91d86198 100644 --- a/PDP11/pdp11_tu.c +++ b/PDP11/pdp11_tu.c @@ -1,6 +1,6 @@ /* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -371,7 +371,8 @@ switch (ofs) { /* decode offset */ 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; + if (tu_unit[drv].flags & UNIT_DIS) + *data |= DT_OFF; else *data |= DT_PRES | dt_map[GET_TYPE (tu_unit[drv].flags)]; break; @@ -396,21 +397,25 @@ t_stat tu_mbwr (int32 data, int32 ofs, int32 fmtr) { int32 drv; -if (fmtr != 0) return MBE_NXD; /* only one fmtr */ +if (fmtr != 0) /* only one fmtr */ + return MBE_NXD; 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); + if (tucs1 & CS1_GO) + tu_set_er (ER_RMR); else { tucs1 = data & CS1_RW; - if (tucs1 & CS1_GO) return tu_go (drv); + if (tucs1 & CS1_GO) + return tu_go (drv); } break; case FC_OF: /* MTFC */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + if (tucs1 & CS1_GO) + tu_set_er (ER_RMR); else { tufc = data; tutc = tutc | TC_FCS; /* set fc flag */ @@ -426,7 +431,8 @@ switch (ofs) { /* decode PA<4:1> */ break; case TC_OF: /* MTTC */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + if (tucs1 & CS1_GO) + tu_set_er (ER_RMR); else { tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC; drv = GET_DRV (tutc); @@ -438,7 +444,8 @@ switch (ofs) { /* decode PA<4:1> */ case CC_OF: /* MTCC */ case DT_OF: /* MTDT */ case SN_OF: /* MTSN */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + if (tucs1 & CS1_GO) + tu_set_er (ER_RMR); break; /* read only */ default: /* all others */ @@ -459,17 +466,17 @@ UNIT *uptr; 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); +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); 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_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 */ @@ -571,7 +578,8 @@ switch (fnc) { /* case on function */ tu_set_er (ER_FER); break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ + if (uptr->UDENS == UD_UNK) /* set dens */ + uptr->UDENS = den; uptr->USTAT = 0; GO_XFER: tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */ @@ -624,7 +632,8 @@ 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); + if (fnc >= FNC_XFER) + mba_set_don (tu_dib.ba); tu_update_fs (FS_ATA, drv); return (tu_stopioe? SCPE_UNATT: SCPE_OK); } @@ -640,7 +649,8 @@ switch (fnc) { /* case on function */ break; } } while ((tufc != 0) && !sim_tape_eot (uptr)); - if (tufc) tu_set_er (ER_FCE); + if (tufc) + tu_set_er (ER_FCE); else tutc = tutc & ~TC_FCS; break; @@ -652,7 +662,8 @@ switch (fnc) { /* case on function */ break; } } while (tufc != 0); - if (tufc) tu_set_er (ER_FCE); + if (tufc) + tu_set_er (ER_FCE); else tutc = tutc & ~TC_FCS; break; @@ -674,11 +685,13 @@ switch (fnc) { /* case on function */ 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 */ - if (st == MTSE_TMK) tu_set_er (ER_FCE); /* tmk also sets FCE */ + if (st == MTSE_TMK) /* tmk also sets FCE */ + tu_set_er (ER_FCE); 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 */ + for (i = tbc; i < tbc + 4; i++) /* pad with 0's */ + xbuf[i] = 0; if (fmt == TC_CDUMP) { /* core dump? */ for (i = j = 0; i < tbc; i = i + 4) { wbuf[j++] = ((uint16) xbuf[i] & 0xF) | @@ -697,14 +710,16 @@ switch (fnc) { /* case on function */ } 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); + 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 (xbc == 0) /* anything?? */ + break; if (fmt == TC_CDUMP) { /* core dump? */ for (i = j = 0; j < xbc; j = j + 1) { xbuf[i++] = wbuf[j] & 0xF; @@ -725,7 +740,8 @@ switch (fnc) { /* case on function */ r = tu_map_err (drv, st, 1); /* map error */ else { tufc = (tufc + tbc) & 0177777; - if (tufc == 0) tutc = tutc & ~TC_FCS; + if (tufc == 0) + tutc = tutc & ~TC_FCS; } break; @@ -733,7 +749,8 @@ switch (fnc) { /* case on function */ case FNC_WCHKR: /* wcheck = read */ tufc = 0; /* clear frame count */ if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */ - if (st == MTSE_TMK) tu_set_er (ER_FCE); /* tmk also sets FCE */ + if (st == MTSE_TMK) /* tmk also sets FCE */ + tu_set_er (ER_FCE); r = tu_map_err (drv, st, 1); /* map error */ break; /* done */ } @@ -756,7 +773,8 @@ switch (fnc) { /* case on function */ } 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); + if (fnc == FNC_WCHKR) + mba_chbufW (tu_dib.ba, xbc, wbuf); else mba_wrbufW (tu_dib.ba, xbc, wbuf); tufc = tbc & 0177777; break; @@ -768,9 +786,9 @@ if (fnc >= FNC_XFER) { /* data xfer? */ 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); +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); return SCPE_OK; } @@ -788,7 +806,8 @@ return; void tu_clr_as (int32 mask) { -if (mask & AS_U0) tufs = tufs & ~FS_ATA; +if (mask & AS_U0) + tufs = tufs & ~FS_ATA; mba_upd_ata (tu_dib.ba, tufs & FS_ATA); return; } @@ -802,8 +821,10 @@ 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 (tu_unit[drv].UDENS == TC_1600) + tufs = tufs | FS_PE; + if (sim_tape_wrp (&tu_unit[drv])) + tufs = tufs | FS_WRL; if (!act) { if (sim_tape_bot (&tu_unit[drv])) tufs = tufs | FS_BOT; @@ -811,9 +832,12 @@ if (tu_unit[drv].flags & UNIT_ATT) { tufs = tufs | FS_EOT; } } -if (tuer) tufs = tufs | FS_ERR; -if (tufs && !act) tufs = tufs | FS_RDY; -if (flg & FS_ATA) mba_upd_ata (tu_dib.ba, 1); +if (tuer) + tufs = tufs | FS_ERR; +if (tufs && !act) + tufs = tufs | FS_RDY; +if (flg & FS_ATA) + mba_upd_ata (tu_dib.ba, 1); return; } @@ -826,7 +850,8 @@ 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 */ + if (qdt) /* set exception */ + mba_set_exc (tu_dib.ba); break; case MTSE_TMK: /* end of file */ @@ -835,22 +860,26 @@ switch (st) { case MTSE_IOERR: /* IO error */ tu_set_er (ER_VPE); /* flag error */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + if (qdt) /* set exception */ + mba_set_exc (tu_dib.ba); 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 */ + if (qdt) /* set exception */ + mba_set_exc (tu_dib.ba); 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 */ + if (qdt) /* set exception */ + mba_set_exc (tu_dib.ba); break; case MTSE_EOM: /* end of medium */ tu_set_er (ER_OPI); /* incomplete */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + if (qdt) /* set exception */ + mba_set_exc (tu_dib.ba); break; case MTSE_BOT: /* reverse into BOT */ @@ -858,7 +887,8 @@ switch (st) { case MTSE_WRP: /* write protect */ tu_set_er (ER_NXF); /* can't execute */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + if (qdt) /* set exception */ + mba_set_exc (tu_dib.ba); break; default: /* unknown error */ @@ -880,7 +910,8 @@ tucs1 = 0; tufc = 0; tuer = 0; tufs = FS_FPR | FS_RDY; -if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */ +if (sim_switches & SWMASK ('P')) /* powerup? clr TC */ + tutc = 0; else tutc = tutc & ~TC_FCS; /* no, clr */ for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */ uptr = tu_dev.units + u; @@ -888,10 +919,14 @@ for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */ 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 = (uint16 *) calloc ((MT_MAXFR + 4) >> 1, sizeof (uint16)); -if (wbuf == NULL) return SCPE_MEM; +if (xbuf == NULL) + xbuf = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8)); +if (xbuf == NULL) + return SCPE_MEM; +if (wbuf == NULL) + wbuf = (uint16 *) calloc ((MT_MAXFR + 4) >> 1, sizeof (uint16)); +if (wbuf == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -903,11 +938,13 @@ int32 drv = uptr - tu_dev.units, flg; t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +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 */ +if (GET_DRV (tutc) == drv) /* sel drv? set SAT */ + flg = flg | FS_SAT; tu_update_fs (flg, drv); /* update status */ return r; } @@ -918,7 +955,8 @@ t_stat tu_detach (UNIT* uptr) { int32 drv = uptr - tu_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; uptr->USTAT = 0; /* clear status flags */ tu_update_fs (FS_ATA | FS_SSC, drv); /* update status */ return sim_tape_detach (uptr); @@ -930,9 +968,12 @@ t_stat tu_set_fmtr (UNIT *uptr, int32 val, char *cptr, void *desc) { DEVICE *dptr = find_dev_from_unit (uptr); -if (cptr != NULL) return SCPE_ARG; -if (dptr == NULL) return SCPE_IERR; -if (val) dptr->flags = dptr->flags | DEV_TM03; +if (cptr != NULL) + return SCPE_ARG; +if (dptr == NULL) + return SCPE_IERR; +if (val) + dptr->flags = dptr->flags | DEV_TM03; else dptr->flags = dptr->flags & ~DEV_TM03; return SCPE_OK; } @@ -941,7 +982,8 @@ t_stat tu_show_fmtr (FILE *st, UNIT *uptr, int32 val, void *desc) { DEVICE *dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; fprintf (st, "TM0%d", (dptr->flags & DEV_TM03? 3: 2)); return SCPE_OK; } @@ -992,7 +1034,8 @@ int32 i; extern int32 saved_PC; extern uint16 *M; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & (TU_NUMDR - 1); M[BOOT_CSR >> 1] = mba_get_csr (tu_dib.ba) & DMASK; saved_PC = BOOT_ENTRY; diff --git a/PDP11/pdp11_uqssp.h b/PDP11/pdp11_uqssp.h index e0e4ce11..b995949a 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-2005, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a diff --git a/PDP11/pdp11_vh.c b/PDP11/pdp11_vh.c index 3677431f..2fdde2a7 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-2006, John A. Dundas III + Copyright (c) 2004-2008, John A. Dundas III Portions derived from work by Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a @@ -26,6 +26,7 @@ vh DHQ11 asynch multiplexor for SIMH + 19-Nov-08 RMS Revised for common TMXR show routines 18-Jun-07 RMS Added UNIT_IDLE flag 29-Oct-06 RMS Synced poll and clock 07-Jul-05 RMS Removed extraneous externs @@ -292,14 +293,11 @@ static t_stat vh_clear (int32 vh, t_bool flag); static t_stat vh_reset (DEVICE *dptr); static t_stat vh_attach (UNIT *uptr, char *cptr); static t_stat vh_detach (UNIT *uptr); -static t_stat vh_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -static t_stat vh_show (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_debug (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_rbuf (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_txq (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_putc (int32 vh, TMLX *lp, int32 chan, int32 data); static void doDMA (int32 vh, int32 chan); -static t_stat vh_summ (FILE *st, UNIT *uptr, int32 val, void *desc); int32 tmxr_send_buffered_data (TMLN *lp); @@ -323,8 +321,6 @@ static UNIT vh_unit[VH_MUXES] = { { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, }; -static const REG vh_nlreg = { DRDATA (NLINES, vh_desc.lines, 6), PV_LEFT }; - static const REG vh_reg[] = { { BRDATA (CSR, vh_csr, DEV_RDX, 16, VH_MUXES) }, { GRDATA (DEVADDR, vh_dib.ba, DEV_RDX, 32, 0), REG_HRO }, @@ -343,18 +339,19 @@ static const MTAB vh_mod[] = { { UNIT_HANGUP, UNIT_HANGUP, "hangup", "HANGUP", NULL }, { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &vh_show_vec, NULL }, + { MTAB_XTD|MTAB_VDV, VH_LINES, "VECTOR", "VECTOR", + &set_vec, &show_vec_mux, (void *) &vh_desc }, { MTAB_XTD|MTAB_VDV, 0, NULL, "AUTOCONFIGURE", &set_addr_flt, NULL, NULL }, /* this one is dangerous, don't use yet */ - { MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "lines", "LINES", - NULL, NULL, (REG *)&vh_nlreg }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &vh_summ }, + { MTAB_XTD|MTAB_VDV, 0, "LINES", "LINES", + NULL, &tmxr_show_lines, (void *) &vh_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &vh_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &vh_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &vh_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &vh_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &vh_desc }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &vh_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEBUG", NULL, @@ -1268,40 +1265,6 @@ static t_stat vh_detach ( UNIT *uptr ) return (tmxr_detach (&vh_desc, uptr)); } -static t_stat vh_summ ( FILE *st, - UNIT *uptr, - int32 val, - void *desc ) -{ -int32 i, t; - -for (i = t = 0; i < vh_desc.lines; i++) { /* get num conn */ - if (vh_ldsc[i].conn) t = t + 1; } -fprintf (st, "%d %s", t, (t == 1) ? "connection" : "connections"); -return SCPE_OK; -} - -static t_stat vh_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < vh_desc.lines; i++) { /* loop thru conn */ - if (vh_ldsc[i].conn) { - t = 1; - if (val) tmxr_fconns (st, &vh_ldsc[i], i); - else tmxr_fstats (st, &vh_ldsc[i], i); } } -if (t == 0) fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -static t_stat vh_show_vec ( FILE *st, - UNIT *uptr, - int32 val, - void *desc ) -{ - return (show_vec (st, uptr, ((vh_desc.lines * 2) / VH_LINES), desc)); -} - static void debug_line ( FILE *st, int32 vh, int32 chan ) diff --git a/PDP11/pdp11_xq.h b/PDP11/pdp11_xq.h index c90edff5..737552c7 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-2005, David T. Hittner + Copyright (c) 2002-2008, 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"), diff --git a/PDP11/pdp11_xq_bootrom.h b/PDP11/pdp11_xq_bootrom.h index e12d3519..125b6c32 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-2005, David T. Hittner + Copyright (c) 2003-2008, 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"), diff --git a/PDP11/pdp11_xu.h b/PDP11/pdp11_xu.h index 43f1c998..e07b5a53 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-2005, David T. Hittner + Copyright (c) 2003-2008, 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"), diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c index 7886d834..cfce154c 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -404,7 +404,8 @@ 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); @@ -583,7 +584,8 @@ int32 iot_data, device, pulse; int32 last_IR; t_stat reason; -if (build_dev_tab ()) return SCPE_STOP; /* build, chk tables */ +if (build_dev_tab ()) /* build, chk tables */ + return SCPE_STOP; PC = PC & AMASK; /* clean variables */ LAC = LAC & LACMASK; MQ = MQ & DMASK; @@ -602,7 +604,8 @@ while (reason == 0) { /* loop until halted */ int32 link_init, fill; if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; api_int = api_eval (&int_pend); /* eval API */ } @@ -677,7 +680,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (hst_lnt) /* record */ + cpu_intr_hist (HIST_API, lvl); 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 */ @@ -708,7 +712,8 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (hst_lnt) /* record */ + cpu_intr_hist (HIST_PI, 0); MB = Jms_word (usmd); /* save state */ ion = 0; /* interrupts off */ ion_defer = 2; /* free instruction */ @@ -730,7 +735,8 @@ while (reason == 0) { /* loop until halted */ reason = STOP_IBKPT; /* stop simulation */ break; } - if (!usmd_defer) usmd = usmd_buf; /* no IOT? load usmd */ + if (!usmd_defer) /* no IOT? load usmd */ + usmd = usmd_buf; else usmd_defer = 0; /* cancel defer */ #endif /* PDP-9/PDP-15 */ @@ -739,17 +745,22 @@ while (reason == 0) { /* loop until halted */ xct_count = 0; /* track nested XCT's */ MA = PC; /* fetch at PC */ - if (Read (MA, &IR, FE)) continue; /* fetch instruction */ + if (Read (MA, &IR, FE)) /* fetch instruction */ + continue; PC = Incr_addr (PC); /* increment PC */ xct_instr: /* label for API, XCT */ - 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 (hst_lnt) /* history? */ + cpu_inst_hist (MA, IR); + if (ion_defer) /* count down defer */ + ion_defer = ion_defer - 1; + 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 */ + if (memm) /* bank mode dir addr */ + MA = (MA & B_EPCMASK) | (IR & B_DAMASK); else MA = (MA & P_EPCMASK) | (IR & P_DAMASK); /* page mode dir addr */ #else /* others */ @@ -763,17 +774,20 @@ while (reason == 0) { /* loop until halted */ /* LAC: opcode 20 */ case 011: /* LAC, indir */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 010: /* LAC, dir */ INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; + if (Read (MA, &MB, RD)) + break; LAC = (LAC & LINK) | MB; break; /* DAC: opcode 04 */ case 003: /* DAC, indir */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 002: /* DAC, dir */ INDEX (IR, MA); Write (MA, LAC & DMASK, WR); @@ -782,7 +796,8 @@ while (reason == 0) { /* loop until halted */ /* DZM: opcode 14 */ case 007: /* DZM, indir */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 006: /* DZM, direct */ INDEX (IR, MA); Write (MA, 0, WR); @@ -791,32 +806,39 @@ while (reason == 0) { /* loop until halted */ /* AND: opcode 50 */ case 025: /* AND, ind */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 024: /* AND, dir */ INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; + if (Read (MA, &MB, RD)) + break; LAC = LAC & (MB | LINK); break; /* XOR: opcode 24 */ case 013: /* XOR, ind */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 012: /* XOR, dir */ INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; + if (Read (MA, &MB, RD)) + break; LAC = LAC ^ MB; break; /* ADD: opcode 30 */ case 015: /* ADD, indir */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 014: /* ADD, dir */ INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; + if (Read (MA, &MB, RD)) + break; t = (LAC & DMASK) + MB; - if (t > DMASK) t = (t + 1) & DMASK; /* end around carry */ + if (t > DMASK) /* end around carry */ + t = (t + 1) & DMASK; if (((~LAC ^ MB) & (LAC ^ t)) & SIGN) /* overflow? */ LAC = LINK | t; /* set link */ else LAC = (LAC & LINK) | t; @@ -825,43 +847,54 @@ while (reason == 0) { /* loop until halted */ /* TAD: opcode 34 */ case 017: /* TAD, indir */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 016: /* TAD, dir */ INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; + if (Read (MA, &MB, RD)) + break; LAC = (LAC + MB) & LACMASK; break; /* ISZ: opcode 44 */ case 023: /* ISZ, indir */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; case 022: /* ISZ, dir */ INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; + if (Read (MA, &MB, RD)) + break; MB = (MB + 1) & DMASK; - if (Write (MA, MB, WR)) break; - if (MB == 0) PC = Incr_addr (PC); + 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; + 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); + 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; + 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 */ + if (usmd) /* trap if usmd */ + prvn = trap_pending = 1; break; /* nop if api_usmd */ } if (xct_count >= xct_max) { /* too many XCT's? */ @@ -872,7 +905,8 @@ while (reason == 0) { /* loop until halted */ #if defined (PDP9) ion_defer = 1; /* defer intr */ #endif - if (Read (MA, &IR, FE)) break; /* fetch inst, mm err? */ + if (Read (MA, &IR, FE)) /* fetch inst, mm err? */ + break; goto xct_instr; /* go execute */ /* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle @@ -888,7 +922,8 @@ while (reason == 0) { /* loop until halted */ MA = 020; /* MA = abs 20 */ ion_defer = 1; /* "free instruction" */ #else /* others */ - if (memm) MA = 020; /* if ext, abs 20 */ + if (memm) /* if ext, abs 20 */ + MA = 020; else MA = (PC & B_EPCMASK) | 020; /* else bank-rel 20 */ #endif #if defined (PDP9) || defined (PDP15) @@ -902,7 +937,8 @@ while (reason == 0) { /* loop until halted */ } #endif if (IR & I_IND) { /* indirect? */ - if (Ia (MA, &MA, 0)) break; + if (Ia (MA, &MA, 0)) + break; } PCQ_ENTRY; MB = Jms_word (api_usmd | t); /* save state */ @@ -913,22 +949,26 @@ while (reason == 0) { /* loop until halted */ /* JMS: opcode 010 - api_usmd records whether usmd = 1 at start of API cycle */ case 005: /* JMS, indir */ - if (Ia (MA, &MA, 0)) break; + 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" */ + if (!usmd) /* "free instruction" */ + ion_defer = 1; #endif MB = Jms_word (api_usmd | usmd); /* save state */ - if (Write (MA, MB, WR)) break; + 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; + if (Ia (MA, &MA, 1)) + break; INDEX (IR, MA); PCQ_ENTRY; /* save old PC */ PC = MA & AMASK; @@ -948,7 +988,8 @@ while (reason == 0) { /* loop until halted */ sim_idle (0, FALSE); /* we're idle */ } else if (((MA ^ (PC - 1)) & AMASK) == 0) { /* 2) JMP *? */ - if (iof) reason = STOP_LOOP; /* iof? inf loop */ + if (iof) /* iof? inf loop */ + reason = STOP_LOOP; else sim_idle (0, FALSE); /* ion? idle */ } } /* end idle */ @@ -967,51 +1008,63 @@ while (reason == 0) { /* loop until halted */ case 0: /* nop */ break; case 1: /* SMA */ - if ((LAC & SIGN) != 0) skp = 1; + if ((LAC & SIGN) != 0) + skp = 1; break; case 2: /* SZA */ - if ((LAC & DMASK) == 0) skp = 1; + 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; + if (LAC >= LINK) + skp = 1; break; case 5: /* SNL | SMA */ - if (LAC >= SIGN) skp = 1; + if (LAC >= SIGN) + skp = 1; break; case 6: /* SNL | SZA */ - if ((LAC >= LINK) || (LAC == 0)) skp = 1; + if ((LAC >= LINK) || (LAC == 0)) + skp = 1; break; case 7: /* SNL | SZA | SMA */ - if ((LAC >= SIGN) || (LAC == 0)) skp = 1; + if ((LAC >= SIGN) || (LAC == 0)) + skp = 1; break; case 010: /* SKP */ skp = 1; break; case 011: /* SPA */ - if ((LAC & SIGN) == 0) skp = 1; + if ((LAC & SIGN) == 0) + skp = 1; break; case 012: /* SNA */ - if ((LAC & DMASK) != 0) skp = 1; + 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; + if (LAC < LINK) + skp = 1; break; case 015: /* SZL & SPA */ - if (LAC < SIGN) skp = 1; + if (LAC < SIGN) + skp = 1; break; case 016: /* SZL & SNA */ - if ((LAC < LINK) && (LAC != 0)) skp = 1; + if ((LAC < LINK) && (LAC != 0)) + skp = 1; break; case 017: /* SZL & SNA & SPA */ - if ((LAC < SIGN) && (LAC != 0)) skp = 1; + if ((LAC < SIGN) && (LAC != 0)) + skp = 1; break; } /* end switch skips */ @@ -1067,7 +1120,8 @@ while (reason == 0) { /* loop until halted */ if (IR & 0000004) { /* OAS */ #if defined (PDP9) || defined (PDP15) - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ + if (usmd) /* trap if usmd */ + prvn = trap_pending = 1; else if (!api_usmd) /* nop if api_usmd */ #endif LAC = LAC | SR; @@ -1076,7 +1130,7 @@ while (reason == 0) { /* loop until halted */ switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */ case 1: /* RAL */ LAC = ((LAC << 1) | (LAC >> 18)) & LACMASK; - break; + break; case 2: /* RAR */ LAC = ((LAC >> 1) | (LAC << 18)) & LACMASK; break; @@ -1104,10 +1158,13 @@ while (reason == 0) { /* loop until halted */ } /* 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 (usmd) /* trap if usmd */ + prvn = trap_pending = 1; + else if (!api_usmd) /* nop if api_usmd */ + reason = STOP_HALT; } - if (skp) PC = Incr_addr (PC); /* if skip, inc PC */ + if (skp) /* if skip, inc PC */ + PC = Incr_addr (PC); break; /* end OPR */ /* EAE: opcode 64 @@ -1121,25 +1178,33 @@ while (reason == 0) { /* loop until halted */ down to zero; the read SC command compensates. */ case 033: case 032: /* EAE */ - if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */ + if (cpu_unit.flags & UNIT_NOEAE) /* disabled? */ + break; 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 & 0010000) /* IR<5>? clear MQ */ + MQ = 0; 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 */ + if (IR & 0002000) /* IR<7>? or AC */ + MQ = (MQ | LAC) & DMASK; + else if (eae_ac_sign) /* if not, |AC| */ + LAC = LAC ^ DMASK; + if (IR & 0001000) /* IR<8>? clear AC */ + LAC = LAC & LINK; link_init = LAC & LINK; /* link temporary */ fill = link_init? DMASK: 0; /* fill = link */ esc = IR & 077; /* get eff SC */ switch ((IR >> 6) & 07) { /* case on IR<9:11> */ case 0: /* setup */ - if (IR & 04) MQ = MQ ^ DMASK; /* IR<15>? ~MQ */ - if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */ - if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */ + if (IR & 04) /* IR<15>? ~MQ */ + MQ = MQ ^ DMASK; + if (IR & 02) /* IR<16>? or MQ */ + LAC = LAC | MQ; + if (IR & 01) /* IR<17>? or SC */ + LAC = LAC | ((-SC) & 077); break; /* Multiply uses a shift and add algorithm. The PDP-15, unlike prior @@ -1147,13 +1212,16 @@ while (reason == 0) { /* loop until halted */ of the result sign. */ case 1: /* multiply */ - if (Read (PC, &MB, FE)) break; /* get next word */ + if (Read (PC, &MB, FE)) /* get next word */ + break; PC = Incr_addr (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ + if (eae_ac_sign) /* EAE AC sign? ~MQ */ + MQ = MQ ^ DMASK; LAC = LAC & DMASK; /* clear link */ SC = esc; /* init SC */ do { /* loop */ - if (MQ & 1) LAC = LAC + MB; /* MQ<17>? add */ + if (MQ & 1) /* MQ<17>? add */ + LAC = LAC + MB; MQ = (MQ >> 1) | ((LAC & 1) << 17); LAC = LAC >> 1; /* shift AC'MQ right */ SC = (SC - 1) & 077; /* decrement SC */ @@ -1170,13 +1238,15 @@ while (reason == 0) { /* loop until halted */ /* 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 + prior implementations, factors IR<6> (signed divide) into the calculation of the result sign. */ case 3: /* divide */ - if (Read (PC, &MB, FE)) break; /* get next word */ + if (Read (PC, &MB, FE)) /* get next word */ + break; PC = Incr_addr (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ + if (eae_ac_sign) /* EAE AC sign? ~MQ */ + MQ = MQ ^ DMASK; if ((LAC & DMASK) >= MB) { /* overflow? */ LAC = (LAC - MB) | LINK; /* set link */ break; @@ -1185,16 +1255,19 @@ while (reason == 0) { /* loop until halted */ t = 0; /* init loop */ SC = esc; /* init SC */ do { /* loop */ - if (t) LAC = (LAC + MB) & LACMASK; + 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; + if (SC > 1) /* skip if last */ + LAC =((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 (t) + LAC = (LAC + MB) & LACMASK; + if (eae_ac_sign) /* sgn rem = sgn divd */ + LAC = LAC ^ DMASK; #if defined (PDP15) if ((IR & 0004000) && (eae_ac_sign ^ link_init)) #else @@ -1209,13 +1282,15 @@ while (reason == 0) { /* loop until halted */ case 4: /* normalize */ #if defined (PDP15) - if (!usmd) ion_defer = 2; /* free instructions */ + if (!usmd) /* free instructions */ + ion_defer = 2; #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; + if (SC == 0) + break; } LAC = link_init | (LAC & DMASK); /* trim AC, restore L */ MQ = MQ & DMASK; /* trim MQ */ @@ -1228,8 +1303,8 @@ while (reason == 0) { /* loop until halted */ LAC = ((fill << (18 - esc)) | (LAC >> esc)) & LACMASK; } else { - if (esc < 36) MQ = - ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK; + if (esc < 36) + MQ = ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK; else MQ = fill; LAC = link_init | fill; } @@ -1238,13 +1313,12 @@ while (reason == 0) { /* loop until halted */ case 6: /* long left shift */ if (esc < 18) { - LAC = link_init | - (((LAC << esc) | (MQ >> (18 - esc))) & DMASK); + 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); + if (esc < 36) + LAC = link_init | (((MQ << (esc - 18)) | (fill >> (36 - esc))) & DMASK); else LAC = link_init | fill; MQ = fill; } @@ -1252,8 +1326,8 @@ while (reason == 0) { /* loop until halted */ break; case 7: /* AC left shift */ - if (esc < 18) LAC = link_init | - (((LAC << esc) | (fill >> (18 - esc))) & DMASK); + if (esc < 18) + LAC = link_init | (((LAC << esc) | (fill >> (18 - esc))) & DMASK); else LAC = link_init | fill; SC = 0; /* clear step count */ break; @@ -1281,7 +1355,8 @@ while (reason == 0) { /* loop until halted */ break; case 005: /* AXS */ XR = (XR + t) & DMASK; - if (SEXT (XR) >= SEXT (LR)) PC = Incr_addr (PC); + if (SEXT (XR) >= SEXT (LR)) + PC = Incr_addr (PC); break; case 006: /* PXL */ LR = XR; @@ -1357,12 +1432,14 @@ while (reason == 0) { /* loop until halted */ #endif if ((api_usmd | usmd) && /* user, not XVM UIOT? */ (!XVM || !(MMR & MM_UIOT))) { - if (usmd) prvn = trap_pending = 1; /* trap if user */ + if (usmd) /* trap if user */ + prvn = trap_pending = 1; 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? */ + if (IR & 0000010) /* clear AC? */ + LAC = LAC & LINK; iot_data = LAC & DMASK; /* AC unchanged */ /* PDP-4 system IOT's */ @@ -1371,8 +1448,10 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (pulse == 002) /* IOF */ + ion = 0; + else if (pulse == 042) /* ION */ + ion = ion_defer = 1; else iot_data = clk (device, pulse, iot_data); break; #endif @@ -1383,24 +1462,31 @@ while (reason == 0) { /* loop until halted */ 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 */ + if (pulse == 002) /* IOF */ + ion = 0; + else if (pulse == 042) /* ION */ + ion = ion_defer = 1; 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 */ + if ((pulse == 001) || (pulse == 041)) + PC = Incr_addr (PC); + else if (pulse == 002) /* CAF - skip CPU */ + reset_all (1); break; case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = Incr_addr (PC); - else if (pulse == 002) memm = 1; /* EEM */ + if ((pulse == 001) && memm) + PC = Incr_addr (PC); + else if (pulse == 002) /* EEM */ + memm = 1; else if (pulse == 042) /* EMIR */ memm = emir_pending = 1; /* ext on, restore */ - else if (pulse == 004) memm = 0; /* LEM */ + else if (pulse == 004) /* LEM */ + memm = 0; break; #endif @@ -1412,8 +1498,10 @@ while (reason == 0) { /* loop until halted */ switch (device) { /* decode IR<6:11> */ case 000: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = 1; /* ION */ + if (pulse == 002) /* IOF */ + ion = 0; + else if (pulse == 042) /* ION */ + ion = ion_defer = 1; else iot_data = clk (device, pulse, iot_data); break; @@ -1423,11 +1511,14 @@ while (reason == 0) { /* loop until halted */ PC = Incr_addr (PC); else if ((pulse == 041) && nexm) /* MPSNE */ PC = Incr_addr (PC); - else if (pulse == 002) prvn = 0; /* MPCV */ - else if (pulse == 042) usmd_buf = 1; /* MPEU */ + else if (pulse == 002) /* MPCV */ + prvn = 0; + else if (pulse == 042) /* MPEU */ + usmd_buf = 1; else if (pulse == 004) /* MPLD */ BR = LAC & BRMASK; - else if (pulse == 044) nexm = 0; /* MPCNE */ + else if (pulse == 044) /* MPCNE */ + nexm = 0; } else reason = stop_inst; break; @@ -1438,12 +1529,14 @@ while (reason == 0) { /* loop until halted */ break; case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); + if ((pulse == 001) || (pulse == 041)) + PC = Incr_addr (PC); else if (pulse == 002) { /* CAF */ reset_all (1); /* reset all exc CPU */ cpu_caf (); /* CAF to CPU */ } - else if (pulse == 044) rest_pending = 1; /* DBR */ + else if (pulse == 044) /* DBR */ + rest_pending = 1; if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { int32 t = api_ffo[api_act & 0377]; api_act = api_act & ~(API_ML0 >> t); @@ -1451,7 +1544,8 @@ while (reason == 0) { /* loop until halted */ break; case 055: /* API control */ - if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; + if (cpu_unit.flags & UNIT_NOAPI) + reason = stop_inst; else if (pulse == 001) { /* SPI */ if (((LAC & SIGN) && api_enb) || ((LAC & 0377) > api_act)) @@ -1469,11 +1563,14 @@ while (reason == 0) { /* loop until halted */ break; case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = Incr_addr (PC); - else if (pulse == 002) memm = 1; /* EEM */ + if ((pulse == 001) && memm) + PC = Incr_addr (PC); + else if (pulse == 002) /* EEM */ + memm = 1; else if (pulse == 042) /* EMIR */ memm = emir_pending = 1; /* ext on, restore */ - else if (pulse == 004) memm = 0; /* LEM */ + else if (pulse == 004) /* LEM */ + memm = 0; break; #endif @@ -1485,8 +1582,10 @@ while (reason == 0) { /* loop until halted */ switch (device) { /* decode IR<6:11> */ case 000: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = 1; /* ION */ + if (pulse == 002) /* IOF */ + ion = 0; + else if (pulse == 042) /* ION */ + ion = ion_defer = 1; else if (XVM && (pulse == 022)) /* ORMM/RDMM */ iot_data = MMR; else if (XVM && (pulse == 024)) /* LDMM */ @@ -1501,15 +1600,18 @@ while (reason == 0) { /* loop until halted */ PC = Incr_addr (PC); else if ((pulse == 041) && nexm) /* MPSNE */ PC = Incr_addr (PC); - else if (pulse == 002) prvn = 0; /* MPCV */ + else if (pulse == 002) /* MPCV */ + prvn = 0; else if (pulse == 042) /* MPEU */ usmd_buf = 1; else if (XVM && (pulse == 062)) /* RDCLK */ iot_data = clk_task_upd (TRUE); - else if (pulse == 004) BR = LAC & t; /* MPLD */ + else if (pulse == 004) /* MPLD */ + BR = LAC & t; else if (RELOC && (pulse == 024)) /* MPLR */ RR = LAC & t; - else if (pulse == 044) nexm = 0; /* MPCNE */ + else if (pulse == 044) /* MPCNE */ + nexm = 0; } else reason = stop_inst; break; @@ -1520,12 +1622,14 @@ while (reason == 0) { /* loop until halted */ break; case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); + if ((pulse == 001) || (pulse == 041)) + PC = Incr_addr (PC); else if (pulse == 002) { /* CAF */ reset_all (2); /* reset all exc CPU, FP15 */ cpu_caf (); /* CAF to CPU */ } - else if (pulse == 044) rest_pending = 1; /* DBR */ + else if (pulse == 044) /* DBR */ + rest_pending = 1; if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { int32 t = api_ffo[api_act & 0377]; api_act = api_act & ~(API_ML0 >> t); @@ -1533,7 +1637,8 @@ while (reason == 0) { /* loop until halted */ break; case 055: /* API control */ - if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; + if (cpu_unit.flags & UNIT_NOAPI) + reason = stop_inst; else if (pulse == 001) { /* SPI */ if (((LAC & SIGN) && api_enb) || ((LAC & 0377) > api_act)) @@ -1548,16 +1653,21 @@ while (reason == 0) { /* loop until halted */ 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 */ + else if (pulse == 021) /* ENB */ + ion_inh = 0; + else if (pulse == 022) /* INH */ + ion_inh = 1; 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 */ + else if (pulse == 042) /* RES */ + rest_pending = 1; + else if (pulse == 062) /* DBA */ + memm = 0; + else if (pulse == 064) /* EBA */ + memm = 1; break; #endif @@ -1571,8 +1681,10 @@ while (reason == 0) { /* loop until halted */ } /* 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; + 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 */ @@ -1596,19 +1708,23 @@ int32 i, hi; *pend = 0; /* assume no intr */ #if defined (PDP15) /* PDP15 only */ -if (ion_inh) return 0; /* inhibited? */ +if (ion_inh) /* inhibited? */ + return 0; #endif for (i = 0; i < API_HLVL+1; i++) { /* any intr? */ - if (int_hwre[i]) *pend = 1; + if (int_hwre[i]) + *pend = 1; } -if (api_enb == 0) return 0; /* off? no req */ +if (api_enb == 0) /* off? no req */ + return 0; 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); +if (hi < api_ffo[api_act & 0377]) + return (hi + 1); return 0; } @@ -1638,7 +1754,8 @@ return d; t_stat Read (int32 ma, int32 *dat, int32 cyc) { ma = ma & AMASK; -if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; +if (MEM_ADDR_OK (ma)) + *dat = M[ma] & DMASK; else *dat = 0; return MM_OK; } @@ -1646,7 +1763,8 @@ return MM_OK; t_stat Write (int32 ma, int32 dat, int32 cyc) { ma = ma & AMASK; -if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; +if (MEM_ADDR_OK (ma)) + M[ma] = dat & DMASK; return MM_OK; } @@ -1662,10 +1780,12 @@ if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */ } else sta = Read (ma, &t, DF); /* fetch indirect */ if (jmp) { /* jmp i? */ - if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; + if (emir_pending && (((t >> 16) & 1) == 0)) + memm = 0; emir_pending = rest_pending = 0; } -if (memm) *ea = t & IAMASK; /* extend? 15b ia */ +if (memm) /* extend? 15b ia */ + *ea = t & IAMASK; else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ return sta; } @@ -1712,7 +1832,8 @@ if (usmd) { /* user mode? */ return MM_ERR; } } -if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; /* valid mem? ok */ +if (MEM_ADDR_OK (ma)) /* valid mem? ok */ + *dat = M[ma] & DMASK; else { *dat = 0; /* set flag, no trap */ nexm = 1; @@ -1733,7 +1854,8 @@ if (usmd) { return MM_ERR; } } -if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; /* valid mem? ok */ +if (MEM_ADDR_OK (ma)) /* valid mem? ok */ + M[ma] = dat & DMASK; else nexm = 1; /* set flag, no trap */ return MM_OK; } @@ -1751,7 +1873,8 @@ if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */ } else sta = Read (ma, &t, DF); if (jmp) { /* jmp i? */ - if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; + 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 */ @@ -1759,7 +1882,8 @@ if (jmp) { /* jmp i? */ } emir_pending = rest_pending = 0; } -if (memm) *ea = t & IAMASK; /* extend? 15b ia */ +if (memm) /* extend? 15b ia */ + *ea = t & IAMASK; else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ return sta; } @@ -1794,8 +1918,10 @@ 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? */ + if (XVM) /* XVM relocation? */ + pa = RelocXVM (ma, REL_R); + else if (RELOC) /* PDP-15 relocation? */ + pa = Reloc15 (ma, REL_R); else pa = Prot15 (ma, cyc == FE); /* PDP-15 prot, fetch only */ if (pa < 0) { /* error? */ *dat = 0; @@ -1803,7 +1929,8 @@ if (usmd) { /* user mode? */ } } else pa = ma & AMASK; /* no prot or reloc */ -if (MEM_ADDR_OK (pa)) *dat = M[pa] & DMASK; /* valid mem? ok */ +if (MEM_ADDR_OK (pa)) /* valid mem? ok */ + *dat = M[pa] & DMASK; else { nexm = 1; /* set flag, no trap */ *dat = 0; @@ -1816,13 +1943,17 @@ 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? */ + if (XVM) /* XVM relocation? */ + pa = RelocXVM (ma, REL_W); + else if (RELOC) /* PDP-15 relocation? */ + pa = Reloc15 (ma, REL_W); else pa = Prot15 (ma, cyc != DF); /* PDP-15 prot, !defer */ - if (pa < 0) return MM_ERR; /* error? */ + if (pa < 0) /* error? */ + return MM_ERR; } else pa = ma & AMASK; /* no prot or reloc */ -if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; /* valid mem? ok */ +if (MEM_ADDR_OK (pa)) /* valid mem? ok */ + M[pa] = dat & DMASK; else nexm = 1; /* set flag, no trap */ return MM_OK; } @@ -1852,14 +1983,16 @@ if (rest_pending) { /* restore pending? */ 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 if ((ma & damask & ~07) == 010) /* autoindex? */ + *ea = t & DMASK; else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */ return sta; } t_stat Incr_addr (int32 ma) { -if (memm) return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); +if (memm) + return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK)); } @@ -1867,7 +2000,8 @@ return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK)); int32 Jms_word (int32 t) { -if (usmd && XVM && (MMR & MM_GM)) return PC; +if (usmd && XVM && (MMR & MM_GM)) + return PC; return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | ((t & 1) << 15) | (PC & IAMASK)); } @@ -1896,12 +2030,14 @@ int32 pa; ma = ma & AMASK; /* 17b addressing */ if (ma > (BR | 0377)) { /* boundary viol? */ - if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ + if (rc != REL_C) /* set flag, trap */ + prvn = trap_pending = 1; 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 */ + if (rc != REL_C) /* set flags, trap */ + nexm = prvn = trap_pending = 1; return -1; } return pa; @@ -1917,7 +2053,8 @@ 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? */ +if (MMR & MM_RDIS) /* reloc disabled? */ + pa = ma; else if ((MMR & MM_SH) && /* shared enabled and */ (ma >= g_base[gmode]) && /* >= shared base and */ (ma < (g_base[gmode] + slr_lnt[slr]))) { /* < shared end? */ @@ -1932,13 +2069,15 @@ else if ((MMR & MM_SH) && /* shared enabled and */ } else { if (ma > (BR | 0377)) { /* normal reloc, viol? */ - if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ + if (rc != REL_C) /* set flag, trap */ + prvn = trap_pending = 1; 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 */ + if (rc != REL_C) /* set flags, trap */ + nexm = prvn = trap_pending = 1; return -1; } return pa; @@ -1965,7 +2104,8 @@ memm = memm_init; nexm = prvn = trap_pending = 0; emir_pending = rest_pending = 0; pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1988,13 +2128,18 @@ 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; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & DMASK; return SCPE_OK; } @@ -2004,12 +2149,16 @@ 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; +if (addr >= MEMSIZE) + return SCPE_NXM; M[addr] = val & DMASK; return SCPE_OK; } @@ -2023,11 +2172,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } @@ -2040,14 +2191,19 @@ DIB *dibp; uint32 newdev; t_stat r; -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; +if (cptr == NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; +if ((r != SCPE_OK) || (newdev == dibp->dev)) + return r; dibp->dev = newdev; /* store */ return SCPE_OK; } @@ -2059,13 +2215,17 @@ t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; fprintf (st, "devno=%02o", dibp->dev); -if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); +if (dibp->num > 1) + fprintf (st, "-%2o", dibp->dev + dibp->num - 1); return SCPE_OK; } @@ -2101,15 +2261,16 @@ for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */ 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 */ + if (dibp->iors) /* if IORS, add */ + dev_iors[p++] = dibp->iors; 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); + 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 */ @@ -2128,12 +2289,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -2142,7 +2305,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -2160,14 +2324,17 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ @@ -2206,7 +2373,8 @@ else hst[hst_p].ir1 = word; hst[hst_p].lac = LAC; hst[hst_p].mq = MQ; hst_p = (hst_p + 1); -if (hst_p >= hst_lnt) hst_p = 0; +if (hst_p >= hst_lnt) + hst_p = 0; return; } @@ -2216,12 +2384,13 @@ 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); +for (j = 0; j < API_HLVL+1; j++) + hst[hst_p].ir = (hst[hst_p].ir << HIST_V_LVL) | (int_hwre[j] & HIST_M_LVL); hst[hst_p].ir1 = 0; hst[hst_p].lac = 0; hst[hst_p].mq = lvl; hst_p = (hst_p + 1); -if (hst_p >= hst_lnt) hst_p = 0; +if (hst_p >= hst_lnt) + hst_p = 0; return; } diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h index d4e4e903..83551e54 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c index 7ed60f5b..0ae13f2c 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -136,7 +136,8 @@ int32 drm61 (int32 dev, int32 pulse, int32 AC) int32 t; if (pulse & 001) { /* DRSF */ - if (TST_INT (DRM)) AC = AC | IOT_SKP; + if (TST_INT (DRM)) + AC = AC | IOT_SKP; } if (pulse & 002) { /* DRCF */ CLR_INT (DRM); /* clear done */ @@ -145,7 +146,8 @@ if (pulse & 002) { /* DRCF */ 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? */ + if (t <= 0) /* wrap around? */ + t = t + DRM_NUMWDT; sim_activate (&drm_unit, t * drm_time); /* schedule op */ } return AC; @@ -156,13 +158,15 @@ int32 drm62 (int32 dev, int32 pulse, int32 AC) int32 t; if (pulse & 001) { /* DRSN */ - if (drm_err == 0) AC = AC | IOT_SKP; + 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? */ + if (t <= 0) /* wrap around? */ + t = t + DRM_NUMWDT; sim_activate (&drm_unit, t * drm_time); /* schedule op */ } return AC; @@ -192,10 +196,12 @@ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ M[drm_ma] = fbuf[da]; /* read word */ } else { /* write */ - if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; + 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; + if (da >= uptr->hwmark) + uptr->hwmark = da + 1; } } drm_ma = (drm_ma + 1) & 0177777; /* incr mem addr */ @@ -241,8 +247,10 @@ t_stat drm_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 PC; -if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +if (drm_dib.dev != DEV_DRM) /* non-std addr? */ + return STOP_NONSTD; +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 ac29f014..9b422fec 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -1,6 +1,6 @@ /* pdp18b_dt.c: 18b DECtape simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -210,7 +210,7 @@ #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); \ + SET_INT (DTA); \ else CLR_INT (DTA); #else /* Type 550 */ @@ -234,7 +234,7 @@ #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); \ + SET_INT (DTA); \ else CLR_INT (DTA); #endif @@ -459,14 +459,19 @@ 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 & 01) /* DTCA */ + dtsa = 0; + if (pulse & 02) /* DTRA!... */ + dat = dtsa; if (pulse & 04) { /* DTXA */ - if ((dat & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((dat & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; + 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); + 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? */ @@ -478,10 +483,12 @@ if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ DT_UPDINT; return dat; } -if ((pulse & 067) == 042) return dtsa; /* DTRA */ +if ((pulse & 067) == 042) /* DTRA */ + return dtsa; if ((pulse & 067) == 061) /* DTEF */ return ((dtsb & DTB_ERF)? IOT_SKP + dat: dat); -if ((pulse & 067) == 062) return dtsb; /* DTRB */ +if ((pulse & 067) == 062) /* DTRB */ + return dtsb; if ((pulse & 067) == 063) /* DTEF!DTRB */ return ((dtsb & DTB_ERF)? IOT_SKP + dtsb: dtsb); return dat; @@ -519,21 +526,24 @@ 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 (unum >= 0) /* get unit */ + uptr = dt_dev.units + unum; 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_DIR) /* rev? set */ + dtsb = dtsb | DTB_REV; 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? */ + if ((dtsa ^ dat) & DTA_UNIT) /* new unit? */ + dt_deselect (dtsa); dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } @@ -562,7 +572,8 @@ int32 old_unit, old_mot; UNIT *uptr; old_unit = DTA_GETUNIT (oldf); /* get unit no */ -if (old_unit < 0) return; /* invalid? */ +if (old_unit < 0) /* invalid? */ + return; uptr = dt_dev.units + old_unit; /* get unit */ old_mot = DTS_GETMOT (uptr->STATE); if (old_mot >= DTS_ATSF) /* at speed? */ @@ -600,7 +611,8 @@ int32 prev_mving, new_mving, prev_dir, new_dir; UNIT *uptr; new_unit = DTA_GETUNIT (newf); /* new unit */ -if (new_unit < 0) return; /* invalid? */ +if (new_unit < 0) /* invalid? */ + return; uptr = dt_dev.units + new_unit; if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ dt_seterr (uptr, DTB_SEL); /* no, error */ @@ -613,10 +625,12 @@ 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) /* stop to stop */ + return; if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -626,7 +640,8 @@ if (new_mving & ~prev_mving) { /* start? */ if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -636,7 +651,8 @@ if (prev_mving & ~new_mving) { /* stop? */ if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -647,7 +663,8 @@ if (prev_dir ^ new_dir) { /* dir chg? */ } if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* cancel cur */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -685,7 +702,8 @@ int32 relpos; uint32 oldpos; oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ +if (dt_setpos (uptr)) /* update pos */ + return; uptr->STATE = newsta; /* update state */ fnc = DTS_GETFNC (uptr->STATE); /* set variables */ dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; @@ -703,30 +721,35 @@ dt_substate = DTO_SOB; /* substate = block star switch (fnc) { /* case function */ case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ + if (dir) /* rev? < start */ + newpos = -1000; 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")); + 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)? + 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")); + 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; + if (dir) + newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); break; } @@ -736,8 +759,9 @@ switch (fnc) { /* case function */ 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; + 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; @@ -746,18 +770,20 @@ switch (fnc) { /* case function */ 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; + 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 (!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]": " ")); + unum, blk, (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": " ")); break; default: @@ -802,7 +828,8 @@ 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 */ +if (ut == 0) /* no time gone? exit */ + return FALSE; uptr->LASTT = new_time; /* update last time */ switch (mot & ~DTS_DIR) { /* case on motion */ @@ -827,7 +854,8 @@ switch (mot & ~DTS_DIR) { /* case on motion */ break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ +if (mot & DTS_DIR) /* update pos */ + uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { @@ -924,7 +952,8 @@ switch (fnc) { /* at speed, check fnc * 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 (MEM_ADDR_OK (ma)) /* store block # */ + M[ma] = blk; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ if (DEBUG_PRI (dt_dev, LOG_MS)) @@ -956,8 +985,8 @@ switch (fnc) { /* at speed, check fnc * 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": " ")); + 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 */ @@ -965,9 +994,12 @@ switch (fnc) { /* at speed, check fnc * 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? */ + if (dir) /* rev? comp obv */ + dtdb = dt_comobv (dtdb); + if (MEM_ADDR_OK (ma)) /* mem addr legal? */ + M[ma] = dtdb; + if (M[DT_WC] == 0) /* wc ovf? */ + dt_substate = DTO_WCO; case DTO_WCO: /* wc ovf, not sob */ if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -1011,8 +1043,8 @@ switch (fnc) { /* at speed, check fnc * 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": " ")); + (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 */ @@ -1021,10 +1053,13 @@ switch (fnc) { /* at speed, check fnc * 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 */ + if (dir) /* rev? comp obv */ + dtdb = dt_comobv (dtdb); fbuf[ba] = dtdb; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (M[DT_WC] == 0) dt_substate = DTO_WCO; + 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 { @@ -1066,10 +1101,13 @@ switch (fnc) { /* at speed, check fnc * dtdb = fbuf[ba]; /* get tape word */ } else dtdb = dt_gethdr (uptr, blk, relpos); /* get hdr */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ + if (dir) /* rev? comp obv */ + dtdb = dt_comobv (dtdb); 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 (MEM_ADDR_OK (ma)) /* mem addr legal? */ + M[ma] = dtdb; + 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; @@ -1101,15 +1139,18 @@ switch (fnc) { /* at speed, check fnc * 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); + 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; + 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 (M[DT_WC] == 0) + dt_substate = DTO_WCO; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ break; @@ -1161,13 +1202,15 @@ switch (fnc) { /* at speed, check fnc * #endif if ((fnc == FNC_READ) && /* read, skip if not */ (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; + (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); + if (dir) + dtdb = dt_comobv (dtdb); break; /* Write and write all */ @@ -1183,9 +1226,11 @@ switch (fnc) { /* at speed, check fnc * (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 */ + if (dir) /* get data word */ + fbuf[ba] = dt_comobv (dtdb); else fbuf[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + 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 */ @@ -1225,7 +1270,8 @@ 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 */ + if (dt_setpos (uptr)) /* update position */ + return; sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); /* state = decel */ } @@ -1239,7 +1285,8 @@ void dt_schedez (UNIT *uptr, int32 dir) { int32 newpos; -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ +if (dir) /* rev? rev ez */ + newpos = DT_EZLIN - DT_WSIZE; else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); return; @@ -1276,7 +1323,8 @@ 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; + if (csum > DMASK) + csum = (csum + 1) & DMASK; } return (csum ^ DMASK); /* 1's comp res */ #endif @@ -1288,13 +1336,16 @@ 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_BLKWD) /* fwd blknum */ + return blk; #if defined (TC02) /* TC02/TC15 */ -if (wrd == DT_CSMWD) return 077; /* rev csum */ +if (wrd == DT_CSMWD) /* rev csum */ + return 077; if (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ return (dt_csum (uptr, blk) << 12); #else /* Type 550 */ -if (wrd == DT_CSMWD) return 0777777; /* rev csum */ +if (wrd == DT_CSMWD) /* rev csum */ + return 0777777; if (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ return (dt_csum (uptr, blk)); #endif @@ -1315,7 +1366,8 @@ for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ 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 */ + if (dt_setpos (uptr)) /* update pos */ + continue; sim_cancel (uptr); sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); @@ -1361,7 +1413,8 @@ int32 u = uptr - dt_dev.units; t_stat r; r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ +if (r != SCPE_OK) /* error? */ + return r; if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */ if (sim_switches & SWMASK ('T')) /* att 12b? */ @@ -1384,15 +1437,19 @@ if (uptr->filebuf == NULL) { /* can't alloc? */ } 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"); +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 (uint16), D8_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0; + 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); @@ -1406,8 +1463,10 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */ 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; + if (k == 0) + break; + for ( ; k < D18_BSIZE; k++) + pdp11b[k] = 0; for (k = 0; k < D18_BSIZE; k++) fbuf[ba++] = pdp11b[k]; } @@ -1437,7 +1496,8 @@ uint16 pdp11b[D18_BSIZE]; uint32 ba, k, *fbuf; int32 u = uptr - dt_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +if (!(uptr->flags & UNIT_ATT)) + return SCPE_OK; if (sim_is_active (uptr)) { sim_cancel (uptr); if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { @@ -1460,7 +1520,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ ba = ba + 2; } /* end loop blk */ fxwrite (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; + if (ferror (uptr->fileref)) + break; } /* end loop file */ } /* end if 12b */ else if (uptr->flags & UNIT_11FMT) { /* 16b? */ @@ -1468,12 +1529,14 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ 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; + 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"); + 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 */ diff --git a/PDP18B/pdp18b_fpp.c b/PDP18B/pdp18b_fpp.c index c5749908..becbbe24 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-2006, Robert M Supnik + Copyright (c) 2003-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -231,12 +231,14 @@ if (fpp_dev.flags & DEV_DIS) /* disabled? */ 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 */ +if (Read (ma, &ar, RD)) /* error? MM exc */ + return fp15_exc (FP_MM); 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); + if (Read (ma, &ar, RD)) + return fp15_exc (FP_MM); } fma.exp = SEXT18 (fma.exp); /* sext exponents */ fmb.exp = SEXT18 (fmb.exp); @@ -246,7 +248,8 @@ switch (fop) { /* case on subop */ break; case FOP_SUB: /* subtract */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ + if (sta = fp15_opnd (fir, ar, &fmb)) /* fetch op to FMB */ + break; 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 */ @@ -254,20 +257,24 @@ switch (fop) { /* case on subop */ case FOP_RSUB: /* reverse sub */ fmb = fma; /* FMB <- FMA */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + if (sta = fp15_opnd (fir, ar, &fma)) /* fetch op to FMA */ + break; 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 (sta = fp15_opnd (fir, ar, &fmb)) /* fetch op to FMB */ + break; 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)) /* fetch op to FMB */ + break; 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 */ @@ -276,14 +283,16 @@ switch (fop) { /* case on subop */ case FOP_RDIV: /* reverse divide */ fmb = fma; /* FMB <- FMA */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + if (sta = fp15_opnd (fir, ar, &fma)) /* fetch op to FMA */ + break; 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 */ + if (sta = fp15_opnd (fir, ar, &fma)) /* fetch op to FMA */ + break; fp15_asign (fir, &fma); /* modify A sign */ if (fir & FI_FP) /* fp? */ sta = fp15_norm (ir, &fma, NULL, 0); /* norm, no round */ @@ -295,19 +304,22 @@ switch (fop) { /* case on subop */ break; case FOP_FLT: /* float */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + if (sta = fp15_opnd (fir, ar, &fma)) /* fetch op to FMA */ + break; 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 */ + if (sta = fp15_opnd (fir, ar, &fma)) /* fetch op to FMA */ + break; sta = fp15_fix (fir, &fma); /* fix */ break; case FOP_LFMQ: /* load FMQ */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + if (sta = fp15_opnd (fir, ar, &fma)) /* fetch op to FMA */ + break; dp_swap (&fma, &fmq); /* swap FMA, FMQ */ fp15_asign (fir, &fma); /* adjust A sign */ if (fir & FI_FP) /* fp? */ @@ -320,14 +332,16 @@ switch (fop) { /* case on subop */ sta = Write (ar, dat, WR); } else { /* no, load */ - if (sta = Read (ar, &dat, RD)) break; + 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 (sta = fp15_opnd (fir, ar, &fmb)) /* fetch op to FMB */ + break; 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 */ @@ -361,12 +375,16 @@ 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 */ +if (ir & FI_NOLOAD) /* no load? */ + return FP_OK; +if (ir & FI_FP) /* fp? at least 2 */ + numwd = 2; else numwd = 1; /* else at least 1 */ -if (ir & FI_DP) numwd = numwd + 1; /* dp? 1 more */ +if (ir & FI_DP) /* dp? 1 more */ + numwd = numwd + 1; for (i = 0; i < numwd; i++) { /* fetch words */ - if (Read (addr, &wd[i], RD)) return FP_MM; + if (Read (addr, &wd[i], RD)) + return FP_MM; addr = (addr + 1) & AMASK; } if (ir & FI_FP) { /* fp? */ @@ -406,7 +424,8 @@ t_stat sta; fguard = 0; /* clear guard */ if (ir & FI_FP) { /* fp? */ - if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */ + if (sta = fp15_norm (ir, a, NULL, 0)) /* normalize */ + return sta; if (ir & FI_DP) { /* dp? */ wd[0] = a->exp & DMASK; /* exponent */ wd[1] = (a->sign << 17) | a->hi; /* hi frac */ @@ -422,8 +441,10 @@ if (ir & FI_FP) { /* fp? */ a->exp = a->exp + 1; } } - if (a->exp > 0377) return FP_OVF; /* sp ovf? */ - if (a->exp < -0400) return FP_UNF; /* sp unf? */ + if (a->exp > 0377) /* sp ovf? */ + return FP_OVF; + if (a->exp < -0400) /* sp unf? */ + return FP_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 */ @@ -444,14 +465,17 @@ else { 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 */ + if (a->hi || (a->lo & SIGN)) /* check int ovf */ + return FP_OVF; + if (a->sign) /* neg? store FMB */ + wd[0] = fmb.lo; 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; + if (Write (addr, wd[i], WR)) + return FP_MM; addr = (addr + 1) & AMASK; } return FP_OK; @@ -464,7 +488,8 @@ return FP_OK; 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? */ +if (a->sign ^ b->sign ^ sub) /* eff subtract? */ + dp_sub (a, b); else { dp_add (a, b); /* no, add */ if (a->hi & UFP_FH_CARRY) { /* carry out? */ @@ -483,7 +508,8 @@ 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 */ +if (fmq.hi | fmq.lo) /* FMQ != 0? ovf */ + return FP_OVF; fp15_asign (ir, a); /* adjust A sign */ return FP_OK; } @@ -507,8 +533,10 @@ 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? */ +if ((b->hi | b->lo) == 0) /* div by 0? */ + return FP_DIV; +if ((a->hi | a->lo) == 0) /* div into 0? */ + return FP_OK; 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 */ @@ -527,7 +555,8 @@ 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? */ + if (i == 0) /* first step? */ + a->exp = a->exp + 1; fmq.lo = fmq.lo | 1; /* set quo bit */ } dp_lsh_1 (a, NULL); /* left shift divd */ @@ -555,12 +584,14 @@ if (((a->hi | a->lo) == 0) || (ediff < -35)) { /* a = 0 or "small"? */ 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 */ + if (ediff > 0) /* |a| > |b|? dnorm b */ + dp_dnrm_r (ir, b, ediff); 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? */ + if (a->sign ^ b->sign ^ sub) /* eff sub? */ + dp_sub (a, b); else { /* eff add */ dp_add (a, b); /* add */ if (a->hi & UFP_FH_CARRY) { /* carry out? */ @@ -596,14 +627,16 @@ 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 (!(b->hi & UFP_FH_NORM)) /* divr not norm? */ + return FP_DIV; 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; + if (i == 0) + a->exp = a->exp + 1; fmq.lo = fmq.lo | 1; /* set quo bit */ } dp_lsh_1 (a, NULL); /* left shift divd */ @@ -622,14 +655,17 @@ 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 */ +if (a->exp > 35) /* exp > 35? ovf */ + return FP_OVF; +if (a->exp < 0) /* exp <0 ? rslt 0 */ + a->hi = a->lo = 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 */ + if (!(ir & FI_NORND)) /* round */ + dp_inc (a); } } fp15_asign (ir, a); /* adjust A sign */ @@ -676,10 +712,14 @@ return; int32 dp_cmp (UFP *a, UFP *b) { -if (a->hi < b->hi) return -1; -if (a->hi > b->hi) return +1; -if (a->lo < b->lo) return -1; -if (a->lo > b->lo) return +1; +if (a->hi < b->hi) + return -1; +if (a->hi > b->hi) + return +1; +if (a->lo < b->lo) + return -1; +if (a->lo > b->lo) + return +1; return 0; } @@ -692,13 +732,15 @@ int32 i; fmq.hi = a->hi; /* FMQ <- a */ fmq.lo = a->lo; a->hi = a->lo = 0; /* a <- 0 */ -if ((fmq.hi | fmq.lo) == 0) return; +if ((fmq.hi | fmq.lo) == 0) + return; if ((b->hi | b->lo) == 0) { fmq.hi = fmq.lo = 0; return; } for (i = 0; i < 35; i++) { /* 35 iterations */ - if (fmq.lo & 1) dp_add (a, b); /* FMQ<35>? a += b */ + if (fmq.lo & 1) /* FMQ<35>? a += b */ + dp_add (a, b); dp_rsh_1 (a, &fmq); /* rsh a'FMQ */ } return; @@ -738,8 +780,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 (sc <= 0) /* legit? */ + return; +for (i = 0; i < sc; i++) /* dnorm to fmq */ + dp_rsh_1 (a, &fmq); if (!(ir & FI_NORND) && (fmq.hi & UFP_FH_NORM)) /* round & fmq<1>? */ dp_inc (a); /* incr a */ return; @@ -820,8 +864,10 @@ if (rnd && b && (b->hi & UFP_FH_NORM)) { /* rounding? */ } } } -if (a->exp > (int32) 0377777) return FP_OVF; /* overflow? */ -if (a->exp < (int32) -0400000) return FP_UNF; /* underflow? */ +if (a->exp > (int32) 0377777) /* overflow? */ + return FP_OVF; +if (a->exp < (int32) -0400000) /* underflow? */ + return FP_UNF; return FP_OK; } @@ -831,12 +877,14 @@ t_stat fp15_exc (t_stat sta) { int32 ma, mb; -if (sta == FP_MM) trap_pending = 0; /* if mm, kill trap */ +if (sta == FP_MM) /* if mm, kill trap */ + trap_pending = 0; 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 */ +if (Write (ma, mb, WR)) /* store */ + return SCPE_OK; PC = (ma + 1) & IAMASK; /* new PC */ return SCPE_OK; } diff --git a/PDP18B/pdp18b_lp.c b/PDP18B/pdp18b_lp.c index 411b3c12..e04698c3 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -134,10 +134,12 @@ 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)) /* LPSF */ + dat = IOT_SKP | dat; if (pulse & 02) { int32 sb = pulse & 060; /* subopcode */ - if (sb == 000) CLR_INT (LPT); /* LPCF */ + if (sb == 000) /* LPCF */ + CLR_INT (LPT); if ((sb == 040) && (lp62_bp < BPTR_MAX)) { /* LPLD */ i = lp62_bp * 3; /* cvt to chr ptr */ lp62_buf[i] = fio_to_asc[(dat >> 12) & 077]; @@ -157,7 +159,8 @@ 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 & 02) /* LSCF */ + CLR_INT (LPTSPC); if (pulse & 04) { /* LSPR */ lp62_spc = 020 | (dat & 07); /* space */ sim_activate (&lp62_unit, lp62_unit.wait); /* activate */ @@ -192,7 +195,8 @@ 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? */ + if (lp62_ovrpr) /* overprint? */ + fputc ('\r', uptr->fileref); fputs (lp62_buf, uptr->fileref); /* print buffer */ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* test error */ @@ -201,7 +205,8 @@ else { return SCPE_IOERR; } lp62_bp = 0; - for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ + for (i = 0; i <= LP62_BSIZE; i++) /* clear buffer */ + lp62_buf[i] = 0; lp62_ovrpr = 1; /* set overprint */ } return SCPE_OK; @@ -217,7 +222,8 @@ 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 */ +for (i = 0; i <= LP62_BSIZE; i++) /* clear buffer */ + lp62_buf[i] = 0; lp62_spc = 0; /* clear state */ lp62_ovrpr = 0; /* clear overprint */ return SCPE_OK; @@ -317,15 +323,18 @@ 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 & 01) && lp647_don) /* LPSF */ + dat = IOT_SKP | dat; 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; + 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 (lp647_ie) /* set int */ + SET_INT (LPT); } } if (pulse & 004) { /* LPDI */ @@ -356,7 +365,8 @@ if (pulse & 004) { /* LPDI */ lp647_bp = lp647_bp + 1; } lp647_don = 1; /* set done */ - if (lp647_ie) SET_INT (LPT); /* set int */ + if (lp647_ie) /* set int */ + SET_INT (LPT); break; } /* end case */ } @@ -365,7 +375,8 @@ return dat; int32 lp647_66 (int32 dev, int32 pulse, int32 dat) { -if ((pulse & 01) && lp647_err) dat = IOT_SKP | dat; /* LPSE */ +if ((pulse & 01) && lp647_err) /* LPSE */ + dat = IOT_SKP | dat; if (pulse & 02) { /* LPCF */ lp647_don = 0; /* clear done, int */ CLR_INT (LPT); @@ -378,7 +389,8 @@ if (pulse & 04) { #if defined (PDP9) else { /* LPEI */ lp647_ie = 1; /* set int enable */ - if (lp647_don) SET_INT (LPT); + if (lp647_don) + SET_INT (LPT); } #endif } @@ -398,7 +410,8 @@ int32 i; char pbuf[LP647_BSIZE + 2]; lp647_don = 1; -if (lp647_ie) SET_INT (LPT); /* set flag */ +if (lp647_ie) /* set flag */ + SET_INT (LPT); if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ lp647_err = 1; /* set error */ return IORETURN (lp647_stopioe, SCPE_UNATT); @@ -406,9 +419,11 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ 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'; + if ((lp647_iot & 060) == 0) + pbuf[lp647_bp++] = '\r'; pbuf[lp647_bp++] = 0; /* append nul */ - for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; /* clear buffer */ + for (i = 0; i < LP647_BSIZE; i++) /* clear buffer */ + lp647_buf[i] = 0; fputs (pbuf, uptr->fileref); /* print buffer */ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* error? */ @@ -444,7 +459,8 @@ 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 */ +for (i = 0; i < LP647_BSIZE; i++) /* clear buffer */ + lp647_buf[i] = 0; return SCPE_OK; } @@ -541,8 +557,10 @@ int32 lp09_66 (int32 dev, int32 pulse, int32 dat) int32 sb = pulse & 060; /* subopcode */ if (pulse & 001) { - if ((sb == 000) && lp09_don) dat = IOT_SKP | dat; /* LSDF */ - if ((sb == 020) && lp09_err) dat = IOT_SKP | dat; /* LSEF */ + if ((sb == 000) && lp09_don) /* LSDF */ + dat = IOT_SKP | dat; + if ((sb == 020) && lp09_err) /* LSEF */ + dat = IOT_SKP | dat; } if (pulse & 002) { if (sb == 000) { /* LSCF */ @@ -566,7 +584,8 @@ if (pulse & 004) { } else if (sb == 040) { /* LION */ lp09_ie = 1; /* set int enab */ - if (lp09_don) SET_INT (LPT); /* if done, set int */ + if (lp09_don) /* if done, set int */ + SET_INT (LPT); } } return dat; @@ -579,13 +598,15 @@ t_stat lp09_svc (UNIT *uptr) int32 c; lp09_don = 1; /* set done */ -if (lp09_ie) SET_INT (LPT); /* int enb? req int */ +if (lp09_ie) /* int enb? req int */ + SET_INT (LPT); 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 ((c == 0) || (c == 0177)) /* skip NULL, DEL */ + return SCPE_OK; fputc (c, uptr->fileref); /* print char */ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* error? */ @@ -730,23 +751,30 @@ if (pulse & 01) { 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 */ + if (sb == 040) /* line count */ + lp15_lc = 1; else lp15_lc = (header >> 9) & 0377; - if (lp15_lc == 0) lp15_lc = 256; + if (lp15_lc == 0) + lp15_lc = 256; lp15_bp = 0; /* reset buf ptr */ } - else if (sb == 060) lp15_ie = 0; /* LPDI */ + else if (sb == 060) /* LPDI */ + lp15_ie = 0; } -if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */ -if ((pulse & 04) && (sb == 040)) lp15_ie = 1; /* LPEI */ +if ((pulse & 02) && (sb == 040)) /* LPOS, LPRS */ + dat = dat | lp15_updsta (0); +if ((pulse & 04) && (sb == 040)) /* LPEI */ + lp15_ie = 1; 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 */ +if (pulse == 021) /* LPCD */ + lp15_sta = lp15_sta & ~STA_DON; +if (pulse == 041) /* LPCF */ + lp15_sta = 0; lp15_updsta (0); /* update status */ return dat; } @@ -805,14 +833,16 @@ for (more = 1; more != 0; ) { /* loop until ctrl */ lp15_bp = more = 0; } else { - if (lp15_bp < LP15_BSIZE) lp15_buf[lp15_bp++] = c[i]; + 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? */ +if (lp15_lc) /* more to do? */ + sim_activate (&lp15_unit, uptr->wait); else lp15_updsta (STA_DON); /* no, set done */ return SCPE_OK; } @@ -822,9 +852,12 @@ return SCPE_OK; int32 lp15_updsta (int32 new) { lp15_sta = (lp15_sta | new) & ~(STA_CLR | STA_ERR | STA_BUSY); -if (lp15_sta & STA_EFLGS) lp15_sta = lp15_sta | STA_ERR; /* update errors */ -if (sim_is_active (&lp15_unit)) lp15_sta = lp15_sta | STA_BUSY; -if (lp15_ie && (lp15_sta & STA_DON)) SET_INT (LPT); +if (lp15_sta & STA_EFLGS) /* update errors */ + lp15_sta = lp15_sta | STA_ERR; +if (sim_is_active (&lp15_unit)) + lp15_sta = lp15_sta | STA_BUSY; +if (lp15_ie && (lp15_sta & STA_DON)) + SET_INT (LPT); else CLR_INT (LPT); /* update int */ return lp15_sta; } diff --git a/PDP18B/pdp18b_mt.c b/PDP18B/pdp18b_mt.c index 073c48ee..22d190cf 100644 --- a/PDP18B/pdp18b_mt.c +++ b/PDP18B/pdp18b_mt.c @@ -1,6 +1,6 @@ /* pdp18b_mt.c: 18b PDP magnetic tape simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ mt (PDP-9) TC59 magtape (PDP-15) TC59D magtape + 14-Nov-08 RMS Replaced mt_log with standard debug facility 16-Feb-06 RMS Added tape capacity checking 16-Aug-05 RMS Fixed C++ declaration and cast problems 18-Mar-05 RMS Added attached test to detach routine @@ -126,12 +127,12 @@ extern int32 M[]; extern int32 int_hwre[API_HLVL+1]; extern UNIT cpu_unit; +extern FILE *sim_deb; int32 mt_cu = 0; /* command/unit */ int32 mt_sta = 0; /* status register */ int32 mt_time = 10; /* record latency */ int32 mt_stopioe = 1; /* stop on error */ -int32 mt_log = 0; uint8 *mtxb = NULL; /* transfer buffer */ DEVICE mt_dev; @@ -177,7 +178,6 @@ REG mt_reg[] = { { 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 } }; @@ -199,7 +199,7 @@ DEVICE mt_dev = { MT_NUMDR, 10, 31, 1, 8, 8, NULL, NULL, &mt_reset, NULL, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE + &mt_dib, DEV_DISABLE | DEV_DEBUG }; /* IOT routine */ @@ -221,13 +221,15 @@ if (pulse & 01) { else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */ dat = IOT_SKP | dat; } -if ((pulse & 06) && mt_log) - printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n", - GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta); +if ((pulse & 06) && DEBUG_PRS (mt_dev)) + fprintf (sim_deb, "[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 */ + if (sb == 000) /* MTRC */ + dat = dat | (mt_cu & 0777700); else if (sb == 020) { /* MTAF, MTLC */ - if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */ + if (!mt_busy ()) /* if not busy, clr */ + mt_cu = mt_sta = 0; mt_sta = mt_sta & ~(STA_ERR | STA_DON); /* clear flags */ } else if (sb == 040) dat = dat | mt_sta; /* MTRS */ @@ -243,7 +245,8 @@ if (pulse & 04) { ((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? */ + if (f == FN_REWIND) /* rewind? */ + uptr->USTAT = STA_REW; else mt_sta = uptr->USTAT = 0; /* no, clear status */ sim_activate (uptr, mt_time); /* start io */ } @@ -275,10 +278,13 @@ 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; + 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); + if (u == GET_UNIT (mt_cu)) + mt_updcsta (uptr, STA_DON); + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, "[MT%d: rewind complete, sta=%o]\n", u, mt_sta); return SCPE_OK; } @@ -293,14 +299,16 @@ 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? */ + if (st == MTSE_RECE) /* rec in err? */ + mt_sta = mt_sta | STA_PAR | STA_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) /* wrong size? */ + mt_sta = mt_sta | STA_RLE | STA_ERR; if (tbc < cbc) { /* record small? */ cbc = tbc; /* use smaller */ wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); @@ -320,7 +328,8 @@ switch (f) { /* case on function */ c2 = mtxb[p++]; c = (c1 << 8) | c2; } - if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; + 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); @@ -384,8 +393,9 @@ switch (f) { /* case on function */ if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */ uptr->USTAT = uptr->USTAT | STA_EOT; 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); +if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, "MT%d: fnc=%d done, ma=%o, wc=%o, sta=%o]\n", + u, f, M[MT_CA], M[MT_WC], mt_sta); return r; } @@ -393,8 +403,7 @@ return r; int32 mt_updcsta (UNIT *uptr, int32 news) { -mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | - (uptr->USTAT & STA_DYN) | news; +mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN) | news; if ((mt_sta & (STA_ERR | STA_DON)) && (mt_cu & CU_IE)) SET_INT (MTA); else CLR_INT (MTA); /* int request */ @@ -435,7 +444,8 @@ switch (st) { case MTSE_IOERR: /* IO error */ mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - if (mt_stopioe) return SCPE_IOERR; + if (mt_stopioe) + return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ @@ -475,12 +485,15 @@ 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; + 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; +if (mtxb == NULL) + mtxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); +if (mtxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -498,7 +511,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr) t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->USTAT = STA_BOT; mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ return r; @@ -508,8 +522,10 @@ return r; t_stat mt_detach (UNIT* uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -if (!sim_is_active (uptr)) uptr->USTAT = 0; +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; +if (!sim_is_active (uptr)) + uptr->USTAT = 0; mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ return sim_tape_detach (uptr); } diff --git a/PDP18B/pdp18b_rb.c b/PDP18B/pdp18b_rb.c index af0725a1..1079fe8c 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-2005, Robert M Supnik + Copyright (c) 2003-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -147,27 +147,34 @@ 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 == 000) /* DBCF */ + rb_sta = rb_sta & ~(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 == 040) /* DBCS */ + rb_sta = 0; } 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) /* DBRD */ + AC = AC | rb_make_da (rb_da); + if (sb == 020) /* DBRS */ + AC = AC | rb_sta; + if (sb == 040) /* DBLM */ + rb_ma = AC & AMASK; } 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 == 000) /* DBLD */ + rb_da = rb_set_da (AC, rb_da); + if (sb == 020) /* DBLW */ + rb_wc = AC & 0177777; 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); + if (t < 0) + t = t + (RB_NUMSC * RB_NUMWD); sim_activate (&rb_unit, t * rb_time); } } @@ -220,7 +227,8 @@ 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? */ + if (d >= 10) /* invalid? */ + return -1; r = r + (d * i); /* insert bin */ i = i * 10; } @@ -248,8 +256,9 @@ do { break; } else { /* not locked */ - fbuf[rb_da] = M[rb_ma]; /* write word */ - if (((t_addr) rb_da) >= uptr->hwmark) uptr->hwmark = rb_da + 1; + 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? */ @@ -257,7 +266,8 @@ do { 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? */ + if (rb_da > RB_SIZE) /* disk wraparound? */ + rb_da = 0; } while ((rb_wc != 0) && (rb_burst != 0)); /* brk if wc, no brst */ if ((rb_wc != 0) && ((rb_sta & RBS_ERR) == 0)) /* more to do? */ @@ -271,8 +281,10 @@ 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 */ +if (rb_sta & RBS_EFLGS) /* error? */ + rb_sta = rb_sta | RBS_ERR; +if (rb_sta & RBS_DON) /* done? clear busy */ + rb_sta = rb_sta & ~RBS_BSY; if ((rb_sta & (RBS_ERR | RBS_DON)) && (rb_sta & RBS_IE)) SET_INT (RB); /* set or clr intr */ else CLR_INT (RB); diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c index 51655485..65a90383 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -191,15 +191,19 @@ sb = pulse & 060; /* subopcode */ if (pulse & 01) { if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON))) /* DSSF */ dat = IOT_SKP | dat; - else if (sb == 020) rf_reset (&rf_dev); /* DSCC */ + else if (sb == 020) /* DSCC */ + rf_reset (&rf_dev); else if (sb == 040) { /* DSCF */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ + if (RF_BUSY) /* busy inhibits */ + rf_sta = rf_sta | RFS_PGE; 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 */ + if (RF_BUSY) /* busy sets PGE */ + rf_sta = rf_sta | RFS_PGE; + else if (sb == 000) /* DRBR */ + dat = dat | rf_dbuf; else if (sb == 020) /* DRAL */ dat = dat | (rf_da & DMASK); else if (sb == 040) /* DSFX */ @@ -208,15 +212,18 @@ if (pulse & 02) { 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 */ + if (RF_BUSY) /* busy sets PGE */ + rf_sta = rf_sta | RFS_PGE; + else if (sb == 000) /* DLBR */ + rf_dbuf = dat & DMASK; 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? */ + if (t < 0) /* wrap around? */ + t = t + RF_NUMWD; sim_activate (&rf_unit, t * rf_time); /* schedule op */ } } @@ -235,15 +242,18 @@ 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); + if (sb == 000) /* DLOK */ + dat = dat | GET_POS (rf_time) | + (sim_is_active (&rf_unit)? 0400000: 0); else if (sb == 040) { /* DSCD */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ + if (RF_BUSY) /* busy inhibits */ + rf_sta = rf_sta | RFS_PGE; else rf_sta = rf_sta & RFS_FR; rf_updsta (0); } else if (sb == 060) { /* DSRS */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ + if (RF_BUSY) /* busy sets PGE */ + rf_sta = rf_sta | RFS_PGE; dat = dat | rf_updsta (0); } } @@ -285,7 +295,8 @@ do { } else { /* not locked */ fbuf[rf_da] = M[pa]; /* write word */ - if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; + if (((uint32) rf_da) >= uptr->hwmark) + uptr->hwmark = rf_da + 1; } } rf_da = rf_da + 1; /* incr disk addr */ @@ -302,7 +313,8 @@ return SCPE_OK; 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_EFLGS) + rf_sta = rf_sta | RFS_ERR; if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE)) SET_INT (RF); else CLR_INT (RF); @@ -335,7 +347,8 @@ uint32 ds_bytes = RF_DKSIZE * sizeof (int32); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; + if (p >= RF_NUMDK) + p = RF_NUMDK - 1; uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); } @@ -347,8 +360,10 @@ return attach_unit (uptr, cptr); t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (val < 0) + return SCPE_IERR; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * RF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; diff --git a/PDP18B/pdp18b_rp.c b/PDP18B/pdp18b_rp.c index b6df6151..e6cf8a75 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -225,8 +225,10 @@ if (pulse & 01) { 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) /* DPOSA */ + dat = dat | rp_sta; + else if (sb == 020) /* DPOSB */ + dat = dat | rp_stb; } if (pulse & 04) { if (rp_busy) { /* busy? */ @@ -235,9 +237,12 @@ if (pulse & 04) { } 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); + 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); @@ -245,8 +250,10 @@ if (pulse & 04) { 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 */ + else if (sb == 040) /* DPCA */ + rp_ma = dat & DMASK; + else if (sb == 060) /* DPWC */ + rp_wc = dat & DMASK; } return dat; } @@ -260,14 +267,18 @@ UNIT *uptr; sb = pulse & 060; if (pulse & 01) { - if (sb == 020) dat = IOT_SKP | dat; /* DPSN */ + if (sb == 020) /* DPSN */ + dat = IOT_SKP | dat; } if (pulse & 02) { if (sb == 000) /* DPOU */ dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; - 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 */ + else if (sb == 020) /* DPOA */ + dat = dat | rp_da; + else if (sb == 040) /* DPOC */ + dat = dat | rp_ma; + else if (sb == 060) /* DPOW */ + dat = dat | rp_wc; } if (pulse & 04) { if (rp_busy) { /* busy? */ @@ -356,9 +367,12 @@ if ((f == FN_WRITE) && (uptr->flags & UNIT_WPRT)) { /* write locked? */ 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 (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; @@ -380,7 +394,8 @@ 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; + for ( ; awc < wc; awc++) + M[pa + awc] = 0; err = ferror (uptr->fileref); } @@ -396,8 +411,10 @@ if ((f == FN_WRITE) && (err == 0)) { /* write? */ 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); + if (awc == 0) + comp = 0; + if (comp != M[pa + i]) + rp_updsta (0, STB_WCE); } err = ferror (uptr->fileref); } @@ -406,7 +423,8 @@ 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; +if (cyl >= RP_NUMCY) + cyl = RP_NUMCY - 1; surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */ sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */ rp_da = (cyl << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT); @@ -431,17 +449,22 @@ UNIT *uptr; uptr = rp_dev.units + GET_UNIT (rp_sta); rp_sta = (rp_sta & ~(STA_DYN | STA_ERR)) | newa; rp_stb = (rp_stb & ~STB_DYN) | newb; -if (uptr->flags & UNIT_WPRT) rp_sta = rp_sta | STA_SUWP; -if ((uptr->flags & UNIT_ATT) == 0) rp_stb = rp_stb | STB_SUFU | STB_SUNR; +if (uptr->flags & UNIT_WPRT) + rp_sta = rp_sta | STA_SUWP; +if ((uptr->flags & UNIT_ATT) == 0) + rp_stb = rp_stb | STB_SUFU | STB_SUNR; else if (sim_is_active (uptr)) { f = (uptr->FUNC) & STA_M_FUNC; if ((f == FN_SEEK) || (f == FN_RECAL)) rp_stb = rp_stb | STB_SUSU | STB_SUNR; } -else if (uptr->CYL >= RP_NUMCY) rp_sta = rp_sta | STA_SUSI; -if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) rp_sta = rp_sta | STA_ERR; +else if (uptr->CYL >= RP_NUMCY) + rp_sta = rp_sta | STA_SUSI; +if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) + rp_sta = rp_sta | STA_ERR; if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) || - ((rp_stb & STB_ATTN) && (rp_sta & STA_IEA))) SET_INT (RP); + ((rp_stb & STB_ATTN) && (rp_sta & STA_IEA))) + SET_INT (RP); else CLR_INT (RP); return; } diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c index d0521c1d..c93b4cf8 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -406,11 +406,13 @@ DEVICE tto_dev = { int32 clk (int32 dev, int32 pulse, int32 dat) { if (pulse & 001) { /* CLSF */ - if (TST_INT (CLK)) dat = dat | IOT_SKP; + if (TST_INT (CLK)) + dat = dat | IOT_SKP; } if (pulse & 004) { /* CLON/CLOF */ CLR_INT (CLK); /* clear flag */ - if (pulse & 040) clk_state = 1; /* CLON */ + if (pulse & 040) /* CLON */ + clk_state = 1; else clk_state = 0; /* CLOF */ } return dat; @@ -430,7 +432,8 @@ clk_task_upd (FALSE); /* update task timer */ #endif if (clk_state) { /* clock on? */ M[7] = (M[7] + 1) & DMASK; /* incr counter */ - if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */ + if (M[7] == 0) /* ovrflo? set flag */ + SET_INT (CLK); } return SCPE_OK; } @@ -451,13 +454,15 @@ uint32 cur = sim_grtime (); uint32 old = clk_task_timer; double usec10; -if (cur > clk_task_last) delta = cur - clk_task_last; +if (cur > clk_task_last) + delta = cur - clk_task_last; else delta = clk_task_last - cur; usec10 = ((((double) delta) * 100000.0) / (((double) tmxr_poll) * ((double) clk_tps))); iusec10 = (int32) usec10; val = (clk_task_timer + iusec10) & DMASK; -if (clr) clk_task_timer = 0; +if (clr) + clk_task_timer = 0; else clk_task_timer = val; clk_task_last = cur; return ((int32) val); @@ -494,8 +499,10 @@ return SCPE_OK; t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; clk_tps = val; return SCPE_OK; } @@ -526,7 +533,8 @@ return SCPE_OK; int32 ptr (int32 dev, int32 pulse, int32 dat) { if (pulse & 001) { /* RSF */ - if (TST_INT (PTR)) dat = dat | IOT_SKP; + if (TST_INT (PTR)) + dat = dat | IOT_SKP; } if (pulse & 002) { /* RRB, RCF */ CLR_INT (PTR); /* clear flag */ @@ -563,7 +571,8 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ ptr_err = 1; /* set error */ #endif if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); @@ -585,7 +594,8 @@ 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 */ +if (ptr_state == 0) /* if done, set flag */ + SET_INT (PTR); else sim_activate (&ptr_unit, ptr_unit.wait); /* else restart */ ptr_unit.pos = ptr_unit.pos + 1; return SCPE_OK; @@ -626,7 +636,8 @@ t_stat ptr_attach (UNIT *uptr, char *cptr) t_stat reason; reason = attach_unit (uptr, cptr); -if (reason != SCPE_OK) return reason; +if (reason != SCPE_OK) + return reason; ptr_err = 0; /* attach clrs error */ ptr_unit.flags = ptr_unit.flags & ~(UNIT_RASCII|UNIT_KASCII); if (sim_switches & SWMASK ('A')) @@ -655,7 +666,8 @@ int32 word, bits, st, ch; word = st = bits = 0; do { - if ((ch = getc (uptr->fileref)) == EOF) return -1; + if ((ch = getc (uptr->fileref)) == EOF) + return -1; uptr->pos = uptr->pos + 1; if (ch & 0200) { word = (word << 6) | (ch & 077); @@ -663,7 +675,8 @@ do { st++; } } while (st < 3); -if (hi != NULL) *hi = bits; +if (hi != NULL) + *hi = bits; return word; } @@ -672,16 +685,19 @@ 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 ((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; + else if (val == OP_HLT) + return STOP_HALT; break; } - else if (MEM_ADDR_OK (origin)) M[origin++] = val; + else if (MEM_ADDR_OK (origin)) + M[origin++] = val; } return SCPE_FMT; } @@ -840,12 +856,15 @@ extern int32 sim_switches; 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) /* non-std addr? */ + return STOP_NONSTD; +if (MEMSIZE < 8192) /* 4k? */ + mask = 0767777; else mask = 0777777; for (i = 0; i < BOOT_LEN; i++) { wd = boot_rom[i]; - if ((wd >= 0040000) && (wd < 0640000)) wd = wd & mask; + if ((wd >= 0040000) && (wd < 0640000)) + wd = wd & mask; M[(BOOT_START & mask) + i] = wd; } PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask; @@ -868,9 +887,11 @@ return ptr_rim_load (&ptr_unit, ASW); int32 ptp (int32 dev, int32 pulse, int32 dat) { if (pulse & 001) { /* PSF */ - if (TST_INT (PTP)) dat = dat | IOT_SKP; + if (TST_INT (PTP)) + dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (PTP); /* PCF */ +if (pulse & 002) /* PCF */ + CLR_INT (PTP); if (pulse & 004) { /* PSA, PSB, PLS */ CLR_INT (PTP); /* clear flag */ ptp_unit.buf = (pulse & 040)? /* load punch buf */ @@ -933,7 +954,8 @@ t_stat ptp_attach (UNIT *uptr, char *cptr) t_stat reason; reason = attach_unit (uptr, cptr); -if (reason != SCPE_OK) return reason; +if (reason != SCPE_OK) + return reason; ptp_err = 0; ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII; if (sim_switches & SWMASK ('A')) @@ -955,13 +977,15 @@ return detach_unit (uptr); int32 tti (int32 dev, int32 pulse, int32 dat) { if (pulse & 001) { /* KSF */ - if (TST_INT (TTI)) dat = dat | IOT_SKP; + if (TST_INT (TTI)) + dat = dat | IOT_SKP; } if (pulse & 002) { /* KRS/KRB */ CLR_INT (TTI); /* clear flag */ dat = dat | tti_unit.buf & TTI_MASK; /* return buffer */ #if defined (PDP15) - if (pulse & 020) tti_fdpx = 1; /* KRS? */ + if (pulse & 020) /* KRS? */ + tti_fdpx = 1; else tti_fdpx = 0; /* no, KRB */ #endif } @@ -984,9 +1008,11 @@ if (tti_2nd) { /* char waiting? */ tti_2nd = 0; /* not waiting */ } else { - if ((in = sim_poll_kbd ()) < SCPE_KFLAG) return in; + if ((in = sim_poll_kbd ()) < SCPE_KFLAG) + return in; c = asc_to_baud[in & 0177]; /* translate char */ - if (c == 0) return SCPE_OK; /* untranslatable? */ + if (c == 0) /* untranslatable? */ + return SCPE_OK; if ((c & TTI_BOTH) || /* case insensitive? */ (((c & TTI_FIGURES)? 1: 0) == tty_shift)) /* right case? */ uptr->buf = c & TTI_MASK; @@ -1012,9 +1038,11 @@ else { int32 c, out; sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; out = c & 0177; /* mask echo to 7b */ -if (c & SCPE_BREAK) c = 0; /* break? */ +if (c & SCPE_BREAK) /* break? */ + c = 0; else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); if ((uptr->flags & TTUF_HDX) && !tti_fdpx && out && /* half duplex and */ ((out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags) | TTUF_KSR)) >= 0)) { @@ -1054,9 +1082,11 @@ return SCPE_OK; int32 tto (int32 dev, int32 pulse, int32 dat) { if (pulse & 001) { /* TSF */ - if (TST_INT (TTO)) dat = dat | IOT_SKP; + if (TST_INT (TTO)) + dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (TTO); /* clear flag */ +if (pulse & 002) /* clear flag */ + CLR_INT (TTO); if (pulse & 004) { /* load buffer */ sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ tto_unit.buf = dat & TTO_MASK; /* load buffer */ diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c index c68d4004..c843e949 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -195,14 +195,16 @@ int32 word, bits, st, ch; word = st = bits = 0; do { - if ((ch = getc (fileref)) == EOF) return -1; + 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; +if (hi != NULL) + *hi = bits; return word; } @@ -221,20 +223,25 @@ t_stat rim_load_47 (FILE *fileref, char *cptr) { int32 origin, val; -if (*cptr != 0) return SCPE_2MARG; +if (*cptr != 0) + return SCPE_2MARG; origin = 0200; for (;;) { - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + 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; + 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 if (val == OP_HLT) /* HLT? */ + break; else return SCPE_FMT; /* error */ } return SCPE_OK; /* done */ @@ -258,20 +265,25 @@ 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 */ + if (r != SCPE_OK) + return r; + if (*cptr != 0) /* no more */ + return SCPE_ARG; } else origin = 0200; /* default 200 */ for (;;) { /* word loop */ - if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT; + 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; + else if (val != OP_HLT) + return SCPE_FMT; break; } - else if (MEM_ADDR_OK (origin)) M[origin++] = val; + else if (MEM_ADDR_OK (origin)) + M[origin++] = val; } return SCPE_OK; } @@ -294,29 +306,38 @@ t_stat bin_load_915 (FILE *fileref, char *cptr) { int32 i, val, bits, origin, count, cksum; -if (*cptr != 0) return SCPE_2MARG; /* no arguments */ +if (*cptr != 0) /* no arguments */ + return SCPE_2MARG; do { val = getword (fileref, & bits); /* find end RIM */ } while ((val >= 0) && ((bits & 1) == 0)); -if (val < 0) rewind (fileref); /* no RIM? rewind */ +if (val < 0) /* no RIM? rewind */ + rewind (fileref); for (;;) { /* block loop */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + if ((val = getword (fileref, NULL)) < 0) + return SCPE_FMT; if (val & SIGN) { - if (val != DMASK) PC = val & 077777; + if (val != DMASK) + PC = val & 077777; break; } cksum = origin = val; /* save origin */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + 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; + 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; + if ((val = getword (fileref, NULL)) < 0) + return SCPE_FMT; cksum = cksum + val; - if (MEM_ADDR_OK (origin)) M[origin++] = val; + if (MEM_ADDR_OK (origin)) + M[origin++] = val; } - if ((cksum & DMASK) != 0) return SCPE_CSUM; + if ((cksum & DMASK) != 0) + return SCPE_CSUM; } return SCPE_OK; } @@ -327,7 +348,8 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) { extern int32 sim_switches; -if (flag != 0) return SCPE_NOFNC; +if (flag != 0) + return SCPE_NOFNC; if (sim_switches & SWMASK ('S')) /* RIM format? */ return rim_load_47 (fileref, cptr); if (sim_switches & SWMASK ('R')) /* HRI format? */ @@ -339,7 +361,8 @@ if (!(sim_switches & SWMASK ('B')) && /* .rim extension? */ val = getword (fileref, &bits); } while ((val >= 0) && ((bits & 1) == 0)); rewind (fileref); /* rewind file */ - if (val < 0) return rim_load_47 (fileref, cptr); /* eof reached? */ + if (val < 0) /* eof reached? */ + return rim_load_47 (fileref, cptr); return hri_load_7915 (fileref, cptr); /* no, HRI */ } return bin_load_915 (fileref, cptr); /* must be BIN */ @@ -904,7 +927,8 @@ 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; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } @@ -939,7 +963,8 @@ if (sw & SWMASK ('P')) { /* packed ASCII? */ return -1; } #endif -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; /* Instruction decode */ @@ -956,7 +981,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ case I_V_NPI: /* IOT no operand */ fprintf (of, "%s", opcode[i]); /* opcode */ - if (inst & 010) fprintf (of, " +10"); + if (inst & 010) + fprintf (of, " +10"); break; case I_V_IOT: /* IOT or EAE */ @@ -974,7 +1000,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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 && (inst & I_IDX)) + fprintf (of, ",X"); #else disp = inst & B_DAMASK; ma = (addr & (AMASK & ~B_DAMASK)) | disp; @@ -983,7 +1010,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ break; case I_V_OPR: /* operate */ - if (sp = (inst & 03730)) fprintf (of, "%s", opcode[i]); + if (sp = (inst & 03730)) + fprintf (of, "%s", opcode[i]); fprint_opr (of, inst & 014047, I_V_OPR, sp); break; @@ -993,7 +1021,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ case I_V_XR9: /* index with lit */ disp = inst & 0777; - if (disp & 0400) fprintf (of, "%s -%-o", opcode[i], 01000 - disp); + if (disp & 0400) + fprintf (of, "%s -%-o", opcode[i], 01000 - disp); else fprintf (of, "%s %-o", opcode[i], disp); break; @@ -1009,14 +1038,17 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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); + 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); + if (val[1] & SIGN) + fputc ('*', of); fprintf (of, " %-o", val[1] & ~SIGN); return -1; @@ -1074,15 +1106,21 @@ 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; +for (i = 1; (i < 5) && (cptr[i] != 0); i++) { + if (cptr[i] == 0) { + for (j = i + 1; j <= 5; j++) + cptr[j] = 0; + } + } if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = (((t_value) cptr[0] & 077) << 12) | (((t_value) cptr[1] & 077) << 6) | ((t_value) cptr[2] & 077); @@ -1090,7 +1128,8 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ } #if defined (PDP15) if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = (((t_value) cptr[0] & 0177) << 11) | (((t_value) cptr[1] & 0177) << 4) | (((t_value) cptr[2] & 0170) >> 3); @@ -1103,7 +1142,8 @@ if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ 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; +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 */ @@ -1115,7 +1155,8 @@ switch (j) { /* case on class */ 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 (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)); @@ -1124,13 +1165,15 @@ switch (j) { /* case on class */ 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; + 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; + if (memm) + damask = B_DAMASK; else damask = P_DAMASK; cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ #else @@ -1145,8 +1188,10 @@ switch (j) { /* case on class */ #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? */ + if (r != SCPE_OK) + return SCPE_ARG; + if (d <= damask) /* fit in 12/13b? */ + val[0] = val[0] | d; else if (cflag && (((addr ^ d) & epcmask) == 0)) val[0] = val[0] | (d & damask); /* hi bits = ePC? */ else return SCPE_ARG; @@ -1154,7 +1199,8 @@ switch (j) { /* case on class */ if (!memm) { cptr = get_glyph (cptr, gbuf, 0); if (gbuf[0] != 0) { - if (strcmp (gbuf, "X") != 0) return SCPE_ARG; + if (strcmp (gbuf, "X") != 0) + return SCPE_ARG; val[0] = val[0] | I_IDX; } } @@ -1172,14 +1218,18 @@ switch (j) { /* case on class */ (strcmp (opcode[i], gbuf) != 0) ; i++) ; if (opcode[i] != NULL) { k = opc_val[i] & DMASK; - if (((k ^ val[0]) & 0740000) != 0) return SCPE_ARG; + 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; + 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; } } @@ -1188,14 +1238,16 @@ switch (j) { /* case on class */ 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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; sta = -1; break; @@ -1205,6 +1257,7 @@ switch (j) { /* case on class */ break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; return sta; } diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c index a44ae156..300830d5 100644 --- a/PDP18B/pdp18b_tt1.c +++ b/PDP18B/pdp18b_tt1.c @@ -1,6 +1,6 @@ -/* pdp15_ttx.c: PDP-15 additional terminals simulator +/* pdp18b_ttx.c: PDP-9/15 additional terminals simulator - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ ttix,ttox LT15/LT19 terminal input/output + 19-Nov-08 RMS Revised for common TMXR show routines 18-Jun-07 RMS Added UNIT_IDLE flag 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode 22-Nov-05 RMS Revised for new terminal processing routines @@ -79,8 +80,6 @@ t_stat ttx_attach (UNIT *uptr, char *cptr); t_stat ttx_detach (UNIT *uptr); t_stat ttx_reset (DEVICE *dptr); 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 @@ -98,8 +97,6 @@ DIB ttix_dib = { UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_IDLE|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) }, @@ -110,15 +107,16 @@ REG ttix_reg[] = { }; 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, 0, "LINES", "LINES", + &ttx_vlines, &tmxr_show_lines, (void *) &ttx_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &ttx_desc }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &ttx_desc }, + &tmxr_dscln, NULL, (void *) &ttx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &ttx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &ttx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &ttx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &ttx_desc }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno, NULL }, { 0 } @@ -195,9 +193,11 @@ int32 ttix (int32 dev, int32 pulse, int32 dat) { int32 ln = ttx_getln (dev, pulse); /* line # */ -if (ln > ttx_lines) return dat; +if (ln > ttx_lines) + return dat; if (pulse & 001) { /* KSF1 */ - if (ttix_test_done (ln)) dat = dat | IOT_SKP; + if (ttix_test_done (ln)) + dat = dat | IOT_SKP; } if (pulse & 002) { /* KRB1 */ ttix_clr_done (ln); /* clear flag */ @@ -212,15 +212,18 @@ t_stat ttix_svc (UNIT *uptr) { int32 ln, c, temp; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; 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 */ +if (ln >= 0) /* got one? rcv enab */ + ttx_ldsc[ln].rcve = 1; 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? */ + if (temp & SCPE_BREAK) /* break? */ + c = 0; else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags) | TTUF_KSR); ttix_buf[ln] = c; ttix_set_done (ln); @@ -234,7 +237,8 @@ return SCPE_OK; t_bool ttix_test_done (int32 ln) { -if (ttix_done & (1 << ln)) return TRUE; +if (ttix_done & (1 << ln)) + return TRUE; return FALSE; } @@ -248,7 +252,9 @@ return; void ttix_clr_done (int32 ln) { ttix_done = ttix_done & ~(1 << ln); -if (ttix_done) { SET_INT (TTI1); } +if (ttix_done) { + SET_INT (TTI1); + } else { CLR_INT (TTI1); } @@ -261,11 +267,14 @@ int32 ttox (int32 dev, int32 pulse, int32 dat) { int32 ln = ttx_getln (dev, pulse); /* line # */ -if (ln > ttx_lines) return dat; +if (ln > ttx_lines) + return dat; if (pulse & 001) { /* TSF */ - if (ttox_test_done (ln)) dat = dat | IOT_SKP; + if (ttox_test_done (ln)) + dat = dat | IOT_SKP; } -if (pulse & 002) ttox_clr_done (ln); /* clear flag */ +if (pulse & 002) /* clear flag */ + ttox_clr_done (ln); if (pulse & 004) { /* load buffer */ sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate unit */ ttox_buf[ln] = dat & 0377; /* load buffer */ @@ -283,7 +292,8 @@ if (ttx_ldsc[ln].conn) { /* connected? */ if (ttx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &ttx_ldsc[ln]; /* get line */ c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags) | TTUF_KSR); - if (c >= 0) tmxr_putc_ln (lp, c); /* output char */ + if (c >= 0) /* output char */ + tmxr_putc_ln (lp, c); tmxr_poll_tx (&ttx_desc); /* poll xmt */ } else { @@ -300,7 +310,8 @@ return SCPE_OK; t_bool ttox_test_done (int32 ln) { -if (ttox_done & (1 << ln)) return TRUE; +if (ttox_done & (1 << ln)) + return TRUE; return FALSE; } @@ -314,8 +325,12 @@ return; void ttox_clr_done (int32 ln) { ttox_done = ttox_done & ~(1 << ln); -if (ttox_done) { SET_INT (TTO1); } -else { CLR_INT (TTO1); } +if (ttox_done) { + SET_INT (TTO1); + } +else { + CLR_INT (TTO1); + } return; } @@ -344,7 +359,7 @@ t_stat ttx_reset (DEVICE *dptr) int32 ln; if (dptr->flags & DEV_DIS) { /* sync enables */ - ttix_dev.flags = ttox_dev.flags | DEV_DIS; + ttix_dev.flags = ttix_dev.flags | DEV_DIS; ttox_dev.flags = ttox_dev.flags | DEV_DIS; } else { @@ -354,7 +369,8 @@ else { 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 */ +for (ln = 0; ln < TTX_MAXL; ln++) /* for all lines */ + ttx_reset_ln (ln); return SCPE_OK; } @@ -377,7 +393,8 @@ 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 */ +if (r != SCPE_OK) /* error */ + return r; sim_activate (uptr, tmxr_poll); /* start poll */ return SCPE_OK; } @@ -391,41 +408,11 @@ 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 */ +for (i = 0; i < TTX_MAXL; i++) /* disable rcv */ + ttx_ldsc[i].rcve = 0; return r; } -/* Show summary processor */ - -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < TTX_MAXL; i++) t = t + (ttx_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -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; -} - /* Change number of lines */ t_stat ttx_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -433,12 +420,16 @@ t_stat ttx_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = get_uint (cptr, 10, TTX_MAXL, &r); -if ((r != SCPE_OK) || (newln == ttx_lines)) return r; -if (newln == 0) return SCPE_ARG; +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; + 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++) { diff --git a/PDP8/pdp8_clk.c b/PDP8/pdp8_clk.c index ab013883..0659c9aa 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -117,7 +117,8 @@ switch (IR & 07) { /* decode IR<9:11> */ return AC; case 5: /* CLLE */ - if (AC & 1) int_enable = int_enable | INT_CLK; /* test AC<11> */ + if (AC & 1) /* test AC<11> */ + int_enable = int_enable | INT_CLK; else int_enable = int_enable & ~INT_CLK; int_req = INT_UPDATE; /* update interrupts */ return AC; @@ -168,8 +169,10 @@ return SCPE_OK; t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; clk_tps = val; return SCPE_OK; } diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c index 63d3bfbb..046449f3 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -344,7 +344,8 @@ reason = 0; while (reason == 0) { /* loop until halted */ if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; + if (reason = sim_process_event ()) + break; } if (int_req > INT_PENDING) { /* interrupt? */ @@ -388,21 +389,25 @@ while (reason == 0) { /* loop until halted */ int32 ea; hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; + 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); + 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]; + 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]; + if ((ea & 07770) != 00010) + ea = IB | M[ea]; else ea = IB | ((M[ea] + 1) & 07777); } } @@ -427,14 +432,16 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 002: /* AND, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = LAC & (M[MA] | 010000); break; @@ -453,14 +460,16 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 006: /* TAD, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = (LAC + M[MA]) & 017777; break; @@ -470,31 +479,39 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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; + 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; + 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; 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; + 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; 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; + if (MEM_ADDR_OK (MA)) + M[MA] = MB; + if (MB == 0) + PC = (PC + 1) & 07777; break; /* Opcode 3, DCA */ @@ -513,17 +530,21 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 016: /* DCA, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; + 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; + if (MEM_ADDR_OK (MA)) + M[MA] = LAC & 07777; LAC = LAC & 010000; break; @@ -553,7 +574,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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; + if (MEM_ADDR_OK (MA)) + M[MA] = PC; } PC = (MA + 1) & 07777; break; @@ -574,7 +596,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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; + if (MEM_ADDR_OK (MA)) + M[MA] = PC; } PC = (MA + 1) & 07777; break; @@ -582,7 +605,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 022: /* JMS, indir, zero */ PCQ_ENTRY; MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ @@ -597,7 +621,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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; + if (MEM_ADDR_OK (MA)) + M[MA] = PC; } PC = (MA + 1) & 07777; break; @@ -605,7 +630,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ @@ -620,7 +646,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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; + if (MEM_ADDR_OK (MA)) + M[MA] = PC; } PC = (MA + 1) & 07777; break; @@ -686,7 +713,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 026: /* JMP, indir, zero */ PCQ_ENTRY; MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ @@ -705,7 +733,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ @@ -774,7 +803,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; } /* end switch opers */ - if (IR & 01) LAC = (LAC + 1) & 017777; /* IAC */ + if (IR & 01) /* IAC */ + LAC = (LAC + 1) & 017777; switch ((IR >> 1) & 07) { /* decode IR<8:10> */ case 0: /* nop */ break; @@ -817,35 +847,44 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ PC = (PC + 1) & 07777; break; case 2: /* SNL */ - if (LAC >= 010000) PC = (PC + 1) & 07777; + if (LAC >= 010000) + PC = (PC + 1) & 07777; break; case 3: /* SZL */ - if (LAC < 010000) PC = (PC + 1) & 07777; + if (LAC < 010000) + PC = (PC + 1) & 07777; break; case 4: /* SZA */ - if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; + if ((LAC & 07777) == 0) + PC = (PC + 1) & 07777; break; case 5: /* SNA */ - if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; + 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; + if ((LAC != 0) && (LAC < 010000)) + PC = (PC + 1) & 07777; break; case 010: /* SMA */ - if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; + if ((LAC & 04000) != 0) + PC = (PC + 1) & 07777; break; case 011: /* SPA */ - if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; + if ((LAC & 04000) == 0) + PC = (PC + 1) & 07777; break; case 012: /* SMA | SNL */ - if (LAC >= 04000) PC = (PC + 1) & 07777; + if (LAC >= 04000) + PC = (PC + 1) & 07777; break; case 013: /* SPA & SZL */ - if (LAC < 04000) PC = (PC + 1) & 07777; + if (LAC < 04000) + PC = (PC + 1) & 07777; break; case 014: /* SMA | SZA */ if (((LAC & 04000) != 0) || ((LAC & 07777) == 0)) @@ -853,24 +892,29 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; case 015: /* SPA & SNA */ if (((LAC & 04000) == 0) && ((LAC & 07777) != 0)) - PC = (PC + 1) & 07777; + PC = (PC + 1) & 07777; break; case 016: /* SMA | SZA | SNL */ - if ((LAC >= 04000) || (LAC == 0)) PC = (PC + 1) & 07777; + if ((LAC >= 04000) || (LAC == 0)) + PC = (PC + 1) & 07777; break; case 017: /* SPA & SNA & SZL */ - if ((LAC < 04000) && (LAC != 0)) PC = (PC + 1) & 07777; + if ((LAC < 04000) && (LAC != 0)) + PC = (PC + 1) & 07777; break; } /* end switch skips */ - if (IR & 0200) LAC = LAC & 010000; /* CLA */ + if (IR & 0200) /* CLA */ + LAC = LAC & 010000; 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 */ + if (IR & 04) /* OSR */ + LAC = LAC | OSR; + if (IR & 02) /* HLT */ + reason = STOP_HALT; } break; } /* end if group 2 */ @@ -885,12 +929,14 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ */ temp = MQ; /* group 3 */ - if (IR & 0200) LAC = LAC & 010000; /* CLA */ + if (IR & 0200) /* CLA */ + LAC = LAC & 010000; if (IR & 0020) { /* MQL */ MQ = LAC & 07777; LAC = LAC & 010000; } - if (IR & 0100) LAC = LAC | temp; /* MQA */ + if (IR & 0100) /* MQA */ + LAC = LAC | temp; if ((IR & 0056) && (cpu_unit.flags & UNIT_NOEAE)) { reason = stop_inst; /* EAE not present */ break; @@ -949,7 +995,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ x0010 - x0017, it is autoincremented. */ - if (emode == 0) gtf = 0; /* mode A? clr gtf */ + if (emode == 0) /* mode A? clr gtf */ + gtf = 0; switch ((IR >> 1) & 027) { /* decode IR<6,8:10> */ case 020: /* mode A, B: SCA */ @@ -961,7 +1008,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 021: /* mode B: DAD */ if (emode) { MA = IF | PC; - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ MQ = MQ + M[MA]; MA = DF | ((MA + 1) & 07777); @@ -985,11 +1033,14 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 022: /* mode B: DST */ if (emode) { MA = IF | PC; - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777; + if (MEM_ADDR_OK (MA)) + M[MA] = MQ & 07777; MA = DF | ((MA + 1) & 07777); - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; + if (MEM_ADDR_OK (MA)) + M[MA] = LAC & 07777; PC = (PC + 1) & 07777; break; } @@ -997,7 +1048,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 002: /* MUY */ MA = IF | PC; if (emode) { /* mode B: defer */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ } temp = (MQ * M[MA]) + (LAC & 07777); @@ -1008,12 +1060,14 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; case 023: /* mode B: SWBA */ - if (emode) break; + 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? */ + if ((MA & 07770) != 00010) /* indirect; autoinc? */ + MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ } if ((LAC & 07777) >= M[MA]) { /* overflow? */ @@ -1032,7 +1086,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ case 024: /* mode B: DPSZ */ if (emode) { - if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777; + if (((LAC | MQ) & 07777) == 0) + PC = (PC + 1) & 07777; break; } LAC = LAC | SC; /* mode A: SCA then */ @@ -1057,7 +1112,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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 */ + if (SC > 25) /* >25? result = 0 */ + temp = 0; else temp = ((LAC << 12) | MQ) << SC; /* <=25? shift LAC:MQ */ LAC = (temp >> 12) & 017777; MQ = temp & 07777; @@ -1076,9 +1132,12 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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; + 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; @@ -1097,8 +1156,10 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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 */ + if (emode && (SC != 0)) + gtf = (temp >> (SC - 1)) & 1; + if (SC > 24) /* >24? result = 0 */ + temp = 0; else temp = temp >> SC; /* <=24? shift AC:MQ */ LAC = (temp >> 12) & 07777; MQ = temp & 07777; @@ -1118,7 +1179,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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 */ + if ((IR & 07707) == 06201) /* set/clear flag */ + tsc_cdf = 1; else tsc_cdf = 0; break; } @@ -1131,7 +1193,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ switch (pulse) { /* decode IR<9:11> */ case 0: /* SKON */ - if (int_req & INT_ION) PC = (PC + 1) & 07777; + if (int_req & INT_ION) + PC = (PC + 1) & 07777; int_req = int_req & ~INT_ION; break; @@ -1144,7 +1207,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; case 3: /* SRQ */ - if (int_req & INT_ALL) PC = (PC + 1) & 07777; + if (int_req & INT_ALL) + PC = (PC + 1) & 07777; break; case 4: /* GTF */ @@ -1164,7 +1228,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; case 6: /* SGT */ - if (gtf) PC = (PC + 1) & 07777; + if (gtf) + PC = (PC + 1) & 07777; break; case 7: /* CAF */ @@ -1224,7 +1289,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; case 5: /* SINT */ - if (int_req & INT_UF) PC = (PC + 1) & 07777; + if (int_req & INT_UF) + PC = (PC + 1) & 07777; break; case 6: /* CUF */ @@ -1252,7 +1318,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ break; case 2: /* SPL */ - if (int_req & INT_PWR) PC = (PC + 1) & 07777; + if (int_req & INT_PWR) + PC = (PC + 1) & 07777; break; case 3: /* CAL */ @@ -1269,7 +1336,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */ 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_SKP) + PC = (PC + 1) & 07777; if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON; } @@ -1298,7 +1366,8 @@ int_req = (int_req & ~INT_ION) | INT_NO_CIF_PENDING; saved_DF = IB = saved_PC & 070000; UF = UB = gtf = emode = 0; pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1308,8 +1377,10 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 07777; +if (addr >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[addr] & 07777; return SCPE_OK; } @@ -1317,7 +1388,8 @@ 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 & 07777; return SCPE_OK; } @@ -1331,11 +1403,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } @@ -1348,14 +1422,19 @@ DIB *dibp; uint32 newdev; t_stat r; -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; +if (cptr == NULL) + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; +if ((r != SCPE_OK) || (newdev == dibp->dev)) + return r; dibp->dev = newdev; /* store */ return SCPE_OK; } @@ -1367,13 +1446,17 @@ t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; fprintf (st, "devno=%02o", dibp->dev); -if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); +if (dibp->num > 1) + fprintf (st, "-%2o", dibp->dev + dibp->num - 1); return SCPE_OK; } @@ -1395,7 +1478,8 @@ 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 < DEV_MAX; i++) /* clr table */ + dev_tab[i] = NULL; 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 */ @@ -1405,10 +1489,10 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ 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); + 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 */ @@ -1427,12 +1511,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -1441,7 +1527,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -1459,26 +1546,31 @@ InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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); + 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); + if (h->ir < 04000) + fprintf (st, " [%04o]", h->opnd); fputc ('\n', st); /* end line */ } /* end else instruction */ } /* end for */ diff --git a/PDP8/pdp8_ct.c b/PDP8/pdp8_ct.c index 4451572e..456ac4bf 100644 --- a/PDP8/pdp8_ct.c +++ b/PDP8/pdp8_ct.c @@ -1,6 +1,6 @@ /* pdp8_ct.c: PDP-8 cassette tape simulator - Copyright (c) 2006-2007, Robert M Supnik + Copyright (c) 2006-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -244,11 +244,13 @@ switch (IR & 07) { /* decode IR<9:11> */ break; case 1: /* KSDR */ - if (ct_df) AC |= IOT_SKP; + if (ct_df) + AC |= IOT_SKP; break; case 2: /* KSEN */ - if (srb & SRB_ALLERR) AC |= IOT_SKP; + if (srb & SRB_ALLERR) + AC |= IOT_SKP; break; case 3: /* KSBF */ @@ -308,7 +310,8 @@ if ((ct_sra & SRA_ENAB) && (uptr->flags & UNIT_ATT)) { /* enabled, att? */ ct_db = 0; } ct_srb &= ~SRB_BEOT; /* tape in motion */ - if (fnc == SRA_REW) ct_srb |= SRB_REW; /* rew? set flag */ + if (fnc == SRA_REW) /* rew? set flag */ + ct_srb |= SRB_REW; if ((fnc != SRA_REW) && !(flg & OP_WRI)) { /* read cmd? */ t_mtrlnt t; t_stat st; @@ -357,7 +360,8 @@ switch (fnc) { /* case on function */ case SRA_CRC: /* CRC */ if ((uptr->FNC & SRA_M_FNC) != SRA_CRC) /* if not CRC */ uptr->FNC = SRA_CRC; /* start CRC seq */ - if (!ct_write) return ct_db; /* read? AC <- buf */ + if (!ct_write) /* read? AC <- buf */ + return ct_db; break; default: @@ -392,7 +396,8 @@ switch (uptr->FNC) { /* case on function */ case SRA_READ: /* read start */ st = sim_tape_rdrecf (uptr, ct_xb, &ct_blnt, CT_MAXFR); /* get rec */ - if (st == MTSE_RECE) ct_srb |= SRB_CRC; /* rec in err? */ + if (st == MTSE_RECE) /* rec in err? */ + ct_srb |= SRB_CRC; else if (st != MTSE_OK) { /* other error? */ r = ct_map_err (uptr, st); /* map error */ break; @@ -405,13 +410,15 @@ switch (uptr->FNC) { /* case on function */ return SCPE_OK; case SRA_READ|SRA_2ND: /* read char */ - if (!ct_read_char ()) break; /* read, overrun? */ + if (!ct_read_char ()) /* read, overrun? */ + break; ct_set_df (TRUE); /* set data flag */ sim_activate (uptr, ct_ctime); /* sched next char */ return SCPE_OK; case SRA_WRITE: /* write start */ - for (i = 0; i < CT_MAXFR; i++) ct_xb[i] = 0; /* clear buffer */ + for (i = 0; i < CT_MAXFR; i++) /* clear buffer */ + ct_xb[i] = 0; uptr->FNC |= SRA_2ND; /* next state */ sim_activate (uptr, ct_ctime); /* sched next char */ return SCPE_OK; @@ -439,7 +446,8 @@ switch (uptr->FNC) { /* case on function */ case SRA_CRC|SRA_2ND: /* second read CRC */ if (ct_bptr != ct_blnt) { /* partial read? */ crc = ct_crc (ct_xb, ct_bptr); /* actual CRC */ - if (crc != 0) ct_srb |= SRB_CRC; /* must be zero */ + if (crc != 0) /* must be zero */ + ct_srb |= SRB_CRC; } break; /* read done */ @@ -490,7 +498,8 @@ if (uptr == NULL) { /* unit specified? */ if ((uptr == NULL) && (ct_sra & SRA_ENAB)) /* none busy? */ uptr = ct_dev.units + GET_UNIT (ct_sra); /* use sel unit */ } -else if (ct_srb & SRB_EOF) uptr->UST |= UST_GAP; /* save gap */ +else if (ct_srb & SRB_EOF) /* save gap */ + uptr->UST |= UST_GAP; if (uptr) { /* any unit? */ ct_srb &= ~(SRB_WLK|SRB_EMP|SRB_RDY); /* clear dyn flags */ if ((uptr->flags & UNIT_ATT) == 0) /* unattached? */ @@ -501,7 +510,8 @@ if (uptr) { /* any unit? */ if (sim_tape_wrp (uptr) || (ct_srb & SRB_REW)) /* locked or rew? */ ct_srb |= SRB_WLK; /* set locked */ } -if (ct_sra & SRA_ENAB) srb = ct_srb; /* can TA see TU60? */ +if (ct_sra & SRA_ENAB) /* can TA see TU60? */ + srb = ct_srb; else srb = 0; /* no */ if ((ct_sra & SRA_IE) && /* int enabled? */ (ct_df || (srb & (SRB_ALLERR|SRB_RDY)))) /* any flag? */ @@ -514,9 +524,11 @@ return srb; void ct_set_df (t_bool timchk) { -if (ct_df && timchk) ct_srb |= SRB_TIM; /* flag still set? */ +if (ct_df && timchk) /* flag still set? */ + ct_srb |= SRB_TIM; ct_df = 1; /* set data flag */ -if (ct_sra & SRA_IE) int_req |= INT_CT; /* if ie, int req */ +if (ct_sra & SRA_IE) /* if ie, int req */ + int_req |= INT_CT; return; } @@ -542,7 +554,8 @@ UNIT *uptr; for (u = 0; u < CT_NUMDR; u++) { /* loop thru units */ uptr = ct_dev.units + u; - if (sim_is_active (uptr)) return uptr; + if (sim_is_active (uptr)) + return uptr; } return NULL; } @@ -557,7 +570,8 @@ crc = 0; for (i = 0; i < cnt; i++) { crc = crc ^ (((uint32) buf[i]) << 8); for (j = 0; j < 8; j++) { - if (crc & 1) crc = (crc >> 1) ^ 0xA001; + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; else crc = crc >> 1; } } @@ -582,7 +596,8 @@ switch (st) { case MTSE_IOERR: /* IO error */ ct_srb |= SRB_CRC; /* set crc err */ - if (ct_stopioe) return SCPE_IOERR; + if (ct_stopioe) + return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ @@ -626,8 +641,10 @@ for (u = 0; u < CT_NUMDR; u++) { /* loop thru units */ sim_cancel (uptr); /* cancel activity */ sim_tape_reset (uptr); /* reset tape */ } -if (ct_xb == NULL) ct_xb = (uint8 *) calloc (CT_MAXFR + 2, sizeof (uint8)); -if (ct_xb == NULL) return SCPE_MEM; +if (ct_xb == NULL) + ct_xb = (uint8 *) calloc (CT_MAXFR + 2, sizeof (uint8)); +if (ct_xb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -638,7 +655,8 @@ t_stat ct_attach (UNIT *uptr, char *cptr) t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; ct_updsta (NULL); uptr->UST = 0; return r; @@ -650,7 +668,8 @@ t_stat ct_detach (UNIT* uptr) { t_stat r; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check attached */ +if (!(uptr->flags & UNIT_ATT)) /* check attached */ + return SCPE_OK; r = sim_tape_detach (uptr); ct_updsta (NULL); uptr->UST = 0; @@ -705,7 +724,8 @@ extern uint16 M[]; if ((ct_dib.dev != DEV_CT) || unitno) /* only std devno */ return STOP_NOTSTD; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +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_defs.h b/PDP8/pdp8_defs.h index 0a1967c1..ea951f7b 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index b28d4504..ac6b3f03 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -184,7 +184,8 @@ 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? */ + if (t < 0) /* wrap around? */ + t = t + DF_NUMWD; sim_activate (&df_unit, t * df_time); /* schedule op */ AC = 0; /* clear AC */ } @@ -224,13 +225,17 @@ int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) { /* DFSE */ - if ((df_sta & DFS_ERR) == 0) AC = AC | IOT_SKP; + 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) /* for DMAC */ + AC = AC & ~07777; + else if (df_done) + AC = AC | IOT_SKP; } -if (pulse & 4) AC = AC | df_da; /* DMAC */ +if (pulse & 4) /* DMAC */ + AC = AC | df_da; return AC; } @@ -281,7 +286,8 @@ do { 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; + if (uptr->FUNC != DF_READ) + da = (da - 1) & 0377777; df_done = 1; /* done */ int_req = int_req | INT_DF; /* update int req */ } @@ -353,7 +359,8 @@ uint32 ds_bytes = DF_DKSIZE * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= DF_NUMDK) p = DF_NUMDK - 1; + if (p >= DF_NUMDK) + p = DF_NUMDK - 1; uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); } @@ -365,8 +372,10 @@ return attach_unit (uptr, cptr); t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (val < 0) + return SCPE_IERR; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * DF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index 398d35b2..5fdfbcaa 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -385,14 +385,16 @@ UNIT *uptr; if (pulse & 01) AC = AC | dtsa; /* DTRA */ if (pulse & 06) { /* select */ - if (pulse & 02) dtsa = 0; /* DTCA */ + if (pulse & 02) /* DTCA */ + dtsa = 0; 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); + 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? */ @@ -412,7 +414,8 @@ 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 & 02) /* DTRB */ + AC = AC | dtsb; if (pulse & 04) { /* DTLB */ dtsb = (dtsb & ~DTB_MEX) | (AC & DTB_MEX); AC = AC & ~07777; /* clear AC */ @@ -475,10 +478,12 @@ 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) /* stop to stop */ + return; if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* schedule acc */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -488,7 +493,8 @@ if (new_mving & ~prev_mving) { /* start? */ if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -498,7 +504,8 @@ if (prev_mving & ~new_mving) { /* stop? */ if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } @@ -509,7 +516,8 @@ if (prev_dir ^ new_dir) { /* dir chg? */ } if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ + if (dt_setpos (uptr)) /* update pos */ + return; sim_cancel (uptr); /* cancel cur */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ @@ -544,7 +552,8 @@ int32 fnc, dir, blk, unum, relpos, newpos; uint32 oldpos; oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ +if (dt_setpos (uptr)) /* update pos */ + return; uptr->STATE = newsta; /* update state */ fnc = DTS_GETFNC (uptr->STATE); /* set variables */ dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; @@ -562,8 +571,9 @@ dt_substate = DTO_SOB; /* substate = block star 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 */ + if (dir) /* rev? < start */ + newpos = -1000; + else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ break; case FNC_MOVE: /* move */ @@ -577,8 +587,9 @@ switch (fnc) { /* case function */ 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")); + if (DEBUG_PRI (dt_dev, LOG_MS)) + fprintf (sim_deb, ">>DT%d: searching %s]\n", + unum, (dir? "backward": "forward")); break; case FNC_WRIT: /* write */ @@ -586,7 +597,8 @@ switch (fnc) { /* case function */ 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; + if (dir) + newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); break; } @@ -596,10 +608,11 @@ switch (fnc) { /* case function */ 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; + 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); + blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); break; default: @@ -637,7 +650,8 @@ 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 */ +if (ut == 0) /* no time gone? exit */ + return FALSE; uptr->LASTT = new_time; /* update last time */ switch (mot & ~DTS_DIR) { /* case on motion */ @@ -662,7 +676,8 @@ switch (mot & ~DTS_DIR) { /* case on motion */ break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ +if (mot & DTS_DIR) /* update pos */ + uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { @@ -748,7 +763,8 @@ switch (fnc) { /* at speed, check fnc * 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 (MEM_ADDR_OK (ma)) /* store block # */ + M[ma] = blk & 07777; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ break; @@ -792,9 +808,12 @@ switch (fnc) { /* at speed, check fnc * 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? */ + if (dir) /* rev? comp obv */ + dat = dt_comobv (dat); + if (MEM_ADDR_OK (ma)) /* mem addr legal? */ + M[ma] = dat; + if (M[DT_WC] == 0) /* wc ovf? */ + dt_substate = DTO_WCO; case DTO_WCO: /* wc ovf, not sob */ if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -849,10 +868,13 @@ switch (fnc) { /* at speed, check fnc * 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 */ + if (dir) /* rev? comp obv */ + dat = dt_comobv (dat); fbuf[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (M[DT_WC] == 0) dt_substate = DTO_WCO; + 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 { @@ -893,12 +915,15 @@ switch (fnc) { /* at speed, check fnc * 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 */ + if (dir) /* rev? comp obv */ + dat = dt_comobv (dat); } 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 (MEM_ADDR_OK (ma)) /* mem addr legal? */ + M[ma] = dat; + 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; @@ -931,15 +956,18 @@ switch (fnc) { /* at speed, check fnc * 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); + 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; + 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 (M[DT_WC] == 0) + dt_substate = DTO_WCO; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ break; @@ -1038,7 +1066,8 @@ 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 */ + if (dt_setpos (uptr)) /* update position */ + return; sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); /* state = decel */ } @@ -1052,7 +1081,8 @@ void dt_schedez (UNIT *uptr, int32 dir) { int32 newpos; -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ +if (dir) /* rev? rev ez */ + newpos = DT_EZLIN - DT_WSIZE; else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); return; @@ -1096,7 +1126,8 @@ for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ 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 */ + if (dt_setpos (uptr)) /* update pos */ + continue; sim_cancel (uptr); sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); @@ -1150,10 +1181,13 @@ 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) /* only unit 0 */ + return SCPE_ARG; +if (dt_dib.dev != DEV_DTA) /* only std devno */ + return STOP_NOTSTD; dt_unit[unitno].pos = DT_EZLIN; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; saved_PC = BOOT_START; return SCPE_OK; } @@ -1199,8 +1233,10 @@ if (uptr->filebuf == NULL) { /* can't alloc? */ } 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"); +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? */ @@ -1210,10 +1246,12 @@ 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]; + for (i = 0; i < k; i++) + pdp18b[i] = pdp11b[i]; } else k = fxread (pdp18b, sizeof (uint32), D18_NBSIZE, uptr->fileref); - if (k == 0) break; + 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; @@ -1247,7 +1285,8 @@ 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)) /* attached? */ + return SCPE_OK; if (sim_is_active (uptr)) { sim_cancel (uptr); if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { @@ -1273,7 +1312,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ ba = ba + 3; } /* end loop blk */ if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (i = 0; i < D18_NBSIZE; i++) pdp11b[i] = pdp18b[i]; + for (i = 0; i < D18_NBSIZE; i++) + pdp11b[i] = pdp18b[i]; fxwrite (pdp11b, sizeof (uint16), D18_NBSIZE, uptr->fileref); } @@ -1281,7 +1321,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ D18_NBSIZE, uptr->fileref); } /* end loop buf */ } /* end else */ - if (ferror (uptr->fileref)) perror ("I/O error"); + 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 */ diff --git a/PDP8/pdp8_fpp.c b/PDP8/pdp8_fpp.c index fb2e5865..3937127e 100644 --- a/PDP8/pdp8_fpp.c +++ b/PDP8/pdp8_fpp.c @@ -1,6 +1,6 @@ /* pdp8_fpp.c: PDP-8 floating point processor (FPP8A) - Copyright (c) 2007, Robert M Supnik + Copyright (c) 2007-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -175,7 +175,7 @@ void fpp_fr_rsh1 (uint32 *a, uint32 sign, uint32 cnt); void fpp_fr_algn (uint32 *a, uint32 sc, uint32 cnt); t_bool fpp_cond_met (uint32 cond); t_bool fpp_norm (FPN *a, uint32 cnt); -uint32 fpp_round (FPN *a); +void fpp_round (FPN *a); t_bool fpp_test_xp (FPN *a); void fpp_copy (FPN *a, FPN *b); void fpp_zcopy (FPN *a, FPN *b); @@ -926,7 +926,7 @@ if (fpp_fr_test (a->fr, 0, cnt) == 0) { /* zero? */ return FALSE; /* don't round */ } while (((a->fr[0] == 0) && !(a->fr[1] & 04000)) || /* lead 13b same? */ - ((a->fr[0] = 07777) & (a->fr[1] & 04000))) { + ((a->fr[0] = 07777) && (a->fr[1] & 04000))) { fpp_fr_lsh12 (a->fr, cnt); /* move word */ a->exp = a->exp - 12; } @@ -989,15 +989,15 @@ if (a->exp < -2048) { /* underflow? */ return FALSE; } -/* Round dp/fp value, returns carry out */ +/* Round dp/fp value */ -uint32 fpp_round (FPN *a) +void fpp_round (FPN *a) { int32 i; uint32 cin, afr0_sign; if (fpp_sta & FPS_EP) /* ep? */ - return FALSE; /* don't round */ + return; /* don't round */ afr0_sign = a->fr[0] & FPN_FRSIGN; /* save input sign */ cin = afr0_sign? 03777: 04000; for (i = FPN_NFR_FP; i >= 0; i--) { /* 3 words */ @@ -1010,7 +1010,7 @@ if (!(fpp_sta & FPS_DP) && /* fp? */ fpp_fr_rsh1 (a->fr, afr0_sign, EXACT); /* rsh, insert sign */ a->exp = a->exp + 1; } -return cin; +return; } /* N-precision integer routines */ @@ -1079,7 +1079,7 @@ for (i = 0; i < cnt; i++) { /* loop thru mpcd */ fpp_fr_rsh1 (c, cin, EXTEND); /* shift answer */ fpp_fr_rsh1 (b, 0, EXACT); /* shift mpcd */ } -if (a[0] & FPN_FRSIGN) /* mpyr negative? */ +if (a[0] & FPN_FRSIGN) /* mpyr negative? */ fpp_fr_sub (c, c, a); /* adjust result */ return; } @@ -1091,10 +1091,10 @@ t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b) uint32 i, old_c, lo, cnt, sign; fpp_fr_fill (c, 0, EXTEND); /* clr answer */ -sign = (a[0] ^ b[0]) & FPN_FRSIGN; /* sign of result */ -if (a[0] & FPN_FRSIGN) /* |a| */ +sign = (a[0] ^ b[0]) & FPN_FRSIGN; /* sign of result */ +if (a[0] & FPN_FRSIGN) /* |a| */ fpp_fr_neg (a, EXACT); -if (b[0] & FPN_FRSIGN); /* |b| */ +if (b[0] & FPN_FRSIGN); /* |b| */ fpp_fr_neg (b, EXACT); if (fpp_sta & FPS_EP) /* ep? 5 words */ lo = FPN_NFR_EP - 1; @@ -1104,16 +1104,16 @@ for (i = 0; i < cnt; i++) { /* loop */ fpp_fr_lsh1 (c, EXTEND); /* shift quotient */ if (fpp_fr_cmp (a, b, EXTEND) >= 0) { /* sub work? */ fpp_fr_sub (a, a, b); /* divd - divr */ - if (a[0] & FPN_FRSIGN) /* sign flip? */ + if (a[0] & FPN_FRSIGN) /* sign flip? */ return TRUE; /* no, overflow */ c[lo] |= 1; /* set quo bit */ } fpp_fr_lsh1 (a, EXTEND); /* shift dividend */ } -old_c = c[0]; /* save ho quo */ +old_c = c[0]; /* save hi quo */ if (sign) /* expect neg ans? */ fpp_fr_neg (c, EXTEND); /* -quo */ -if (old_c & FPN_FRSIGN) /* sign set before */ +if (old_c & FPN_FRSIGN) /* sign set before */ return TRUE; /* neg? */ return FALSE; } diff --git a/PDP8/pdp8_lp.c b/PDP8/pdp8_lp.c index 28f792f4..f2fc6a21 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP8/pdp8_mt.c b/PDP8/pdp8_mt.c index 41dc2d37..cda142ae 100644 --- a/PDP8/pdp8_mt.c +++ b/PDP8/pdp8_mt.c @@ -1,6 +1,6 @@ /* pdp8_mt.c: PDP-8 magnetic tape simulator - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -247,13 +247,15 @@ switch (IR & 07) { /* decode IR<9:11> */ return AC; case 5: /* LCMR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ + if (mt_busy ()) /* busy? illegal op */ + mt_sta = mt_sta | STA_ILL | STA_ERR; 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 */ + if (mt_busy ()) /* busy? illegal op */ + mt_sta = mt_sta | STA_ILL | STA_ERR; mt_fn = AC; /* load function */ if ((mt_fn & FN_GO) == 0) { /* go set? */ mt_updcsta (uptr); /* update status */ @@ -285,7 +287,8 @@ switch (IR & 07) { /* decode IR<9:11> */ return 0; case 7: /* LDBR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ + if (mt_busy ()) /* busy? illegal op */ + mt_sta = mt_sta | STA_ILL | STA_ERR; mt_db = AC; /* load buffer */ mt_set_done (); /* set done */ mt_updcsta (uptr); /* update status */ @@ -407,14 +410,16 @@ 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? */ + if (st == MTSE_RECE) /* rec in err? */ + mt_sta = mt_sta | STA_PAR | STA_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) /* wrong size? */ + mt_sta = mt_sta | STA_RLE | STA_ERR; if (tbc < cbc) { /* record small? */ cbc = tbc; /* use smaller */ wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; @@ -428,7 +433,8 @@ switch (f) { /* case on function */ c2 = mtxb[p++] & 077; c = (c1 << 6) | c2; } - if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; + 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; @@ -440,7 +446,8 @@ switch (f) { /* case on function */ 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; + if (mt_cu & CU_UNPAK) + mtxb[p++] = M[xma] & 0377; else { mtxb[p++] = (M[xma] >> 6) & 077; mtxb[p++] = M[xma] & 077; @@ -494,7 +501,8 @@ int32 mt_updcsta (UNIT *uptr) { mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) || - (mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT; + (mt_done && (mt_cu & CU_IED))) + int_req = int_req | INT_MT; else int_req = int_req & ~INT_MT; return mt_sta; } @@ -522,7 +530,8 @@ 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 */ + if (xma == 077777) /* at limit? error */ + mt_sta = mt_sta | STA_INC | STA_ERR; else v = xma + 1; /* else 15b incr */ } return v; @@ -556,7 +565,8 @@ switch (st) { case MTSE_IOERR: /* IO error */ mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - if (mt_stopioe) return SCPE_IOERR; + if (mt_stopioe) + return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ @@ -599,8 +609,10 @@ for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ (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; +if (mtxb == NULL) + mtxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); +if (mtxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -612,9 +624,11 @@ t_stat r; int32 u = uptr - mt_dev.units; /* get unit number */ r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->USTAT = STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); +if (u == GET_UNIT (mt_cu)) + mt_updcsta (uptr); return r; } @@ -624,9 +638,12 @@ t_stat mt_detach (UNIT* uptr) { int32 u = uptr - mt_dev.units; /* get unit number */ -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); +if (!(uptr->flags & UNIT_ATT)) /* check for attached */ + return SCPE_OK; +if (!sim_is_active (uptr)) + uptr->USTAT = STA_REM; +if (u == GET_UNIT (mt_cu)) + mt_updcsta (uptr); return sim_tape_detach (uptr); } @@ -639,6 +656,7 @@ int32 u = uptr - mt_dev.units; /* get unit number */ if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) uptr->USTAT = uptr->USTAT | STA_WLK; else uptr->USTAT = uptr->USTAT & ~STA_WLK; -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); +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 787ba31f..9ba51307 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -162,7 +162,8 @@ 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"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); @@ -281,8 +282,10 @@ int32 i; extern int32 saved_PC; extern uint16 M[]; -if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +if (ptr_dib.dev != DEV_PTR) /* only std devno */ + return STOP_NOTSTD; +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 74f40438..7117a95c 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -197,7 +197,8 @@ 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? */ + if (t < 0) /* wrap around? */ + t = t + RF_NUMWD; sim_activate (&rf_unit, t * rf_time); /* schedule op */ AC = 0; /* clear AC */ } @@ -242,13 +243,17 @@ int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) { /* DFSE */ - if (rf_sta & RFS_ERR) AC = AC | IOT_SKP; + 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) /* for DMAC */ + AC = AC & ~07777; + else if (rf_done) + AC = AC | IOT_SKP; } -if (pulse & 4) AC = AC | (rf_da & 07777); /* DMAC */ +if (pulse & 4) /* DMAC */ + AC = AC | (rf_da & 07777); return AC; } @@ -281,7 +286,8 @@ switch (pulse) { /* decode IR<9:11> */ break; } /* end switch */ -if ((uint32) rf_da >= rf_unit.capac) rf_sta = rf_sta | RFS_NXD; +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; @@ -325,7 +331,8 @@ do { 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; + if (((uint32) rf_da) >= uptr->hwmark) + uptr->hwmark = rf_da + 1; } } rf_da = (rf_da + 1) & 03777777; /* incr disk addr */ @@ -394,7 +401,8 @@ 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) /* only std devno */ + return STOP_NOTSTD; if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) M[dm4_rom[i]] = dm4_rom[i + 1]; @@ -417,7 +425,8 @@ uint32 ds_bytes = RF_DKSIZE * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; + if (p >= RF_NUMDK) + p = RF_NUMDK - 1; uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); } @@ -429,8 +438,10 @@ return attach_unit (uptr, cptr); t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (val < 0) + return SCPE_IERR; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * RF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; diff --git a/PDP8/pdp8_rk.c b/PDP8/pdp8_rk.c index 4d5beb80..dfbc6578 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -222,18 +222,21 @@ switch (IR & 07) { /* decode IR<9:11> */ 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]); + 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; + 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; + 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)); @@ -241,19 +244,23 @@ switch (IR & 07) { /* decode IR<9:11> */ break; case 4: /* DLCA */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; + 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; + 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; + if (rk_busy != 0) + rk_sta = rk_sta | RKS_BUSY; else { rk_cmd = AC; /* load command */ rk_sta = 0; /* clear status */ @@ -282,8 +289,10 @@ void rk_go (int32 func, int32 cyl) int32 t; UNIT *uptr; -if (func == RKC_RALL) func = RKC_READ; /* all? use standard */ -if (func == RKC_WALL) func = RKC_WRITE; +if (func == RKC_RALL) /* all? use standard */ + func = RKC_READ; +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; @@ -359,17 +368,20 @@ if ((uptr->FUNC == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { pa = GET_MEX (rk_cmd) | rk_ma; /* phys address */ da = GET_DA (rk_cmd, rk_da) * RK_NUMWD * sizeof (int16);/* disk address */ swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */ -if ((wc1 = ((rk_ma + wc) - 010000)) > 0) wc = wc - wc1; /* if wrap, limit */ +if ((wc1 = ((rk_ma + wc) - 010000)) > 0) /* if wrap, limit */ + wc = wc - wc1; 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 */ + for ( ; awc < wc; awc++) /* fill if eof */ + M[pa + awc] = 0; 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 */ + for ( ; awc < wc1; awc++) /* fill if eof */ + M[pa + awc] = 0; err = ferror (uptr->fileref); } } @@ -441,8 +453,10 @@ t_stat rk_boot (int32 unitno, DEVICE *dptr) int32 i; extern int32 saved_PC; -if (rk_dib.dev != DEV_RK) return STOP_NOTSTD; /* only std devno */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +if (rk_dib.dev != DEV_RK) /* only std devno */ + return STOP_NOTSTD; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; M[BOOT_UNIT] = (unitno & RK_M_NUMDR) << 1; saved_PC = BOOT_START; return SCPE_OK; diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c index ac2376c0..7b658469 100644 --- a/PDP8/pdp8_rl.c +++ b/PDP8/pdp8_rl.c @@ -1,6 +1,6 @@ /* pdp8_rl.c: RL8A cartridge disk simulator - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -268,7 +268,8 @@ switch (IR & 07) { /* case IR<9:11> */ break; case 1: /* RLSD */ - if (rl_done) AC = IOT_SKP; /* skip if done */ + if (rl_done) /* skip if done */ + AC = IOT_SKP; else AC = 0; rl_done = 0; /* clear done */ int_req = int_req & ~INT_RL; /* clear intr */ @@ -381,7 +382,8 @@ switch (IR & 07) { /* case IR<9:11> */ return AC; case 7: /* RLSE */ - if (rl_erf) dat = IOT_SKP | AC; /* skip if err */ + if (rl_erf) /* skip if err */ + dat = IOT_SKP | AC; else dat = AC; rl_erf = 0; break; @@ -410,8 +412,10 @@ 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; + 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; @@ -453,7 +457,8 @@ 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 */ + if (bc > maxc) /* trk ovrun? limit */ + wc = bc = maxc; } else { bc = ((wc * 3) + 1) / 2; /* 12b mode */ @@ -469,7 +474,8 @@ 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 < bc; i++) /* fill buffer */ + rlxb[i] = 0; for (i = j = 0; i < wc; i++) { /* store buffer */ if (rlcsb & RLCSB_8B) /* 8b mode? */ M[ma] = rlxb[i] & 0377; /* store */ @@ -500,13 +506,15 @@ if ((func == RLCSB_WRITE) && (err == 0)) { /* write? */ 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 */ + for (i = bc; i < wbc; i++) /* end of blk */ + rlxb[i] = 0; 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? */ +if (rlwc != 0) /* completed? */ + rler = rler | RLER_INCMP; rlma = (rlma + wc) & 07777; /* final word addr */ rlsa = rlsa + ((bc + (RL_NUMBY - 1)) / RL_NUMBY); rl_set_done (0); @@ -525,8 +533,10 @@ void rl_set_done (int32 status) { rl_done = 1; rler = rler | status; -if (rler) rl_erf = 1; -if (rlcsb & RLCSB_IE) int_req = int_req | INT_RL; +if (rler) + rl_erf = 1; +if (rlcsb & RLCSB_IE) + int_req = int_req | INT_RL; else int_req = int_req & ~INT_RL; return; } @@ -553,8 +563,10 @@ for (i = 0; i < RL_NUMDR; i++) { sim_cancel (uptr); uptr->STAT = 0; } -if (rlxb == NULL) rlxb = (uint8 *) calloc (RL_MAXFR, sizeof (uint8)); -if (rlxb == NULL) return SCPE_MEM; +if (rlxb == NULL) + rlxb = (uint8 *) calloc (RL_MAXFR, sizeof (uint8)); +if (rlxb == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -567,14 +579,17 @@ 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? */ +if (r != SCPE_OK) /* error? */ + return r; 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; + 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 ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return r; if (p > (RL01_SIZE * sizeof (int16))) { uptr->flags = uptr->flags | UNIT_RL02; uptr->capac = RL02_SIZE; @@ -590,7 +605,8 @@ return SCPE_OK; t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; return SCPE_OK; } @@ -615,14 +631,20 @@ t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 i, da = RL_BBMAP * RL_NUMBY; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (uptr->flags & UNIT_RO) return SCPE_RO; -if (!get_yn ("Create bad block table? [N]", FALSE)) return SCPE_OK; -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; +if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; +if (uptr->flags & UNIT_RO) + return SCPE_RO; +if (!get_yn ("Create bad block table? [N]", FALSE)) + return SCPE_OK; +if (fseek (uptr->fileref, da, SEEK_SET)) + return SCPE_IOERR; rlxb[0] = RL_BBID; -for (i = 1; i < RL_NUMBY; i++) rlxb[i] = 0; +for (i = 1; i < RL_NUMBY; i++) + rlxb[i] = 0; fxwrite (rlxb, sizeof (uint8), RL_NUMBY, uptr->fileref); -if (ferror (uptr->fileref)) return SCPE_IOERR; +if (ferror (uptr->fileref)) + return SCPE_IOERR; return SCPE_OK; } @@ -670,10 +692,13 @@ 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) /* only unit 0 */ + return SCPE_ARG; +if (rl_dib.dev != DEV_RL) /* only std devno */ + return STOP_NOTSTD; rl_unit[unitno].TRK = 0; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; saved_PC = BOOT_START; return SCPE_OK; } diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c index fe99c7f6..03249ee2 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -229,7 +229,8 @@ switch (IR & 07) { /* decode IR<9:11> */ break; case 1: /* LCD */ - if (rx_state != IDLE) return AC; /* ignore if busy */ + if (rx_state != IDLE) /* ignore if busy */ + return AC; dev_done = dev_done & ~INT_RX; /* clear done, int */ int_req = int_req & ~INT_RX; rx_tr = rx_err = 0; /* clear flags */ @@ -291,7 +292,8 @@ switch (IR & 07) { /* decode IR<9:11> */ break; case 6: /* INTR */ - if (AC & 1) int_enable = int_enable | INT_RX; + if (AC & 1) + int_enable = int_enable | INT_RX; else int_enable = int_enable & ~INT_RX; int_req = INT_UPDATE; break; @@ -404,7 +406,8 @@ switch (rx_state) { /* case on state */ 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 */ + if (rx_bptr < bps) /* if more, set xfer */ + rx_tr = 1; else rx_done (0, 0); /* else done */ } else { @@ -418,7 +421,8 @@ switch (rx_state) { /* case on state */ rx_buf[byptr + 1] = (rx_dbr & 017) << 4; } rx_bptr = rx_bptr + 1; - if (rx_bptr < wps) rx_tr = 1; /* if more, set xfer */ + if (rx_bptr < wps) /* if more, set xfer */ + rx_tr = 1; else { for (i = PTR12 (wps); i < bps; i++) rx_buf[i] = 0; /* else fill sector */ @@ -461,7 +465,8 @@ switch (rx_state) { /* case on state */ 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_WRDEL) /* del data? */ + rx_esr = rx_esr | RXES_DD; if (func == RXCS_READ) { /* read? */ for (i = 0; i < bps; i++) rx_buf[i] = fbuf[da + i]; } @@ -470,9 +475,11 @@ switch (rx_state) { /* case on state */ rx_done (0, 0100); /* done, error */ break; } - for (i = 0; i < bps; i++) fbuf[da + i] = rx_buf[i]; + for (i = 0; i < bps; i++) + fbuf[da + i] = rx_buf[i]; da = da + bps; - if (da > uptr->hwmark) uptr->hwmark = da; + if (da > uptr->hwmark) + uptr->hwmark = da; } rx_done (0, 0); /* done */ break; @@ -487,9 +494,11 @@ switch (rx_state) { /* case on state */ break; case SDXFR: /* erase disk */ - for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0; + 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; + if (rx_csr & RXCS_DEN) + uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; rx_done (0, 0); break; @@ -520,7 +529,8 @@ switch (rx_state) { /* case on state */ 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; + if ((rx_unit[1].flags & UNIT_ATT) == 0) + rx_ecode = 0020; break; } /* end case state */ @@ -539,14 +549,17 @@ 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_28) /* RX28? */ + rx_esr = rx_esr | RXES_RX02; 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? */ +if (new_ecode > 0) /* test for error */ + rx_err = 1; +if (new_ecode < 0) /* don't update? */ + return; rx_ecode = new_ecode; /* update ecode */ rx_dbr = rx_esr; /* update RXDB */ return; @@ -566,7 +579,8 @@ 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? */ +if (dptr->flags & DEV_DIS) /* disabled? */ + sim_cancel (&rx_unit[0]); 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)); @@ -582,7 +596,8 @@ t_stat rx_attach (UNIT *uptr, char *cptr) uint32 sz; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { - if (sz > RX_SIZE) 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; @@ -593,8 +608,10 @@ return attach_unit (uptr, cptr); 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 (uptr->flags & UNIT_ATT) + return SCPE_ALATT; +if ((rx_28 == 0) && val) /* not on RX8E */ + return SCPE_NOFNC; uptr->capac = val? RX2_SIZE: RX_SIZE; return SCPE_OK; } @@ -605,13 +622,17 @@ t_stat rx_settype (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 i; -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -if (val == rx_28) return SCPE_OK; +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++) { - if (val) rx_unit[i].flags = rx_unit[i].flags | UNIT_DEN | UNIT_AUTO; + if (val) + rx_unit[i].flags = rx_unit[i].flags | UNIT_DEN | UNIT_AUTO; else rx_unit[i].flags = rx_unit[i].flags & ~(UNIT_DEN | UNIT_AUTO); rx_unit[i].capac = val? RX2_SIZE: RX_SIZE; } @@ -716,13 +737,16 @@ 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) /* only std devno */ + return STOP_NOTSTD; if (rx_28) { - for (i = 0; i < BOOT2_LEN; i++) M[BOOT2_START + i] = boot2_rom[i]; + for (i = 0; i < BOOT2_LEN; i++) + M[BOOT2_START + i] = boot2_rom[i]; saved_PC = BOOT2_ENTRY; } else { - for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; + for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; M[BOOT_INST] = unitno? 07024: 07004; saved_PC = BOOT_ENTRY; } diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c index c8ffa520..db3a095c 100644 --- a/PDP8/pdp8_sys.c +++ b/PDP8/pdp8_sys.c @@ -151,7 +151,8 @@ do { /* data block */ if ((lo = getc (fi)) == EOF) return SCPE_FMT; wd = (hi << 6) | lo; - if (wd > 07777) origin = wd & 07777; + if (wd > 07777) + origin = wd & 07777; else M[origin++ & 07777] = wd; if ((hi = getc (fi)) == EOF) return SCPE_FMT; @@ -223,7 +224,8 @@ return SCPE_IERR; t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) { -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; +if ((*cptr != 0) || (flag != 0)) + return SCPE_ARG; if ((sim_switches & SWMASK ('R')) || /* RIM format? */ (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) return sim_load_rim (fileref); @@ -544,7 +546,8 @@ t_stat r; cflag = (uptr == NULL) || (uptr == &cpu_unit); inst = val[0]; if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } @@ -561,7 +564,8 @@ if (sw & SWMASK ('T')) { /* TSS8 packed? */ if ((sw & SWMASK ('F')) && /* FPP8? */ ((r = fprint_sym_fpp (of, val)) != SCPE_ARG)) return r; -if (!(sw & SWMASK ('M'))) return SCPE_ARG; +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; /* Instruction decode */ @@ -602,7 +606,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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); + if (cflag) + fprintf (of, "%-o", (addr & 07600) | disp); else fprintf (of, "C %-o", disp); } else fprintf (of, "%-o", disp); /* page zero */ @@ -614,17 +619,20 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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]); + 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 */ + 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]); + if (opcode[i]) + fprintf (of, (sp? " %s": "%s"), opcode[i]); break; } /* end case */ @@ -655,18 +663,21 @@ char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); while (isspace (*cptr)) cptr++; /* absorb spaces */ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; 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 */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) | ((t_value) (cptr[1] - 040) & 077); return SCPE_OK; @@ -678,7 +689,8 @@ if ((r = parse_sym_fpp (cptr, val)) != SCPE_ARG) /* FPP8 inst? */ 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; +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 */ @@ -697,12 +709,14 @@ switch (j) { /* case on class */ (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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; val[0] = val[0] | (d << 3); break; } @@ -722,8 +736,10 @@ switch (j) { /* case on class */ } else { d = get_uint (gbuf, 8, 07777, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (d <= 0177) val[0] = val[0] | d; + 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; diff --git a/PDP8/pdp8_td.c b/PDP8/pdp8_td.c index 2f1cdd30..7797fadd 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -280,15 +280,18 @@ int32 diff, t; switch (pulse) { case 01: /* SDSS */ - if (td_slf) return AC | IOT_SKP; + if (td_slf) + return AC | IOT_SKP; break; case 02: /* SDST */ - if (td_tme) return AC | IOT_SKP; + if (td_tme) + return AC | IOT_SKP; break; case 03: /* SDSQ */ - if (td_qlf) return AC | IOT_SKP; + if (td_qlf) + return AC | IOT_SKP; break; case 04: /* SDLC */ @@ -344,7 +347,8 @@ 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? */ +if ((uptr->flags & UNIT_ATT) == 0) /* new unit attached? */ + return FALSE; new_mving = ((newf & TDC_STPGO) != 0); /* new moving? */ prev_mving = (uptr->STATE != STA_STOP); /* previous moving? */ @@ -353,10 +357,12 @@ prev_dir = ((uptr->STATE & STA_DIR) != 0); /* previous dir? */ td_mtk = 0; /* mark trk reg cleared */ -if (!prev_mving && !new_mving) return FALSE; /* stop from stop? */ +if (!prev_mving && !new_mving) /* stop from stop? */ + return FALSE; if (new_mving && !prev_mving) { /* start from stop? */ - if (td_setpos (uptr)) return TRUE; /* update pos */ + if (td_setpos (uptr)) /* update pos */ + return TRUE; sim_cancel (uptr); /* stop current */ sim_activate (uptr, td_dctime - (td_dctime >> 2)); /* sched accel */ uptr->STATE = STA_ACC | new_dir; /* set status */ @@ -367,7 +373,8 @@ if (new_mving && !prev_mving) { /* start from stop? */ 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 */ + if (td_setpos (uptr)) /* update pos */ + return TRUE; sim_cancel (uptr); /* stop current */ sim_activate (uptr, td_dctime); /* schedule decel */ uptr->STATE = STA_DEC | prev_dir; /* set status */ @@ -404,7 +411,8 @@ int32 delta; new_time = sim_grtime (); /* current time */ ut = new_time - uptr->LASTT; /* elapsed time */ -if (ut == 0) return FALSE; /* no time gone? exit */ +if (ut == 0) /* no time gone? exit */ + return FALSE; uptr->LASTT = new_time; /* update last time */ switch (uptr->STATE & ~STA_DIR) { /* case on motion */ @@ -429,7 +437,8 @@ switch (uptr->STATE & ~STA_DIR) { /* case on motion */ break; } -if (uptr->STATE & STA_DIR) uptr->pos = uptr->pos - delta; /* update pos */ +if (uptr->STATE & STA_DIR) /* update pos */ + uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { @@ -456,7 +465,8 @@ 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 (mot == STA_STOP) /* stopped? done */ + return SCPE_OK; if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ uptr->STATE = uptr->pos = 0; /* also done */ return SCPE_UNATT; @@ -483,7 +493,8 @@ switch (mot) { /* case on motion */ break; case STA_UTS: /* up to speed */ - if (dir) uptr->pos = uptr->pos - 1; /* adjust position */ + if (dir) /* adjust position */ + uptr->pos = uptr->pos - 1; else uptr->pos = uptr->pos + 1; uptr->LASTT = sim_grtime (); /* save time */ if (((int32) uptr->pos < 0) || /* off reel? */ @@ -505,7 +516,8 @@ switch (mot) { /* case on motion */ 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 */ +if (unum != su) /* not sel? done */ + return SCPE_OK; td_slf = 1; /* set single */ td_qlctr = (td_qlctr + 1) % DT_WSIZE; /* count words */ if (td_qlctr == 0) { /* lines mod 4? */ @@ -646,7 +658,8 @@ 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 */ +if (ba >= uptr->hwmark) /* upd length */ + uptr->hwmark = ba + 1; return; } @@ -661,7 +674,8 @@ 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 */ + if (td_setpos (uptr)) /* update pos */ + continue; sim_cancel (uptr); sim_activate (uptr, td_dctime); /* sched decel */ uptr->STATE = STA_DEC | (uptr->STATE & STA_DIR); @@ -729,10 +743,13 @@ 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]; +for (i = 0; i < BOOT_LEN; i++) + M[BOOT_START + i] = boot_rom[i]; saved_PC = BOOT_START; return SCPE_OK; } @@ -756,7 +773,8 @@ t_stat r; uint32 ba, sz; r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* fail? */ +if (r != SCPE_OK) /* fail? */ + return r; if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; if (sim_switches & SWMASK ('F')) /* att 18b? */ @@ -779,8 +797,10 @@ if (uptr->filebuf == NULL) { /* can't alloc? */ } 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"); +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? */ @@ -790,11 +810,14 @@ 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]; + 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; + 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) | @@ -814,9 +837,12 @@ 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); -for (i = 0; i < 4; i++) k = td_set_mtk (MTK_REV_PRE, 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); +for (i = 0; i < 4; i++) + k = td_set_mtk (MTK_REV_PRE, u, k); k = td_set_mtk (MTK_FWD_GRD, u, k); k = td_set_mtk (MTK_REV_BLK, u, k); k = td_set_mtk (MTK_INTER, u, k); @@ -838,7 +864,8 @@ int32 i, k; int32 u = uptr - td_dev.units; uint32 ba; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +if (!(uptr->flags & UNIT_ATT)) + return SCPE_OK; 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); @@ -856,7 +883,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ ba = ba + 3; } /* end loop blk */ if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (i = 0; i < D18_NBSIZE; i++) pdp11b[i] = pdp18b[i]; + for (i = 0; i < D18_NBSIZE; i++) + pdp11b[i] = pdp18b[i]; fxwrite (pdp11b, sizeof (uint16), D18_NBSIZE, uptr->fileref); } diff --git a/PDP8/pdp8_tsc.c b/PDP8/pdp8_tsc.c index 15be1845..38ca4273 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-2005, Robert M Supnik + Copyright (c) 2003-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -118,7 +118,8 @@ switch (IR & 07) { /* decode IR<9:11> */ case 3: /* ECDF */ AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */ - if (tsc_cdf) AC = AC | IOT_SKP; /* if cdf, skip */ + if (tsc_cdf) /* if cdf, skip */ + AC = AC | IOT_SKP; tsc_cdf = 0; break; diff --git a/PDP8/pdp8_tt.c b/PDP8/pdp8_tt.c index bd683ce4..82a5784c 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -153,7 +153,8 @@ switch (IR & 07) { /* decode IR<9:11> */ return (AC | tti_unit.buf); /* return buffer */ case 5: /* KIE */ - if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO); + 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; @@ -175,8 +176,10 @@ t_stat tti_svc (UNIT *uptr) int32 c; sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; +if (c & SCPE_BREAK) /* break? */ + uptr->buf = 0; else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); uptr->pos = uptr->pos + 1; dev_done = dev_done | INT_TTI; /* set done */ diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c index 42ba5a2c..0cb067fa 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-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ ttix,ttox PT08/KL8JA terminal input/output + 19-Nov-08 RMS Revised for common TMXR show routines 07-Jun-06 RMS Added UNIT_IDLE flag 06-Jul-06 RMS Fixed bug in DETACH routine 22-Nov-05 RMS Revised for new terminal processing routines @@ -75,8 +76,6 @@ t_stat ttox_svc (UNIT *uptr); t_stat ttox_reset (DEVICE *dptr); t_stat ttx_attach (UNIT *uptr, char *cptr); t_stat ttx_detach (UNIT *uptr); -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc); void ttx_enbdis (int32 dis); /* TTIx data structures @@ -104,13 +103,14 @@ REG ttix_reg[] = { }; MTAB ttix_mod[] = { - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &ttx_desc }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &ttx_desc }, + &tmxr_dscln, NULL, (void *) &ttx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &ttx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &ttx_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &ttx_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &ttx_desc }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } @@ -198,7 +198,8 @@ switch (pulse) { /* case IR<9:11> */ return (AC | ttix_buf[ln]); /* return buf */ case 5: /* KIE */ - if (AC & 1) int_enable = int_enable | (itti + itto); + if (AC & 1) + int_enable = int_enable | (itti + itto); else int_enable = int_enable & ~(itti + itto); int_req = INT_UPDATE; /* update intr */ break; @@ -221,16 +222,19 @@ t_stat ttix_svc (UNIT *uptr) { int32 ln, c, temp; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; 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*/ +if (ln >= 0) /* got one? rcv enb*/ + ttx_ldsc[ln].rcve = 1; 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? */ + if (temp & SCPE_BREAK) /* break? */ + c = 0; else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags)); ttix_buf[ln] = c; dev_done = dev_done | (INT_TTI1 << ln); @@ -317,7 +321,8 @@ if (ttx_ldsc[ln].conn) { /* connected? */ if (ttx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &ttx_ldsc[ln]; /* get line */ c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags)); - if (c >= 0) tmxr_putc_ln (lp, c); /* output char */ + if (c >= 0) /* output char */ + tmxr_putc_ln (lp, c); tmxr_poll_tx (&ttx_desc); /* poll xmt */ } else { @@ -357,7 +362,8 @@ int32 t; t_stat r; r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ +if (r != SCPE_OK) /* error */ + return r; t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init calib */ sim_activate (uptr, t); /* start poll */ return SCPE_OK; @@ -377,43 +383,12 @@ sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -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; -} - /* Enable/disable device */ void ttx_enbdis (int32 dis) { if (dis) { - ttix_dev.flags = ttox_dev.flags | DEV_DIS; + ttix_dev.flags = ttix_dev.flags | DEV_DIS; ttox_dev.flags = ttox_dev.flags | DEV_DIS; } else { diff --git a/SDS/sds_cpu.c b/SDS/sds_cpu.c index 38c2e804..a8f87db7 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-2007, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -365,7 +365,8 @@ t_stat reason, tr; /* Restore register state */ -if (io_init ()) return SCPE_STOP; /* init IO; conflict? */ +if (io_init ()) /* init IO; conflict? */ + return SCPE_STOP; reason = 0; xfr_req = xfr_req & ~1; /* <0> reserved */ int_req = int_req & ~1; /* <0> reserved */ @@ -384,13 +385,15 @@ while (reason == 0) { /* loop until halted */ } if (sim_interval <= 0) { /* event queue? */ - if (reason = sim_process_event ()) break; /* process */ + if (reason = sim_process_event ()) /* process */ + break; 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 */ + if (reason = chan_process ()) /* process */ + break; int_reqhi = api_findreq (); /* recalc int req */ chan_req = chan_testact (); /* recalc chan act */ } @@ -405,7 +408,8 @@ while (reason == 0) { /* loop until halted */ 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 (hst_lnt) /* record inst */ + inst_hist (tinst, P, HIST_INT); if (pa != VEC_RTCP) { /* normal intr? */ tr = one_inst (tinst, P, save_mode); /* exec intr inst */ if (tr) { /* stop code? */ @@ -436,11 +440,14 @@ while (reason == 0) { /* loop until halted */ 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); + 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; + if (reason != STOP_HALT) + P = save_P; + if (reason == STOP_IONRDY) + reason = 0; } } /* end if r == 0 */ if (reason < 0) { /* mm (fet or ex)? */ @@ -454,7 +461,8 @@ while (reason == 0) { /* loop until halted */ 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); + 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 */ @@ -498,7 +506,8 @@ if (inst & I_POP) { /* POP? */ } else { /* normal POP */ dat = (OV << 23) | dat; /* ov in <0> */ - if (r = Write (0, dat)) return r; + if (r = Write (0, dat)) + return r; } } else { /* mon mode */ @@ -516,170 +525,234 @@ 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &A)) /* get operand */ + return r; break; case LDB: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &B)) return r; /* get operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &B)) /* get operand */ + return r; break; case LDX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &X)) return r; /* get operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &X)) /* get operand */ + return r; break; case STA: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Write (va, A)) return r; /* write operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Write (va, A)) /* write operand */ + return r; break; case STB: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Write (va, B)) return r; /* write operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Write (va, B)) /* write operand */ + return r; break; case STX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Write (va, X)) return r; /* write operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Write (va, X)) /* write operand */ + return r; break; case EAX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (r = Write (va, A)) /* write A */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; dat = AddM24 (dat, A); /* mem + A */ - if (r = Write (va, dat)) return r; /* rewrite */ + if (r = Write (va, dat)) /* rewrite */ + return r; break; case MIN: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; dat = AddM24 (dat, 1); /* mem + 1 */ - if (r = Write (va, dat)) return r; /* rewrite */ + if (r = Write (va, dat)) /* rewrite */ + return r; break; case MUL: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (A == dat) /* if A = op, skip */ + P = (P + 1) & VA_MASK; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (SXT (A) > SXT (dat)) /* if A > op, skip */ + P = (P + 1) & VA_MASK; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (((A ^ dat) & B) == 0) /* if A = op masked */ + P = (P + 1) & VA_MASK; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if ((A & dat) == 0) /* if !(A & op), skip */ + P = (P + 1) & VA_MASK; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if ((B & dat) == 0) /* if !(B & op), skip */ + P = (P + 1) & VA_MASK; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (dat & SIGN) /* if op < 0, skip */ + P = (P + 1) & VA_MASK; break; case SKR: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Write (va, dat)) /* rewrite */ + return r; + if (dat & SIGN) /* if op < 0, skip */ + P = (P + 1) & VA_MASK; break; case SKD: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; if (SXT_EXP (B) < SXT_EXP (dat)) { /* B < dat? */ X = (dat - B) & DMASK; /* X = dat - B */ P = (P + 1) & VA_MASK; /* skip */ @@ -693,65 +766,81 @@ switch (op) { /* case on opcode */ break; case HLT: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; 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 */ + if (exu_cnt > exu_lim) /* too many? */ + return STOP_EXULIM; + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; PCQ_ENTRY; P = va & VA_MASK; /* branch */ break; case BRX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; X = (X + 1) & DMASK; /* incr X */ if (X & I_IND) { /* bit 9 set? */ - if (r = Read (va, &dat)) return r; /* test dest access */ + if (r = Read (va, &dat)) /* test dest access */ + return r; PCQ_ENTRY; P = va & VA_MASK; /* branch */ } break; case BRM: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; 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 */ + if (r = Write (va, dat)) /* write ret word */ + return r; 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 */ + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; 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; + 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 */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; api_dismiss (); /* dismiss hi api */ PCQ_ENTRY; P = dat & VA_MASK; /* branch */ @@ -759,7 +848,8 @@ switch (op) { /* case on opcode */ 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; + if (mon_usr_trap) + return MM_MONUSR; } } else OV = (dat >> 23) & 1; /* restore OV */ @@ -772,25 +862,35 @@ switch (op) { /* case on opcode */ old_B = B; old_X = X; if (inst & 000001211) { /* A change? */ - if (inst & 01000) dat = (~old_A + 1) & DMASK; /* CNA */ + 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); + 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; + if (inst & 00040) + dat = old_X; else dat = 0; - if (inst & 00004) dat = dat | old_A; - if (inst & 00100) B = (B & ~EXPMASK) | (dat & EXPMASK); + 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; + if (inst & 00400) + dat = old_A; else dat = 0; - if (inst & 00020) dat = dat | old_B; - if (inst & 00100) X = SXT_EXP (dat) & DMASK; + if (inst & 00020) + dat = dat | old_B; + if (inst & 00100) + X = SXT_EXP (dat) & DMASK; else X = dat; } break; @@ -798,27 +898,34 @@ switch (op) { /* case on opcode */ /* 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; + 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 */ + if (r = EaSh (inst, &va)) /* decode eff addr */ + return r; 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); + if (sc) + ShfR48 (sc, (A & SIGN)? DMASK: 0); break; case 04: /* right cycle */ sc = sc % 48; /* mod 48 */ - if (sc) RotR48 (sc); + if (sc) + RotR48 (sc); break; case 05: /* right logical */ - if (sc) ShfR48 (sc, 0); + if (sc) + ShfR48 (sc, 0); break; default: CRETINS; /* invalid inst */ @@ -827,23 +934,28 @@ switch (op) { /* case on opcode */ break; case LSH: - if (r = EaSh (inst, &va)) return r; /* decode eff addr */ + if (r = EaSh (inst, &va)) /* decode eff addr */ + return r; 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; + 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; + if ((A ^ dat) & SIGN) + OV = 1; } break; case 02: /* normalize */ - if (sc > 48) sc = 48; + if (sc > 48) + sc = 48; for (i = 0; i < sc; i++) { /* until max count */ - if ((A ^ (A << 1)) & SIGN) break; + if ((A ^ (A << 1)) & SIGN) + break; A = ((A << 1) | (B >> 23)) & DMASK; B = (B << 1) & DMASK; } @@ -851,12 +963,15 @@ switch (op) { /* case on opcode */ break; case 04: /* left cycle */ sc = sc % 48; /* mod 48 */ - if (sc) RotR48 (48 - sc); /* rotate */ + if (sc) /* rotate */ + RotR48 (48 - sc); break; case 06: /* cycle normalize */ - if (sc > 48) sc = 48; + if (sc > 48) + sc = 48; for (i = 0; i < sc; i++) { /* until max count */ - if ((A ^ (A << 1)) & SIGN) break; + if ((A ^ (A << 1)) & SIGN) + break; old_A = A; /* cyclic shift */ A = ((A << 1) | (B >> 23)) & DMASK; B = ((B << 1) | (old_A >> 23)) & DMASK; @@ -872,57 +987,79 @@ switch (op) { /* case on opcode */ /* 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 */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (r = op_miwy (inst, dat)) /* process inst */ + return r; 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 */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = op_wyim (inst, &dat)) /* process inst */ + return r; + 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 */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = op_eomd (inst)) /* process inst */ + return r; 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 */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = Read (va, &dat)) /* get operand */ + return r; + if (r = op_pot (dat)) /* process inst */ + return r; 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 */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = Ea (inst, &va)) /* decode eff addr */ + return r; + if (r = op_pin (&dat)) /* process inst */ + return r; + if (r = Write (va, dat)) /* write result */ + return r; 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; + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; + if (r = op_sks (inst, &dat)) /* process inst */ + return r; + if (dat) + P = (P + 1) & VA_MASK; break; default: - if (!nml_mode && usr_mode) return MM_PRVINS; /* usr? priv viol */ + if (!nml_mode && usr_mode) /* priv inst */ + return MM_PRVINS; CRETINS; /* invalid inst */ break; } @@ -940,13 +1077,16 @@ 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); + 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 */ + if (hst_lnt) /* record */ + hst[hst_p].ea = *addr; return SCPE_OK; } - if (r = Read (va, &wd)) return r; /* read ind; fails? */ + if (r = Read (va, &wd)) /* read ind; fails? */ + return r; va = (va & VA_USR) | (wd & XVA_MASK); } return STOP_INDLIM; /* too many indirects */ @@ -963,14 +1103,17 @@ 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 */ + if (wd & I_IDX) /* 9b indexing */ + *addr = (va & (VA_MASK & ~I_SHFMSK)) | ((va + X) & I_SHFMSK); else *addr = va & VA_MASK; - if (hst_lnt) hst[hst_p].ea = *addr; /* record */ + if (hst_lnt) /* record */ + hst[hst_p].ea = *addr; 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? */ + if (wd & I_IDX) + va = (va & VA_USR) | ((va + X) & VA_MASK); + if (r = Read (va, &wd)) /* read ind; fails? */ + return r; va = (va & VA_USR) | (wd & XVA_MASK); } return STOP_INDLIM; /* too many indirects */ @@ -984,20 +1127,24 @@ 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 */ + if (va < 020000) /* first 8K: 1 for 1 */ + pa = va; + else if (va < 030000) /* next 4K: ext EM2 */ + pa = va + em2_dyn; 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 */ + if (map == MAP_PROT) /* prot? no access */ + return MM_NOACC; 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 */ + if (map & MAP_PROT) + return MM_NOACC; /* prot? no access */ pa = map | (va & VA_POFF); /* map address */ } *dat = M[pa]; /* return word */ @@ -1012,15 +1159,18 @@ 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 */ + if (va < 020000) /* first 8K: 1 for 1 */ + pa = va; + else if (va < 030000) /* next 4K: ext EM2 */ + pa = va + em2_dyn; 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 */ + if (map == MAP_PROT) /* zero? no access */ + return MM_NOACC; else return MM_WRITE; /* else, write prot */ } pa = map | (va & VA_POFF); /* map address */ @@ -1028,10 +1178,12 @@ else if (usr_mode || (va & VA_USR)) { /* user mapping? */ 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 */ + if (map & MAP_PROT) /* prot? no access */ + return MM_NOACC; pa = map | (va & VA_POFF); /* map address */ } -if (MEM_ADDR_OK (pa)) M[pa] = dat; +if (MEM_ADDR_OK (pa)) + M[pa] = dat; return SCPE_OK; } @@ -1042,20 +1194,29 @@ 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')) /* -n: normal */ + nml = 1; +else if (sw & SWMASK ('X')) /* -x: mon */ + nml = usr = 0; +else if (sw & SWMASK ('U')) { /* -u: user */ + nml = 0; + usr = 1; + } +else if (!(sw & SWMASK ('V'))) /* -v: curr */ + return va; 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 */ + if (va < 020000) /* first 8K: 1 for 1 */ + pa = va; + else if (va < 030000) /* next 4K: ext EM2 */ + pa = va + em2_dyn; 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? */ + if (map == MAP_PROT) /* no access page? */ + return MAXMEMSIZE + 1; pa = (map & ~MAP_PROT) | (va & VA_POFF); /* map address */ } return pa; @@ -1066,16 +1227,19 @@ return pa; 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> */ +if (t > DMASK) /* carry to X<0> */ + X = X | SIGN; else X = X & ~SIGN; -if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ +if (((s1 ^ ~s2) & (s1 ^ t)) /* overflow */ + & SIGN) OV = 1; return t & DMASK; } uint32 AddM24 (uint32 s1, uint32 s2) { uint32 t = s1 + s2; /* add */ -if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ +if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) /* overflow */ + OV = 1; return t & DMASK; } @@ -1102,7 +1266,8 @@ if ((s1 ^ s2) & SIGN) { B = ((B ^ DMASK) + 1) & DMASK; A = ((A ^ DMASK) + (B == 0)) & DMASK; } -else if (A & SIGN) OV = 1; +else if (A & SIGN) + OV = 1; return; } @@ -1126,7 +1291,8 @@ if (TSTS (dvdh)) { /* dvd < 0? */ } if ((dvdh > dvr) || /* divide fail? */ ((dvdh == dvr) && dvdl) || - ((dvdh == dvr) && !TSTS (ar ^ m))) OV = 1; + ((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 */ @@ -1137,11 +1303,14 @@ for (i = 0; i < 23; i++) { /* 23 iterations */ else dvdh = (dvdh + dvr) & DMASK; /* sign was -, add */ } quo = quo << 1; /* shift quo */ -if (dvdh & SIGN) dvdh = (dvdh + dvr) & DMASK; /* last op -? restore */ +if (dvdh & SIGN) /* last op -? restore */ + dvdh = (dvdh + dvr) & DMASK; else quo = quo | 1; /* +, set quo bit */ -if (TSTS (ar ^ m)) A = NEG (quo); /* sign of quo */ +if (TSTS (ar ^ m)) /* sign of quo */ + A = NEG (quo); else A = quo; /* A = quo */ -if (TSTS (ar)) B = NEG (dvdh); /* sign of rem */ +if (TSTS (ar)) /* sign of rem */ + B = NEG (dvdh); else B = dvdh; /* B = rem */ return; } @@ -1164,7 +1333,8 @@ return; void ShfR48 (uint32 sc, uint32 sgn) { -if (sc >= 48) A = B = sgn; +if (sc >= 48) + A = B = sgn; if (sc >= 24) { sc = sc - 24; B = ((A >> sc) | (sgn << (24 - sc))) & DMASK; @@ -1228,8 +1398,10 @@ mon_map[4] = ((EM2 & 07) << 12); mon_map[5] = ((EM2 & 07) << 12) + (1 << VA_V_PN); mon_map[6] = (RL4 << 5) & MAP_PAGE; mon_map[7] = (RL4 << 11) & MAP_PAGE; -if (mon_map[6] == 0) mon_map[6] = MAP_PROT; -if (mon_map[7] == 0) mon_map[7] = MAP_PROT; +if (mon_map[6] == 0) + mon_map[6] = MAP_PROT; +if (mon_map[7] == 0) + mon_map[7] = MAP_PROT; return; } @@ -1241,7 +1413,8 @@ 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; + if ((t >> i) & 1) + return i; } return 0; /* none */ } @@ -1284,7 +1457,8 @@ api_lvl = 0; api_lvlhi = 0; alert = 0; pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; @@ -1297,9 +1471,12 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) uint32 pa; pa = RelocC (addr, sw); -if (pa > MAXMEMSIZE) return SCPE_REL; -if (pa >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[pa] & DMASK; +if (pa > MAXMEMSIZE) + return SCPE_REL; +if (pa >= MEMSIZE) + return SCPE_NXM; +if (vptr != NULL) + *vptr = M[pa] & DMASK; return SCPE_OK; } @@ -1310,8 +1487,10 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) uint32 pa; pa = RelocC (addr, sw); -if (pa > MAXMEMSIZE) return SCPE_REL; -if (pa >= MEMSIZE) return SCPE_NXM; +if (pa > MAXMEMSIZE) + return SCPE_REL; +if (pa >= MEMSIZE) + return SCPE_NXM; M[pa] = val & DMASK; return SCPE_OK; } @@ -1325,11 +1504,13 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 037777) != 0)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +for (i = val; i < MEMSIZE; i++) + mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; return SCPE_OK; } @@ -1342,9 +1523,11 @@ extern DEVICE drm_dev, mux_dev, muxl_dev; extern UNIT drm_unit, mux_unit; extern DIB mux_dib; -if ((cpu_unit.flags & UNIT_GENIE) == (uint32) val) return SCPE_OK; +if ((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 */ + (mux_unit.flags & UNIT_ATT)) /* can't do it */ + return SCPE_NOFNC; if (val) { /* Genie? */ drm_dev.flags = drm_dev.flags & ~DEV_DIS; /* enb drum */ mux_dev.flags = mux_dev.flags & ~DEV_DIS; /* enb mux */ @@ -1367,7 +1550,8 @@ return SCPE_OK; t_stat rtc_svc (UNIT *uptr) { -if (rtc_pie) int_req = int_req | INT_RTCP; /* set pulse intr */ +if (rtc_pie) /* set pulse intr */ + int_req = int_req | INT_RTCP; sim_activate (&rtc_unit, sim_rtcn_calb (rtc_tps, TMR_RTC)); /* reactivate */ return SCPE_OK; } @@ -1380,14 +1564,20 @@ 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 */ +if (op == MIN) /* incr */ + val = 1; +else if (op == SKR) /* decr */ + val = DMASK; 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 */ +if (r = Ea (inst, &va)) /* decode eff addr */ + return r; +if (r = Read (va, &dat)) /* get operand */ + return r; 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 */ +if (r = Write (va, dat)) /* rewrite */ + return r; +if (dat == 0) /* set clk sync int */ + int_req = int_req | INT_RTCS; return SCPE_OK; } @@ -1404,8 +1594,10 @@ return SCPE_OK; t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; rtc_tps = val; return SCPE_OK; } @@ -1423,7 +1615,8 @@ return SCPE_OK; void inst_hist (uint32 ir, uint32 pc, uint32 tp) { hst_p = (hst_p + 1); /* next entry */ -if (hst_p >= hst_lnt) hst_p = 0; +if (hst_p >= hst_lnt) + hst_p = 0; hst[hst_p].typ = tp | (OV << 4); hst[hst_p].pc = pc; hst[hst_p].ir = ir; @@ -1442,12 +1635,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].typ = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -1456,7 +1651,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -1475,14 +1671,17 @@ extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); static char *cyc[] = { " ", " ", "INT", "TRP" }; -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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 */ @@ -1490,7 +1689,8 @@ for (k = 0; k < lnt; k++) { /* print specified */ 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, " "); + 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) diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h index 4b715f15..b3dc6405 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-2005, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/SDS/sds_drm.c b/SDS/sds_drm.c index 9c468dfa..1e0bfc42 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-2005, Robert M. Supnik + Copyright (c) 2002-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -153,15 +153,19 @@ int32 t, op = inst & 07700; switch (fnc) { case IO_CONN: /* connect */ - if (op == 00400) return drm_reset (&drm_dev); /* EOM 404 = reset */ + if (op == 00400) /* EOM 404 = reset */ + return drm_reset (&drm_dev); if (op == 00500) { /* EOM 504 = read DA */ - if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */ + 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? */ + if (t < DRM_NUMGP) /* in gap? */ + M[DRM_AD] = DRM_NUMWD - t; 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 */ + if (sim_is_active (&drm_unit)) /* must be idle */ + return SCPE_OK; drm_sta = DRM_SFET; /* state = fetch */ sim_activate (&drm_unit, drm_ftime); /* activate */ } @@ -204,7 +208,8 @@ if (drm_sta != DRM_SXFR) { /* fetch drum prog? */ 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 */ + if (t <= 0) /* add trk lnt */ + t = t + (DRM_NUMSC * DRM_PHYWD); sim_activate (&drm_unit, t * drm_xtime); /* activate */ } else { @@ -228,7 +233,8 @@ if (drm_sta != DRM_SXFR) { /* fetch drum prog? */ return SCPE_OK; case DRM_EIE: /* end, int if err */ - if (!drm_err) return SCPE_OK; + if (!drm_err) + return SCPE_OK; case DRM_EIU: /* end, int uncond */ int_req = int_req | INT_DRM; @@ -245,28 +251,32 @@ else { /* transfer word */ 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; + 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 */ + if (drm_da >= DRM_SIZE) /* wrap */ + drm_da = 0; 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); + 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 >= uptr->hwmark) + uptr->hwmark = drm_da + 1; } #endif drm_sta = DRM_SFET; /* back to fetch */ diff --git a/SDS/sds_dsk.c b/SDS/sds_dsk.c index 8165f500..cf9d41ea 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-2005, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -157,24 +157,29 @@ 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? */ + if (new_ch != dsk_dib.chan) /* wrong chan? */ + return SCPE_IERR; 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 */ + for (i = 0; i < DSK_NUMWD; i++) /* clear buffer */ + dsk_buf[i] = 0; xfr_req = xfr_req & ~XFR_DSK; /* clr xfr flg */ sim_activate (&dsk_unit, dsk_stime); /* activate */ break; case IO_EOM1: /* EOM mode 1 */ new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ - if (inst & 07600) CRETIOP; /* inv inst? */ + if (new_ch != dsk_dib.chan) /* wrong chan? */ + return SCPE_IERR; + if (inst & 07600) /* inv inst? */ + CRETIOP; alert = POT_DSK; /* alert */ break; case IO_DISC: /* disconnect */ dsk_end_op (0); /* normal term */ - if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */ + if (inst & DEV_OUT) + return dsk_fill (inst); /* fill write */ break; case IO_WREOR: /* write eor */ @@ -183,7 +188,8 @@ switch (fnc) { /* case on function */ case IO_SKS: /* SKS */ new_ch = I_GETSKCH (inst); /* sks chan */ - if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong 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)) || @@ -198,7 +204,8 @@ switch (fnc) { /* case on function */ 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 */ + if (r = dsk_read_buf (inst)) /* read sector */ + return r; } dsk_wptr = dsk_bptr >> 2; /* word pointer */ dsk_byte = dsk_bptr & 03; /* byte in word */ @@ -212,7 +219,8 @@ switch (fnc) { /* case on function */ 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 */ + if (r = dsk_write_buf (inst)) /* write sector */ + return r; } dsk_wptr = dsk_bptr >> 2; /* word pointer */ dsk_buf[dsk_wptr] = ((dsk_buf[dsk_wptr] << 6) | (*dat & 077)) & DMASK; @@ -240,11 +248,13 @@ t_stat pot_dsk (uint32 num, uint32 *dat) { int32 st; -if (sim_is_active (&dsk_unit)) return STOP_IONRDY; /* busy? wait */ +if (sim_is_active (&dsk_unit)) /* busy? wait */ + return STOP_IONRDY; 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 */ +if (st == 0 /* min time */ + ) st = dsk_stime; sim_activate (&dsk_unit, st); /* set timer */ dsk_unit.cyl = dsk_unit.cyl | DSK_SIP; /* seeking */ return SCPE_OK; @@ -256,7 +266,8 @@ 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 (dsk_op) /* sched r/w */ + sim_activate (&dsk_unit, dsk_stime); } else { xfr_req = xfr_req | XFR_DSK; /* set xfr req */ @@ -282,7 +293,8 @@ 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; +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 */ @@ -317,7 +329,8 @@ if (ferror (dsk_unit.fileref)) { /* error? */ } 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 */ +for (i = 0; i < DSK_NUMWD; i++) /* clear buffer */ + dsk_buf[i] = 0; return SCPE_OK; } @@ -332,7 +345,8 @@ 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? */ +if (dsk_bptr == 0) /* no fill? */ + return SCPE_OK; for ( ; dsk_bptr < pktend; dsk_bptr++) { /* fill packet */ int32 dsk_wptr = dsk_bptr >> 2; dsk_buf[dsk_wptr] = (dsk_buf[dsk_wptr] << 6) & DMASK; @@ -346,7 +360,8 @@ return dsk_write_buf (dev); /* write sec */ void dsk_end_op (uint32 fl) { -if (fl) chan_set_flag (dsk_dib.chan, fl); /* set flags */ +if (fl) /* set flags */ + chan_set_flag (dsk_dib.chan, fl); dsk_op = 0; /* clear op */ xfr_req = xfr_req & ~XFR_DSK; /* clear xfr */ sim_cancel (&dsk_unit); /* stop */ @@ -371,6 +386,7 @@ dsk_bptr = dsk_blnt = 0; xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ sim_cancel (&dsk_unit); /* deactivate */ dsk_unit.cyl = 0; -for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ +for (i = 0; i < DSK_NUMWD; i++) /* clear buffer */ + dsk_buf[i] = 0; return SCPE_OK; } diff --git a/SDS/sds_io.c b/SDS/sds_io.c index 9e2e37e4..241d7ce7 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-2005, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -259,7 +259,8 @@ 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 */ + if (dev == 0) /* no device? dead */ + return STOP_INVIOP; return STOP_IONRDY; /* hang until full */ } *dat = chan_war[ch]; /* get data */ @@ -275,13 +276,15 @@ 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 */ + if (dev == 0) /* no device? dead */ + return STOP_INVIOP; 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 */ + if (VLD_DEV (dev, ch)) /* wake channel */ + SET_XFR (dev, ch); chan_flag[ch] = chan_flag[ch] & ~CHF_OWAK; /* clear wake */ } return SCPE_OK; @@ -292,7 +295,8 @@ t_stat op_pin (uint32 *dat) uint32 al = alert; /* local copy */ alert = 0; /* clear alert */ -if ((al == 0) || (dev_alt[al].pin == NULL)) CRETIOP; /* inv alert? */ +if ((al == 0) || (dev_alt[al].pin == NULL)) /* inv alert? */ + CRETIOP; return dev_alt[al].pin (al, dat); /* PIN from dev */ } @@ -301,7 +305,8 @@ t_stat op_pot (uint32 dat) uint32 al = alert; /* local copy */ alert = 0; /* clear alert */ -if ((al == 0) || (dev_alt[al].pot == NULL)) CRETIOP; /* inv alert? */ +if ((al == 0) || (dev_alt[al].pot == NULL)) /* inv alert? */ + CRETIOP; return dev_alt[al].pot (al, &dat); /* POT to dev */ } @@ -319,19 +324,23 @@ 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 */ + if (ch_dev) /* chan act? err */ + CRETIOP; + if (INV_DEV (dev, ch)) /* inv dev? err */ + CRETDEV; 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 (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 */ + if (chan_flag[ch] & CHF_24B) /* 24B? 1 ch/wd */ + chan_cpw[ch] = 0; 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 */ @@ -345,7 +354,8 @@ switch (mod) { 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 */ + if (ch >= CHAN_E) /* DACC? ext */ + inst = inst | CHM_CE; chan_mode[ch] = inst; /* save mode */ chan_mar[ch] = (CHM_GETHMA (inst) << 14) | /* get hi mar */ (chan_mar[ch] & CHI_M_MA); @@ -353,7 +363,8 @@ switch (mod) { (chan_wcr[ch] & CHI_M_WC); } else if (dev) { /* dev EOM */ - if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ + if (INV_DEV (dev, ch)) /* inv dev? err */ + CRETDEV; return dev_dsp[dev][ch] (IO_EOM1, inst, NULL); } else { /* chan EOM */ @@ -362,8 +373,10 @@ switch (mod) { 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 == 002000) /* alert addr */ + alert = POT_ADRY + ch; + else if (inst == 001000) /* alert DCR */ + alert = POT_DCRY + ch; 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? */ @@ -381,25 +394,38 @@ switch (mod) { 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; + 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 & 00001) /* clr OV */ + OV = 0; + if (inst & 00002) /* ion */ + ion = 1; + else if (inst & 00004) /* iof */ + ion = 0; + if ((inst & 00010) && (((X >> 1) ^ X) & EXPS)) + OV = 1; + if (inst & 00020) /* alert sys int */ + alert = POT_SYSI; + if (inst & 00100) /* arm clk pls */ + rtc_pie = 1; + else if (inst & 00200) /* disarm pls */ + rtc_pie = 0; + if ((inst & 01400) == 01400) /* alert RL4 */ + alert = POT_RL4; + else if (inst & 00400) /* alert RL1 */ + alert = POT_RL1; + else if (inst & 01000) /* alert RL2 */ + alert = POT_RL2; if (inst & 02000) { /* nml to mon */ nml_mode = usr_mode = 0; - if (inst & 00400) mon_usr_trap = 1; + if (inst & 00400) + mon_usr_trap = 1; } break; @@ -424,21 +450,24 @@ uint32 dev = inst & DEV_MASK; /* get dev # */ *dat = 0; if ((ch == 4) && !(inst & 037774)) { /* EM test */ if (((inst & 0001) && (EM2 != 2)) || - ((inst & 0002) && (EM3 != 3))) *dat = 1; + ((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 */ + if (INV_DEV (dev, ch)) /* inv dev? err */ + CRETDEV; 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; + ((inst & 00400) && (chan_flag[ch] & CHF_IREC))) + *dat = 1; } break; @@ -457,12 +486,14 @@ switch (mod) { ((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; + ((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); + if (dev3_dsp[dev]) + dev3_dsp[dev] (IO_SKS, inst, dat); else CRETINS; } /* end case */ @@ -547,8 +578,10 @@ 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? */ + if (r) /* error? */ + chan_flag[ch] = chan_flag[ch] | CHF_ERR; + if (chan_flag[ch] & CHF_24B) /* 24B? */ + chan_war[ch] = dat; 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; @@ -563,15 +596,18 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ 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]; + 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 (TST_EOR (ch)) /* eor? */ + return chan_eor (ch); if (tfnc == CHM_COMP) { /* C: EOW, intr */ - if (ion) int_req = int_req | int_zc[ch]; + if (ion) + int_req = int_req | int_zc[ch]; } else if (tfnc & CHM_SGNL) /* Sx: error */ chan_flag[ch] = chan_flag[ch] | CHF_ERR; @@ -580,7 +616,8 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ } /* end if full */ } /* end if xfr */ if (TST_EOR (ch)) { /* end record? */ - if (tfnc == CHM_COMP) chan_flush_war (ch); /* C: fill war */ + if (tfnc == CHM_COMP) /* C: fill war */ + chan_flush_war (ch); else if (chan_cnt[ch]) { /* RX, CX: fill? */ chan_flush_war (ch); /* fill war */ if (chan_flag[ch] & CHF_ILCE) /* ilce on? store */ @@ -606,7 +643,8 @@ void chan_flush_war (int32 ch) int32 i = (chan_cpw[ch] - chan_cnt[ch]) + 1; if (i) { - if (chan_flag[ch] & CHF_24B) chan_war[ch] = 0; + if (chan_flag[ch] & CHF_24B) + chan_war[ch] = 0; else if (chan_flag[ch] & CHF_12B) chan_war[ch] = (chan_war[ch] << 12) & DMASK; else chan_war[ch] = (chan_war[ch] << (i * 6)) & DMASK; @@ -637,7 +675,8 @@ 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 (INV_DEV (dev, ch)) /* invalid dev? */ + CRETIOP; if (chan_cnt[ch] == 0) { /* buffer empty? */ if (chan_flag[ch] & CHF_ILCE) { /* interlace on? */ chan_war[ch] = ReadP (chan_mar[ch]); @@ -647,13 +686,15 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ } else { /* ilce off */ CLR_XFR (dev, ch); /* cant xfr */ - if (TST_EOR (dev)) return chan_eor (ch); /* EOR? */ + if (TST_EOR (dev)) /* EOR? */ + return chan_eor (ch); 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? */ + if (chan_flag[ch] & CHF_24B) /* 24B? */ + dat = chan_war[ch]; 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 */ @@ -663,13 +704,15 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ 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 (r) /* error? */ + chan_flag[ch] = chan_flag[ch] | CHF_ERR; 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]; + if (ion) + int_req = int_req | int_zc[ch]; dev_disc (ch, dev); /* disconnnect */ } /* end if comp */ else { /* extended */ @@ -691,10 +734,12 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ 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 */ + else if (ion) /* no TOP, EOW intr */ + int_req = int_req | int_zc[ch]; } /* end if cnt */ } /* end if xfr */ -if (TST_EOR (ch)) return chan_eor (ch); /* eor rcvd? */ +if (TST_EOR (ch)) /* eor rcvd? */ + return chan_eor (ch); return r; } @@ -734,13 +779,15 @@ return SCPE_OK; t_stat dev_disc (uint32 ch, uint32 dev) { chan_uar[ch] = 0; /* disconnect */ -if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_DISC, dev, NULL); +if (dev_dsp[dev][ch]) + return dev_dsp[dev][ch] (IO_DISC, dev, NULL); return SCPE_OK; } t_stat dev_wreor (uint32 ch, uint32 dev) { -if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_WREOR, dev, NULL); +if (dev_dsp[dev][ch]) + return dev_dsp[dev][ch] (IO_WREOR, dev, NULL); chan_flag[ch] = chan_flag[ch] | CHF_EOR; /* set eor */ return SCPE_OK; } @@ -756,9 +803,11 @@ 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 */ + if (dev & DEV_OUT) /* write */ + r = chan_write (i); else r = chan_read (i); /* read */ - if (r) return r; + if (r) + return r; } } return SCPE_OK; @@ -772,7 +821,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; } @@ -794,7 +844,8 @@ return; void chan_set_flag (int32 ch, uint32 fl) { -if ((ch >= 0) && (ch < NUM_CHAN)) chan_flag[ch] = chan_flag[ch] | fl; +if ((ch >= 0) && (ch < NUM_CHAN)) + chan_flag[ch] = chan_flag[ch] | fl; return; } @@ -802,7 +853,8 @@ return; void chan_set_uar (int32 ch, uint32 dev) { -if ((ch >= 0) && (ch < NUM_CHAN)) chan_uar[ch] = dev & DEV_MASK; +if ((ch >= 0) && (ch < NUM_CHAN)) + chan_uar[ch] = dev & DEV_MASK; return; } @@ -810,7 +862,8 @@ return; void chan_disc (int32 ch) { -if ((ch >= 0) && (ch < NUM_CHAN)) chan_uar[ch] = 0; +if ((ch >= 0) && (ch < NUM_CHAN)) + chan_uar[ch] = 0; return; } @@ -843,15 +896,20 @@ DEVICE *dptr; DIB *dibp; int32 i; -if (sptr == NULL) return SCPE_ARG; /* valid args? */ -if (uptr == NULL) return SCPE_IERR; +if (sptr == NULL) /* valid args? */ + return SCPE_ARG; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +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? */ + if (val && !(val & (1 << i))) /* legal? */ + return SCPE_ARG; dibp->chan = i; /* store new */ return SCPE_OK; } @@ -864,11 +922,14 @@ t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr; DIB *dibp; -if (uptr == NULL) return SCPE_IERR; +if (uptr == NULL) + return SCPE_IERR; dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; fprintf (st, "channel=%s", chname[dibp->chan]); return SCPE_OK; } @@ -896,21 +957,24 @@ for (i = 0; i < NUM_CHAN; 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? */ + if ((dibp == NULL) || (dptr->flags & DEV_DIS)) /* exist, enabled? */ + continue; ch = dibp->chan; /* get channel */ dev = dibp->dev; /* get device num */ - if (ch < 0) dev3_dsp[dev] = dibp->iop; /* special device */ + if (ch < 0) /* special device */ + dev3_dsp[dev] = dibp->iop; else { - if (dibp->tplt == NULL) return TRUE; /* must have template */ + if (dibp->tplt == NULL) /* must have template */ + return TRUE; 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); + 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 */ diff --git a/SDS/sds_lp.c b/SDS/sds_lp.c index b8dd52ee..0de82e70 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-2007, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ lpt line printer + 24-Nov-08 RMS Fixed loss of carriage control position on space op 19-Jan-07 RMS Added UNIT_TEXT flag 25-Apr-03 RMS Revised for extended file support */ @@ -62,7 +63,8 @@ DEVICE lpt_dev; t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat lpt_crctl (int32 ch); +t_stat lpt_crctl (UNIT *uptr, int32 ch); +t_stat lpt_space (UNIT *uptr, int32 cnt); t_stat lpt_status (UNIT *uptr); t_stat lpt_bufout (UNIT *uptr); void lpt_end_op (int32 fl); @@ -136,8 +138,10 @@ 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 */ + if (new_ch != lpt_dib.chan) /* wrong chan? */ + return SCPE_IERR; + for (i = 0; i < LPT_WIDTH; i++) /* clr buffer */ + lpt_buf[i] = 0; lpt_bptr = 0; /* clr buf ptr */ lpt_err = 0; /* err = 0 */ xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ @@ -147,7 +151,8 @@ 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 (new_ch != lpt_dib.chan) /* wrong chan? */ + CRETIOP; if (inst & 0400) { /* space? */ lpt_spc = inst; /* save instr */ lpt_sta = lpt_sta | SET_SPC; /* need space */ @@ -167,17 +172,20 @@ switch (fnc) { /* case function */ case IO_SKS: /* SKS */ new_ch = I_GETSKCH (inst); /* sks chan */ - if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */ + if (new_ch != lpt_dib.chan) /* wrong chan? */ + return SCPE_IERR; 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 */ + (t == 004) && !lpt_err) /* 11062: !err */ + *dat = 1; 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 */ + if (lpt_bptr < LPT_WIDTH) /* store data */ + lpt_buf[lpt_bptr++] = asc; lpt_sta = lpt_sta | SET_XFR; /* need xfr */ sim_activate (&lpt_unit, lpt_ctime); /* start ch timer */ break; @@ -194,13 +202,9 @@ return SCPE_OK; t_stat lpt_svc (UNIT *uptr) { t_stat r = SCPE_OK; -static const char *lpt_stabl[] = { - "\r", "\n", "\n\n", "\n\n\n", - "\n\n\n\n", "\n\n\n\n\n", - "\n\n\n\n\n\n", "\n\n\n\n\n\n\n" - }; -if (lpt_sta & SET_XFR) chan_set_ordy (lpt_dib.chan); /* need lpt xfr? */ +if (lpt_sta & SET_XFR) /* need lpt xfr? */ + chan_set_ordy (lpt_dib.chan); if (lpt_sta & SET_EOR) { /* printing? */ chan_set_flag (lpt_dib.chan, CHF_EOR); /* set eor flg */ r = lpt_bufout (uptr); /* output buf */ @@ -209,8 +213,8 @@ 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 */ + lpt_space (uptr, ln); /* upspace */ + else lpt_crctl (uptr, ln); /* carriage ctl */ } r = lpt_status (uptr); /* update status */ } @@ -257,7 +261,8 @@ return SCPE_OK; void lpt_end_op (int32 fl) { -if (fl) chan_set_flag (lpt_dib.chan, fl); /* set flags */ +if (fl) /* set flags */ + chan_set_flag (lpt_dib.chan, fl); xfr_req = xfr_req & ~XFR_LPT; /* clear xfr */ sim_cancel (&lpt_unit); /* stop */ if (fl & CHF_ERR) { /* error? */ @@ -269,25 +274,42 @@ return; /* Carriage control */ -t_stat lpt_crctl (int32 ch) +t_stat lpt_crctl (UNIT *uptr, int32 ch) { int32 i, j; if ((ch == 1) && CHP (ch, lpt_cct[0])) { /* top of form? */ - fputs ("\f\n", lpt_unit.fileref); /* ff + nl */ + fputs ("\f\n", uptr->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 */ + 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); + for (j = 0; j < i; j++) + fputc ('\n', uptr->fileref); return SCPE_OK; } } return STOP_CCT; /* runaway channel */ } +/* Spacing */ + +t_stat lpt_space (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_ccp = (lpt_ccp + cnt) % lpt_ccl; + } +return SCPE_OK; +} + /* Reset routine */ t_stat lpt_reset (DEVICE *dptr) diff --git a/SDS/sds_mt.c b/SDS/sds_mt.c index d3e4347c..ea9c83bc 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-2006, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -193,18 +193,21 @@ 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 (new_ch != mt_dib.chan) /* wrong chan? */ + return SCPE_IERR; if (mt_gap) { /* in gap? */ mt_gap = 0; /* clr gap flg */ sim_cancel (uptr); /* cancel timer */ } - else if (sim_is_active (uptr)) CRETIOP; /* busy? */ + else if (sim_is_active (uptr)) /* busy? */ + CRETIOP; 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? */ + (inst & CHC_REV)) /* rw & rev? */ + return STOP_INVIOP; mt_inst = inst; /* save inst */ if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */ chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */ @@ -214,7 +217,8 @@ 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? */ + if (new_ch != mt_dib.chan) /* wrong chan? */ + CRETIOP; t = inst & 07670; /* get command */ if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */ sim_tape_rewind (uptr); /* rewind unit */ @@ -222,27 +226,31 @@ switch (fnc) { /* case function */ 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 */ + ((mt_inst & DEV_OUT) == 0)) + mt_skip = 1; /* set flag */ else CRETINS; break; case IO_DISC: /* disconnect */ sim_cancel (uptr); /* no more xfr's */ if (inst & DEV_OUT) { /* write? */ - if (r = mt_wrend (inst)) return r; /* end record */ + if (r = mt_wrend (inst)) /* end record */ + return r; } 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 */ + if (r = mt_wrend (inst)) /* end record */ + return r; mt_gap = 1; /* in gap */ sim_activate (uptr, mt_gtime); /* start timer */ break; case IO_SKS: /* SKS */ new_ch = I_GETSKCH (inst); /* get chan # */ - if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */ + if (new_ch != mt_dib.chan) /* wrong chan? */ + return SCPE_IERR; if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */ t = I_GETSKCND (inst); /* get skip cond */ switch (t) { /* case sks cond */ @@ -281,22 +289,27 @@ switch (fnc) { /* case function */ 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? */ + if ((r != SCPE_OK) || (mt_blnt == 0)) /* err, inv reclnt? */ + return r; } uptr->botf = 0; /* off BOT */ - if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */ + if (mt_inst & CHC_REV) /* get next rev */ + chr = mtxb[--mt_bptr] & 077; else chr = mtxb[mt_bptr++] & 077; /* get next fwd */ - if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr];/* bcd? */ + if (!(mt_inst & CHC_BIN)) /* bcd? */ + chr = bcd_to_sds[chr]; *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? */ + (mt_bptr >= mt_blnt)) /* recd done? */ + mt_readend (uptr); 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_inst & CHC_BIN)) /* bcd? */ + chr = sds_to_bcd[chr]; if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */ break; @@ -315,7 +328,8 @@ 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 if (mt_skip) /* skip record */ + mt_readend (uptr); else { /* normal xfr */ xfr_req = xfr_req | XFR_MT0; /* set xfr req */ sim_activate (uptr, mt_ctime); /* reactivate */ @@ -350,9 +364,12 @@ if (st == MTSE_TMK) { /* tape mark? */ } 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 */ + if (st == MTSE_IOERR) /* IO error? */ + return SCPE_IOERR; + if (st == MTSE_INVRL) /* inv rec lnt? */ + return SCPE_MTRLNT; + if (st == MTSE_EOM) /* eom? set eot */ + uptr->eotf = 1; return SCPE_OK; } mt_blnt = tbc; /* set buf lnt */ @@ -366,7 +383,8 @@ 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? */ +if (mt_eof) /* EOF? */ + chan_disc (mt_dib.chan); else { mt_gap = 1; /* no, in gap */ sim_activate (uptr, mt_gtime); /* start timer */ @@ -383,7 +401,8 @@ t_mtrlnt tbc; t_stat st; sim_cancel (uptr); /* no more xfr's */ -if (mt_bptr == 0) return SCPE_OK; /* buf empty? */ +if (mt_bptr == 0) /* buf empty? */ + return SCPE_OK; if (!(uptr->flags & UNIT_ATT)) { /* attached? */ mt_set_err (uptr); /* no, err, disc */ return SCPE_UNATT; @@ -407,8 +426,10 @@ else { uptr->eotf = 1; } mt_bptr = 0; -if (st != MTSE_OK) mt_set_err (uptr); /* error? */ -if (st == MTSE_IOERR) return SCPE_IOERR; +if (st != MTSE_OK) /* error? */ + mt_set_err (uptr); +if (st == MTSE_IOERR) + return SCPE_IOERR; return SCPE_OK; } @@ -451,7 +472,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr) t_stat r; r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; uptr->botf = 1; uptr->eotf = 0; return SCPE_OK; @@ -469,7 +491,8 @@ t_stat mt_boot (int32 unitno, DEVICE *dptr) { extern uint32 P, M[]; -if (unitno) return SCPE_ARG; /* only unit 0 */ +if (unitno) /* only unit 0 */ + return SCPE_ARG; M[0] = 077777771; /* -7B */ M[1] = 007100000; /* LDX 0 */ M[2] = 000203610; /* EOM 3610B */ diff --git a/SDS/sds_mux.c b/SDS/sds_mux.c index ed143602..ef6203fd 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-2006, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ mux terminal multiplexor + 19-Nov-08 RMS Revixed for common TMXR show routines 29-Dec-06 RMS Revised to use console conversion routines 29-Jun-05 RMS Added SET MUXLn DISCONNECT 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS @@ -136,8 +137,6 @@ void mux_scan_next (void); DIB mux_dib = { -1, DEV3_GMUX, 0, NULL, &mux }; -REG mux_nlreg = { DRDATA (NLINES, MUX_NUMLIN, 6), PV_LEFT }; - UNIT mux_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), MUX_INIT_POLL }; REG mux_reg[] = { @@ -152,15 +151,16 @@ REG mux_reg[] = { }; MTAB mux_mod[] = { - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &mux_vlines, NULL, &mux_nlreg }, + { MTAB_XTD | MTAB_VDV, 0, "LINES", "LINES", + &mux_vlines, tmxr_show_lines, (void *) &mux_desc }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &mux_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, + NULL, &tmxr_show_summ, (void *) &mux_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &mux_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &mux_desc }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &mux_show, NULL }, + NULL, &tmxr_show_cstat, (void *) &mux_desc }, { 0 } }; @@ -255,14 +255,16 @@ switch (fnc) { case IO_CONN: /* connect */ if ((PROJ_GENIE && (inst == 000230001)) || /* set alert */ - (!PROJ_GENIE && (inst == 020277777))) alert = POT_MUX; + (!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; + if (!sim_is_active (&muxl_unit[ln])) + *dat = 1; } else if (!PROJ_GENIE && ((inst & 077776000) == 024076000)) { ln = SKS_CHAN (inst); /* get line */ @@ -326,7 +328,8 @@ else { /* enabled */ 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; + 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; @@ -344,7 +347,8 @@ t_stat muxi_svc (UNIT *uptr) { int32 ln, c, t; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; t = sim_rtcn_calb (mux_tps, TMR_MUX); /* calibrate */ sim_activate (uptr, t); /* continue poll */ ln = tmxr_poll_conn (&mux_desc); /* look for connect */ @@ -363,7 +367,8 @@ for (ln = 0; ln < MUX_NUMLIN; ln++) { /* loop thru lines */ 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 */ - if (c & SCPE_BREAK) c = 0; /* break? */ + if (c & SCPE_BREAK) /* break? */ + c = 0; else c = sim_tt_inpcvt (c, TT_GET_MODE (muxl_unit[ln].flags)); mux_rbuf[ln] = c; /* save char */ MUX_SETFLG (ln, MUX_FRCV); /* set rcv flag */ @@ -385,7 +390,8 @@ uint32 ln = uptr - muxl_unit; /* line # */ if (mux_ldsc[ln].conn) { /* connected? */ if (mux_ldsc[ln].xmte) { /* xmt enabled? */ c = sim_tt_outcvt (mux_xbuf[ln], TT_GET_MODE (muxl_unit[ln].flags)); - if (c >= 0) tmxr_putc_ln (&mux_ldsc[ln], c); /* output char */ + if (c >= 0) /* output char */ + tmxr_putc_ln (&mux_ldsc[ln], c); tmxr_poll_tx (&mux_desc); /* poll xmt */ } else { /* buf full */ @@ -407,7 +413,8 @@ void mux_scan_next (void) { int32 i; -if (mux_slck) return; /* locked? */ +if (mux_slck) /* locked? */ + return; 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? */ @@ -435,8 +442,10 @@ if (mux_unit.flags & UNIT_ATT) { /* master att? */ } } 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_LINES; i++) + mux_reset_ln (i); +for (i = 0; i < MUX_FLAGS; i++) /* clear all ints */ + MUX_CLRINT (i); return SCPE_OK; } @@ -448,7 +457,8 @@ t_stat r; int32 t; r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ +if (r != SCPE_OK) /* error */ + return r; t = sim_rtcn_init (mux_unit.wait, TMR_MUX); sim_activate (uptr, t); /* start poll */ return SCPE_OK; @@ -462,42 +472,12 @@ 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 */ +for (i = 0; i < MUX_LINES; i++) /* disable rcv */ + mux_ldsc[i].rcve = 0; sim_cancel (uptr); /* stop poll */ return r; } -/* Show summary processor */ - -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -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; -} - /* Change number of lines */ t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -505,12 +485,16 @@ t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) int32 newln, i, t; t_stat r; -if (cptr == NULL) return SCPE_ARG; +if (cptr == NULL) + return SCPE_ARG; newln = get_uint (cptr, 10, MUX_LINES, &r); -if ((r != SCPE_OK) || (newln == MUX_NUMLIN)) return r; -if (newln == 0) return SCPE_ARG; +if ((r != SCPE_OK) || (newln == MUX_NUMLIN)) + return r; +if (newln == 0) + return SCPE_ARG; if (newln < MUX_NUMLIN) { - for (i = newln, t = 0; i < MUX_NUMLIN; i++) t = t | mux_ldsc[i].conn; + for (i = newln, t = 0; i < MUX_NUMLIN; i++) + t = t | mux_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < MUX_NUMLIN; i++) { @@ -538,7 +522,8 @@ void mux_reset_ln (int32 ln) { int32 flg = ln * MUX_FLAGS; -if (mux_ldsc[ln].conn) mux_sta[ln] = MUX_SCRO | MUX_SDSR; +if (mux_ldsc[ln].conn) + mux_sta[ln] = MUX_SCRO | MUX_SDSR; else mux_sta[ln] = 0; sim_cancel (&muxl_unit[ln]); mux_flags[flg + MUX_FRCV] = 0; diff --git a/SDS/sds_rad.c b/SDS/sds_rad.c index 2add471d..4194c755 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-2005, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -136,25 +136,31 @@ 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 (new_ch != rad_dib.chan) /* wrong chan? */ + return SCPE_IERR; + if (CHC_GETCPW (inst) > 1) /* 1-2 char/word? */ + return STOP_INVIOP; 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 */ + if (t <= 0) /* seek */ + t = t + RAD_NUMSC; sim_activate (&rad_unit, t * rad_time * (RAD_NUMWD / 2)); xfr_req = xfr_req & ~XFR_RAD; /* clr xfr flg */ break; case IO_EOM1: /* EOM mode 1 */ new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ - if ((inst & 00600) == 00200) alert = POT_RADS; /* alert for sec */ + if (new_ch != rad_dib.chan) /* wrong chan? */ + return SCPE_IERR; + if ((inst & 00600) == 00200) /* alert for sec */ + alert = POT_RADS; else if ((inst & 06600) == 0) { /* alert for addr */ - if (sim_is_active (&rad_unit)) rad_err = 1; /* busy? */ + if (sim_is_active (&rad_unit)) /* busy? */ + rad_err = 1; else { rad_nobi = (inst & 01000)? 1: 0; /* save inc type */ alert = POT_RADA; /* set alert */ @@ -164,7 +170,8 @@ switch (fnc) { /* case function */ case IO_DISC: /* disconnect */ rad_end_op (0); /* normal term */ - if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */ + if (inst & DEV_OUT) /* fill write */ + return rad_fill (rad_sba); break; case IO_WREOR: /* write eor */ @@ -173,7 +180,8 @@ switch (fnc) { /* case function */ case IO_SKS: /* SKS */ new_ch = I_GETSKCH (inst); /* sks chan */ - if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ + if (new_ch != rad_dib.chan) /* wrong chan? */ + return SCPE_IERR; t = I_GETSKCND (inst); /* sks cond */ lun = RAD_GETLUN (rad_da); if (((t == 000) && !sim_is_active (&rad_unit)) || /* 10026: ready */ @@ -193,7 +201,8 @@ switch (fnc) { /* case function */ rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ return SCPE_OK; } - if (rad_sba & 1) *dat = fbuf[p] & 07777; /* odd byte? */ + if (rad_sba & 1) /* odd byte? */ + *dat = fbuf[p] & 07777; else *dat = (fbuf[p] >> 12) & 07777; /* even */ rad_sba = rad_adjda (rad_sba, 1); /* next byte */ break; @@ -210,9 +219,11 @@ switch (fnc) { /* case function */ 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? */ + if (rad_sba & 1) /* odd byte? */ + fbuf[p] = fbuf[p] | (*dat & 07777); else fbuf[p] = (*dat & 07777) << 12; /* even */ - if (p >= rad_unit.hwmark) rad_unit.hwmark = p + 1; /* mark hiwater */ + if (p >= rad_unit.hwmark) /* mark hiwater */ + rad_unit.hwmark = p + 1; rad_sba = rad_adjda (rad_sba, 1); /* next byte */ break; @@ -257,8 +268,10 @@ uint32 *fbuf = rad_unit.filebuf; int32 wa = (sba + 1) >> 1; /* whole words */ 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; + 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 */ } return SCPE_OK; @@ -283,7 +296,8 @@ return sba; void rad_end_op (int32 fl) { -if (fl) chan_set_flag (rad_dib.chan, fl); /* set flags */ +if (fl) /* set flags */ + chan_set_flag (rad_dib.chan, fl); xfr_req = xfr_req & ~XFR_RAD; /* clear xfr */ sim_cancel (&rad_unit); /* stop */ if (fl & CHF_ERR) { /* error? */ diff --git a/SDS/sds_stddev.c b/SDS/sds_stddev.c index 29c6baf9..7899228b 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-2005, Robert M. Supnik + Copyright (c) 2001-2008, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -232,7 +232,8 @@ 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 */ + if (new_ch != ptr_dib.chan) /* inv conn? err */ + return SCPE_IERR; ptr_sor = 1; /* start of rec */ xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ sim_activate (&ptr_unit, ptr_unit.wait); /* activate */ @@ -275,7 +276,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ 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"); + if (ptr_stopioe) + printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); /* I/O error */ @@ -354,7 +356,8 @@ 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 */ + if (new_ch != ptp_dib.chan) /* inv conn? err */ + return SCPE_IERR; 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 */ @@ -392,7 +395,8 @@ t_stat r = SCPE_OK; if (ptp_ldr) { /* need leader? */ for (i = 0; i < 12; i++) { /* punch leader */ - if (r = ptp_out (0)) break; + if (r = ptp_out (0)) + break; } } ptp_ldr = 0; /* clear flag */ @@ -463,7 +467,8 @@ 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 */ + if (new_ch != tti_dib.chan) /* inv conn? err */ + return SCPE_IERR; xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ break; @@ -494,14 +499,17 @@ 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 */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return temp; +if (temp & SCPE_BREAK) /* ignore break */ + return SCPE_OK; 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 */ + if (temp == '\r') /* lf after cr */ + sim_putchar ('\n'); xfr_req = xfr_req | XFR_TTI; /* set xfr flag */ } else sim_putchar (007); /* ding! */ @@ -539,7 +547,8 @@ 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 */ + if (new_ch != tto_dib.chan) /* inv conn? err */ + return SCPE_IERR; xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ sim_activate (&tto_unit, tto_unit.wait); /* activate */ break; @@ -573,9 +582,12 @@ t_stat tto_svc (UNIT *uptr) int32 asc; t_stat r; -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'; +if (uptr->buf == TT_CR) /* control chars? */ + asc = '\r'; +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 */ diff --git a/SDS/sds_sys.c b/SDS/sds_sys.c index c00823ae..cd87ea82 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-2005, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -163,24 +163,28 @@ for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ 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 (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; + 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; + if (ptr >= CCT_LNT) + return SCPE_FMT; cctbuf[ptr++] = mask; } } if (ptr == 0) return SCPE_FMT; lpt_ccl = ptr; lpt_ccp = 0; -for (rpt = 0; rpt < lpt_ccl; rpt++) lpt_cct[rpt] = cctbuf[rpt]; +for (rpt = 0; rpt < lpt_ccl; rpt++) + lpt_cct[rpt] = cctbuf[rpt]; return SCPE_OK; } @@ -193,9 +197,12 @@ int32 get_word (FILE *fileref, int32 *ldr) int32 i, c, wd; for (i = wd = 0; i < 4; ) { - if ((c = fgetc (fileref)) == EOF) return -1; - if ((c == 0) && (*ldr == 0)) return -1; - if (c == 0) continue; + if ((c = fgetc (fileref)) == EOF) + return -1; + if ((c == 0) && (*ldr == 0)) + return -1; + if (c == 0) + continue; *ldr = 0; wd = (wd << 6) | (c & 077); i++; @@ -210,10 +217,13 @@ int32 ldr = 1; extern int32 sim_switches; extern uint32 P; -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -if (sim_switches & SWMASK ('L')) return sim_load_cct (fileref); +if ((*cptr != 0) || (flag != 0)) + return SCPE_ARG; +if (sim_switches & SWMASK ('L')) + return sim_load_cct (fileref); for (i = 0; i < 8; i++) { /* read boot */ - if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_FMT; + if ((wd = get_word (fileref, &ldr)) < 0) + return SCPE_FMT; buf[i] = wd; } if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */ @@ -221,11 +231,15 @@ if ((buf[0] != 023200012) || /* 2 = WIM 12,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; + (buf[5] != 004100005)) /* 7 = BRX 5 */ + return SCPE_FMT; +for (i = 0; i < 8; i++) /* copy boot */ + M[i + 2] = buf[i]; +if (I_GETOP (buf[6]) == BRU) + P = buf[6] & VA_MASK; for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */ - if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_OK; + if ((wd = get_word (fileref, &ldr)) < 0) + return SCPE_OK; M[i] = wd; } return SCPE_NXM; @@ -415,7 +429,8 @@ shf = inst & I_SHFMSK; nonop = inst & 077777; if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; + if (inst > 0377) + return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } @@ -443,22 +458,26 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ case I_V_SHF: /* shift */ fprintf (of, "%s %-o", opcode[i], shf); - if (tag) fprintf (of, ",%-o", tag); + 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); + 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); + 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); + if (tag) + fprintf (of, ",%-o", tag); break; case I_V_REG: /* reg change */ @@ -498,7 +517,8 @@ 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 */ +if (r == SCPE_OK) /* ok? advance */ + return tptr; *tag = 0; return cptr; /* no change */ } @@ -523,19 +543,27 @@ t_stat r; char gbuf[CBUFSIZE]; while (isspace (*cptr)) cptr++; -for (i = 1; (i < 4) && (cptr[i] != 0); i++) - if (cptr[i] == 0) for (j = i + 1; j <= 4; j++) cptr[j] = 0; +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) /* must have 1 char */ + return SCPE_ARG; val[0] = (t_value) cptr[0] | 0200; return SCPE_OK; } if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; for (i = j = 0, val[0] = 0; i < 4; i++) { - if (cptr[i] == 0) j = 1; /* latch str end */ + if (cptr[i] == 0) /* latch str end */ + j = 1; k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */ - if (j || (k < 0)) k = 0; /* bad, end? spc */ + if (j || (k < 0)) /* bad, end? spc */ + k = 0; val[0] = (val[0] << 6) | k; } return SCPE_OK; @@ -543,7 +571,8 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */ 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; +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 */ @@ -555,7 +584,8 @@ switch (j) { /* case on class */ 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; + if (r != SCPE_OK) + return SCPE_ARG; cptr = get_tag (cptr, &tag); /* get opt tag */ val[0] = val[0] | d | tag; break; @@ -563,13 +593,15 @@ switch (j) { /* case on class */ 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; + 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; + if (r != SCPE_OK) + return SCPE_ARG; cptr = get_tag (cptr, &tag); /* get opt tag */ val[0] = val[0] | d | tag; break; @@ -577,7 +609,8 @@ switch (j) { /* case on class */ 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; + if (r != SCPE_OK) + return SCPE_ARG; cptr = get_tag (cptr, &tag); /* get opt tag */ val[0] = val[0] | d | tag; break; @@ -589,12 +622,14 @@ switch (j) { /* case on class */ (strcmp (opcode[i], gbuf) != 0); i++) ; if (opcode[i] != NULL) { k = opc_val[i] & DMASK;; - if (I_GETOP (k) != RCH) return SCPE_ARG; + 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; + if (r != SCPE_OK) + return SCPE_ARG; else val[0] = val[0] | d; } } @@ -604,15 +639,18 @@ switch (j) { /* case on class */ 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 */ + if (chname[i] != NULL) /* named chan */ + d = i; else { d = get_uint (gbuf, 8, NUM_CHAN - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; /* numbered chan */ + if (r != SCPE_OK) /* numbered chan */ + return SCPE_ARG; } 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? */ +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; return SCPE_OK; } diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 82c03931..add4651b 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -1,6 +1,6 @@ /* vax780_defs.h: VAX 780 model-specific definitions file - Copyright (c) 2004-2007, Robert M Supnik + Copyright (c) 2004-2008, Robert 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,6 +23,7 @@ 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-08 RMS Moved I/O support routines to I/O library 29-Apr-07 RMS Modified model-specific reserved operand check macros to reflect 780 microcode patches (found by Naoki Hamada) 29-Oct-06 RMS Added clock coscheduler function @@ -222,6 +223,8 @@ #define DZ_MUXES 4 /* max # of DZV muxes */ #define DZ_LINES 8 /* lines per DZV mux */ #define VH_MUXES 4 /* max # of DHQ muxes */ +#define DLX_LINES 16 /* max # of KL11/DL11's */ +#define DCX_LINES 16 /* max # of DC11's */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ @@ -427,13 +430,6 @@ int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf); int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf); int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (char *name, int32 num); - int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf); int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf); @@ -449,4 +445,6 @@ t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc); void sbi_set_errcnf (void); int32 clk_cosched (int32 wait); +#include "pdp11_io_lib.h" + #endif diff --git a/VAX/vax780_fload.c b/VAX/vax780_fload.c index c74e3f93..d8c2ed3e 100644 --- a/VAX/vax780_fload.c +++ b/VAX/vax780_fload.c @@ -97,7 +97,8 @@ uint32 i, j, start, size, origin; if ((fl_unit.flags & UNIT_ATT) == 0) /* floppy attached? */ return SCPE_UNATT; -if (*cptr == 0) return SCPE_2FARG; +if (*cptr == 0) + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get file name */ if (!rtfile_parse (gbuf, file_name)) /* legal file name? */ return SCPE_ARG; @@ -135,23 +136,29 @@ file_name[0] = file_name[1] = file_name[2] = 0; /* zero file name */ for (i = 0; i < 2; i++) { /* 6 characters */ for (j = 0; j < 3; j++) { c = *pntr; - if ((c == '.') || (c == 0)) d = 0; /* fill if . or end */ + if ((c == '.') || (c == 0)) /* fill if . or end */ + d = 0; else { - if ((d = rtfile_ator50 (c)) == 0) return FALSE; + if ((d = rtfile_ator50 (c)) == 0) + return FALSE; pntr++; } file_name[i] = (file_name[i] * 050) + d; /* merge into name */ } } -if (file_name[0] == 0) return FALSE; /* no name? lose */ +if (file_name[0] == 0) /* no name? lose */ + return FALSE; while ((c = *pntr++) != '.') { /* scan for . */ - if (c == 0) return TRUE; /* end? done */ + if (c == 0) /* end? done */ + return TRUE; } for (i = 0; i < 3; i++) { /* 3 characters */ c = *pntr; - if (c == 0) d = 0; /* fill if end */ + if (c == 0) /* fill if end */ + d = 0; else { - if ((d = rtfile_ator50 (c)) == 0) return FALSE; + if ((d = rtfile_ator50 (c)) == 0) + return FALSE; pntr++; } file_name[2] = (file_name[2] * 050) + d; /* merge into ext */ @@ -179,8 +186,7 @@ uint32 rtfile_lookup (uint16 *file_name, uint32 *start) uint16 dirseg[DS_SIZE]; uint32 segnum, dirent; -for (segnum = 1; /* loop thru segments */ - (segnum != 0) && (segnum <= DS_MAX); +for (segnum = 1; (segnum != 0) && (segnum <= DS_MAX); /* loop thru segments */ segnum = dirseg[DS_NEXT]) { if (!rtfile_read ((segnum * 2) + 4, 2, dirseg)) /* read segment */ return 0; /* error? */ diff --git a/VAX/vax780_mba.c b/VAX/vax780_mba.c index b7cd550c..afe264c4 100644 --- a/VAX/vax780_mba.c +++ b/VAX/vax780_mba.c @@ -275,7 +275,8 @@ if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? sbi_set_errcnf (); /* err confirmation */ return SCPE_OK; } -if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */ +if (mb >= MBA_NUM) /* valid? */ + return SCPE_NXM; rtype = MBA_RTYPE (pa); /* get reg type */ switch (rtype) { /* case on type */ @@ -325,12 +326,15 @@ switch (rtype) { /* case on type */ break; case MBART_EXT: /* external */ - if (!mbregR[mb]) return SCPE_NXM; /* device there? */ + if (!mbregR[mb]) /* device there? */ + return SCPE_NXM; drv = MBA_EXTDRV (pa); /* get dev num */ ofs = MBA_EXTOFS (pa); /* get reg offs */ r = mbregR[mb] (val, ofs, drv); /* call device */ - if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */ - else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + if (r == MBE_NXD) /* nx drive? */ + mba_upd_sr (MBASR_NFD, 0, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; *val |= (mba_sr[mb] & ~WMASK); /* upper 16b from SR */ if (DEBUG_PRI (mba_dev[mb], MBA_DEB_RRD)) fprintf (sim_deb, ">>MBA%d: drv %d ext reg %d read, value = %X\n", mb, drv, ofs, *val); @@ -364,7 +368,8 @@ if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? sbi_set_errcnf (); /* err confirmation */ return SCPE_OK; } -if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */ +if (mb >= MBA_NUM) /* valid? */ + return SCPE_NXM; rtype = MBA_RTYPE (pa); /* get reg type */ switch (rtype) { /* case on type */ @@ -382,7 +387,8 @@ switch (rtype) { /* case on type */ mba_reset (&mba_dev[mb]); /* reset MBA */ if ((val & MBACR_ABORT) && (mba_sr[mb] & MBASR_DTBUSY)) { - if (mbabort[mb]) mbabort[mb] (); /* abort? */ + if (mbabort[mb]) /* abort? */ + mbabort[mb] (); mba_upd_sr (MBASR_DTABT, 0, mb); } if ((val & MBACR_MNT) && @@ -390,7 +396,8 @@ switch (rtype) { /* case on type */ mba_upd_sr (MBASR_PGE, 0, mb); /* mnt & xfer? */ val = val & ~MBACR_MNT; } - if ((val & MBACR_IE) == 0) mba_clr_int (mb); + if ((val & MBACR_IE) == 0) + mba_clr_int (mb); mba_cr[mb] = (mba_cr[mb] & ~MBACR_WR) | (val & MBACR_WR); break; @@ -424,7 +431,8 @@ switch (rtype) { /* case on type */ break; case MBART_EXT: /* external */ - if (!mbregW[mb]) return SCPE_NXM; /* device there? */ + if (!mbregW[mb]) /* device there? */ + return SCPE_NXM; drv = MBA_EXTDRV (pa); /* get dev num */ ofs = MBA_EXTOFS (pa); /* get reg offs */ cs1dt = (ofs == MBA_CS1) && (val & CSR_GO) && /* starting xfr? */ @@ -434,8 +442,10 @@ switch (rtype) { /* case on type */ break; } r = mbregW[mb] (val & WMASK, ofs, drv); /* write dev reg */ - if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */ - else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + if (r == MBE_NXD) /* nx drive? */ + mba_upd_sr (MBASR_NFD, 0, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; if (cs1dt && (r == SCPE_OK)) /* did dt start? */ mba_sr[mb] = (mba_sr[mb] | MBASR_DTBUSY) & ~MBASR_W1C; if (DEBUG_PRI (mba_dev[mb], MBA_DEB_RWR)) @@ -470,18 +480,22 @@ int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf) int32 i, j, ba, mbc, pbc; uint32 pa, dat; -if (mb >= MBA_NUM) return 0; /* valid MBA? */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; ba = mba_va[mb]; /* get virt addr */ mbc = (MBABC_WR + 1) - mba_bc[mb]; /* get Mbus bc */ -if (bc > mbc) bc = mbc; /* use smaller */ +if (bc > mbc) /* use smaller */ + bc = mbc; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */ + if (!mba_map_addr (ba + i, &pa, mb)) /* page inv? */ + break; if (!ADDR_IS_MEM (pa)) { /* NXM? */ mba_upd_sr (MBASR_RTMO, 0, mb); break; } pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; if (DEBUG_PRI (mba_dev[mb], MBA_DEB_XFR)) fprintf (sim_deb, ">>MBA%d: read, pa = %X, bc = %X\n", mb, pa, pbc); if ((pa | pbc) & 1) { /* aligned word? */ @@ -516,18 +530,22 @@ int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf) int32 i, j, ba, mbc, pbc; uint32 pa, dat; -if (mb >= MBA_NUM) return 0; /* valid MBA? */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; ba = mba_va[mb]; /* get virt addr */ mbc = (MBABC_WR + 1) - mba_bc[mb]; /* get Mbus bc */ -if (bc > mbc) bc = mbc; /* use smaller */ +if (bc > mbc) /* use smaller */ + bc = mbc; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */ + if (!mba_map_addr (ba + i, &pa, mb)) /* page inv? */ + break; if (!ADDR_IS_MEM (pa)) { /* NXM? */ mba_upd_sr (MBASR_RTMO, 0, mb); break; } pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; if (DEBUG_PRI (mba_dev[mb], MBA_DEB_XFR)) fprintf (sim_deb, ">>MBA%d: write, pa = %X, bc = %X\n", mb, pa, pbc); if ((pa | pbc) & 1) { /* aligned word? */ @@ -563,12 +581,15 @@ int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf) int32 i, j, ba, mbc, pbc; uint32 pa, dat, cmp; -if (mb >= MBA_NUM) return 0; /* valid MBA? */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; ba = mba_va[mb]; /* get virt addr */ mbc = (MBABC_WR + 1) - mba_bc[mb]; /* get Mbus bc */ -if (bc > mbc) bc = mbc; /* use smaller */ +if (bc > mbc) /* use smaller */ + bc = mbc; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */ + if (!mba_map_addr (ba + i, &pa, mb)) /* page inv? */ + break; if (!ADDR_IS_MEM (pa)) { /* NXM? */ mba_upd_sr (MBASR_RTMO, 0, mb); break; @@ -576,10 +597,12 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */ if (DEBUG_PRI (mba_dev[mb], MBA_DEB_XFR)) fprintf (sim_deb, ">>MBA%d: check, pa = %X, bc = %X\n", mb, pa, pbc); - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; for (j = 0; j < pbc; j++, pa++) { /* byte by byte */ cmp = ReadB (pa); - if ((i + j) & 1) dat = (*buf++ >> 8) & BMASK; + if ((i + j) & 1) + dat = (*buf++ >> 8) & BMASK; else dat = *buf & BMASK; if (cmp != dat) { mba_upd_sr ((j & 1)? MBASR_WCEU: MBASR_WCEL, 0, mb); @@ -618,7 +641,8 @@ return; void mba_upd_ata (uint32 mb, uint32 val) { -if (val) mba_upd_sr (MBASR_ATA, 0, mb); +if (val) + mba_upd_sr (MBASR_ATA, 0, mb); else mba_upd_sr (0, MBASR_ATA, mb); return; } @@ -633,7 +657,8 @@ return; int32 mba_get_bc (uint32 mb) { -if (mb >= MBA_NUM) return 0; +if (mb >= MBA_NUM) + return 0; return (MBABC_WR + 1) - mba_bc[mb]; } @@ -641,7 +666,8 @@ void mba_set_int (uint32 mb) { DIB *dibp; -if (mb >= MBA_NUM) return; +if (mb >= MBA_NUM) + return; dibp = (DIB *) mba_dev[mb].ctxt; if (dibp) nexus_req[dibp->vloc >> 5] |= (1u << (dibp->vloc & 0x1F)); @@ -652,7 +678,8 @@ void mba_clr_int (uint32 mb) { DIB *dibp; -if (mb >= MBA_NUM) return; +if (mb >= MBA_NUM) + return; dibp = (DIB *) mba_dev[mb].ctxt; if (dibp) nexus_req[dibp->vloc >> 5] &= ~(1u << (dibp->vloc & 0x1F)); @@ -661,9 +688,12 @@ return; void mba_upd_sr (uint32 set, uint32 clr, uint32 mb) { -if (mb >= MBA_NUM) return; -if (set & MBASR_ABORTS) set |= (MBASR_DTCMP|MBASR_DTABT); -if (set & (MBASR_DTCMP|MBASR_DTABT)) mba_sr[mb] &= ~MBASR_DTBUSY; +if (mb >= MBA_NUM) + return; +if (set & MBASR_ABORTS) + set |= (MBASR_DTCMP|MBASR_DTABT); +if (set & (MBASR_DTCMP|MBASR_DTABT)) + mba_sr[mb] &= ~MBASR_DTBUSY; mba_sr[mb] = (mba_sr[mb] | set) & ~clr; if ((set & MBASR_INTR) && (mba_cr[mb] & MBACR_IE)) mba_set_int (mb); @@ -680,9 +710,11 @@ int32 i, mb; DIB *dibp; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; mb = dibp->ba - TR_MBA0; -if ((mb < 0) || (mb >= MBA_NUM)) return SCPE_IERR; +if ((mb < 0) || (mb >= MBA_NUM)) + return SCPE_IERR; mba_cnf[mb] = 0; mba_cr[mb] &= MBACR_MNT; mba_sr[mb] = 0; @@ -691,9 +723,11 @@ mba_va[mb] = 0; mba_dr[mb] = 0; mba_smr[mb] = 0; if (sim_switches & SWMASK ('P')) { - for (i = 0; i < MBA_NMAPR; i++) mba_map[mb][i] = 0; + for (i = 0; i < MBA_NMAPR; i++) + mba_map[mb][i] = 0; } -if (mbabort[mb]) mbabort[mb] (); /* reset device */ +if (mbabort[mb]) /* reset device */ + mbabort[mb] (); return SCPE_OK; } @@ -704,9 +738,11 @@ t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc) DEVICE *dptr = find_dev_from_unit (uptr); DIB *dibp; -if (dptr == NULL) return SCPE_IERR; +if (dptr == NULL) + return SCPE_IERR; dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; +if (dibp == NULL) + return SCPE_IERR; fprintf (st, "Massbus adapter %d", dibp->ba); return SCPE_OK; } @@ -715,8 +751,10 @@ return SCPE_OK; void mba_set_enbdis (uint32 mb, t_bool dis) { -if (mb >= MBA_NUM) return; /* valid MBA? */ -if (dis) mba_dev[mb].flags |= DEV_DIS; +if (mb >= MBA_NUM) /* valid MBA? */ + return; +if (dis) + mba_dev[mb].flags |= DEV_DIS; else mba_dev[mb].flags &= ~DEV_DIS; return; } @@ -741,9 +779,11 @@ t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp) { uint32 idx; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +if ((dptr == NULL) || (dibp == NULL)) /* validate args */ + return SCPE_IERR; idx = dibp->ba; /* Mbus # */ -if (idx >= MBA_NUM) return SCPE_STOP; +if (idx >= MBA_NUM) + return SCPE_STOP; if ((mbregR[idx] && dibp->rd && /* conflict? */ (mbregR[idx] != dibp->rd)) || (mbregW[idx] && dibp->wr && @@ -751,15 +791,18 @@ if ((mbregR[idx] && dibp->rd && /* conflict? */ (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); + 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 */ +if (dibp->rd) /* set rd dispatch */ + mbregR[idx] = dibp->rd; +if (dibp->wr) /* set wr dispatch */ + mbregW[idx] = dibp->wr; +if (dibp->ack[0]) /* set abort dispatch */ + mbabort[idx] = dibp->ack[0]; return SCPE_OK; } diff --git a/VAX/vax780_mem.c b/VAX/vax780_mem.c index 5e9b05cc..2183b832 100644 --- a/VAX/vax780_mem.c +++ b/VAX/vax780_mem.c @@ -1,6 +1,6 @@ /* vax780_mem.c: VAX 11/780 memory controllers - Copyright (c) 2004-2005, Robert M Supnik + Copyright (c) 2004-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -185,7 +185,8 @@ switch (ofs) { break; case MCRD_OF: /* CR D */ - if (!extmem) return SCPE_NXM; /* MS780E only */ + if (!extmem) /* MS780E only */ + return SCPE_NXM; *val = mcr_d[mctl] & MCRC_E_RD; break; @@ -228,7 +229,8 @@ switch (ofs) { break; case MCRD_OF: /* CR D */ - if (!extmem) return SCPE_NXM; /* MS780E only */ + if (!extmem) /* MS780E only */ + return SCPE_NXM; mcr_d[mctl] = ((mcr_d[mctl] & ~MCRC_WR) | (val & MCRC_WR)) & ~(val & MCRC_E_W1C); break; diff --git a/VAX/vax780_sbi.c b/VAX/vax780_sbi.c index be7088fb..7debc2d2 100644 --- a/VAX/vax780_sbi.c +++ b/VAX/vax780_sbi.c @@ -226,21 +226,30 @@ static const int32 sw_int_mask[IPL_SMAX] = { 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 */ -if ((ipl < IPL_CLKINT) && tmr_int) return IPL_CLKINT; /* clock int */ +if (hlt_pin) /* hlt pin int */ + return IPL_HLTPIN; +if ((ipl < IPL_MEMERR) && mem_err) /* mem err int */ + return IPL_MEMERR; +if ((ipl < IPL_CRDERR) && crd_err) /* crd err int */ + return IPL_CRDERR; +if ((ipl < IPL_CLKINT) && tmr_int) /* clock int */ + return IPL_CLKINT; uba_eval_int (); /* update UBA */ for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */ - if (i <= ipl) return 0; /* at ipl? no int */ - if (nexus_req[i - IPL_HMIN]) return i; /* req != 0? int */ + if (i <= ipl) /* at ipl? no int */ + return 0; + if (nexus_req[i - IPL_HMIN]) /* req != 0? int */ + return i; } if ((ipl < IPL_TTINT) && (tti_int || tto_int)) /* console int */ return IPL_TTINT; -if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */ -if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */ +if (ipl >= IPL_SMAX) /* ipl >= sw max? */ + return 0; +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 ((t >> i) & 1) /* req != 0? int */ + return i; } return 0; } @@ -406,7 +415,7 @@ switch (rg) { ((wcs_addr + WCSA_CTR_INC) & WCSA_CTR); if ((wcs_addr & WCSA_CTR) == WCSA_CTR_MAX) wcs_addr = (wcs_addr & ~WCSA_ADDR) | - ((wcs_addr + 1) & WCSA_ADDR); + ((wcs_addr + 1) & WCSA_ADDR); break; case MT_RXCS: /* RXCS */ @@ -437,15 +446,19 @@ switch (rg) { case MT_SBIER: /* SBIER */ sbi_er = (sbi_er & ~SBIER_WR) | (val & SBIER_WR); sbi_er = sbi_er & ~(val & SBIER_W1C); - if (val & SBIER_TMO) sbi_er = sbi_er & ~SBIER_TMOW1C; - if (val & SBIER_IBTMO) sbi_er = sbi_er & ~SBIER_IBTW1C; + if (val & SBIER_TMO) + sbi_er = sbi_er & ~SBIER_TMOW1C; + if (val & SBIER_IBTMO) + sbi_er = sbi_er & ~SBIER_IBTW1C; if ((sbi_er & SBIER_CRDIE) && (sbi_er & SBIER_CRD)) crd_err = 1; else crd_err = 0; break; case MT_SBIQC: /* SBIQC */ - if (val & SBIQC_MBZ) { RSVD_OPND_FAULT; } + if (val & SBIQC_MBZ) { + RSVD_OPND_FAULT; + } WriteLP (val, 0); WriteLP (val + 4, 0); break; @@ -521,8 +534,8 @@ void sbi_set_tmo (int32 pa) { if ((sbi_er & SBIER_TMO) == 0) { /* not yet set? */ sbi_tmo = pa >> 2; /* save addr */ - if (mchk_ref == REF_V) sbi_tmo |= SBITMO_VIRT | /* virt? add mode */ - (PSL_GETCUR (PSL) << SBITMO_V_MODE); + if (mchk_ref == REF_V) /* virt? add mode */ + sbi_tmo |= SBITMO_VIRT | (PSL_GETCUR (PSL) << SBITMO_V_MODE); sbi_er |= SBIER_TMO; /* set tmo flag */ } else sbi_er |= SBIER_MULT; /* yes, multiple */ @@ -533,7 +546,8 @@ return; void sbi_set_errcnf (void) { -if (sbi_er & SBIER_CNF) sbi_er |= SBIER_MULT; +if (sbi_er & SBIER_CNF) + sbi_er |= SBIER_MULT; else sbi_er |= SBIER_CNF; MACH_CHECK (MCHK_RD_F); return; @@ -604,9 +618,11 @@ if (slptr = strchr (gbuf, '/')) { /* found slash? */ *slptr = 0; /* zero in string */ } dptr = find_unit (gbuf, &uptr); /* find device */ -if ((dptr == NULL) || (uptr == NULL)) return SCPE_ARG; +if ((dptr == NULL) || (uptr == NULL)) + return SCPE_ARG; dibp = (DIB *) dptr->ctxt; /* get DIB */ -if (dibp == NULL) return SCPE_ARG; +if (dibp == NULL) + return SCPE_ARG; unitno = (int32) (uptr - dptr->units); r5v = 0; if ((strncmp (regptr, "/R5:", 4) == 0) || @@ -614,9 +630,11 @@ if ((strncmp (regptr, "/R5:", 4) == 0) || (strncmp (regptr, "/r5:", 4) == 0) || (strncmp (regptr, "/r5=", 4) == 0)) { r5v = (int32) get_uint (regptr + 4, 16, LMASK, &r); - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; } -else if (*regptr != 0) return SCPE_ARG; +else if (*regptr != 0) + return SCPE_ARG; for (i = 0; boot_tab[i].name != NULL; i++) { if (strcmp (dptr->name, boot_tab[i].name) == 0) { R[0] = boot_tab[i].code; @@ -647,7 +665,8 @@ printf ("Loading boot code from vmb.exe\n"); if (sim_log) fprintf (sim_log, "Loading boot code from vmb.exe\n"); r = load_cmd (0, "-O vmb.exe 200"); -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; SP = PC = 512; return SCPE_OK; } @@ -703,20 +722,24 @@ t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp) { uint32 idx; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; +if ((dptr == NULL) || (dibp == NULL)) + return SCPE_IERR; idx = dibp->ba; -if (idx >= NEXUS_NUM) return SCPE_IERR; +if (idx >= NEXUS_NUM) + return SCPE_IERR; if ((nexusR[idx] && dibp->rd && /* conflict? */ (nexusR[idx] != dibp->rd)) || (nexusW[idx] && dibp->wr && (nexusW[idx] != dibp->wr))) { printf ("Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); + if (sim_log) + fprintf (sim_log, "Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); return SCPE_STOP; } -if (dibp->rd) nexusR[idx] = dibp->rd; /* set rd dispatch */ -if (dibp->wr) nexusW[idx] = dibp->wr; /* set wr dispatch */ +if (dibp->rd) /* set rd dispatch */ + nexusR[idx] = dibp->rd; +if (dibp->wr) /* set wr dispatch */ + nexusW[idx] = dibp->wr; return SCPE_OK; } diff --git a/VAX/vax780_stddev.c b/VAX/vax780_stddev.c index d5ce4afb..512ac36c 100644 --- a/VAX/vax780_stddev.c +++ b/VAX/vax780_stddev.c @@ -1,6 +1,6 @@ /* vax780_stddev.c: VAX 11/780 standard I/O devices - Copyright (c) 1998-2007, Robert M Supnik + Copyright (c) 1998-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -29,8 +29,9 @@ todr TODR clock tmr interval timer + 17-Aug-08 RMS Resync TODR on any clock reset 18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock - 29-Oct-2006 RMS Added clock coscheduler function + 29-Oct-06 RMS Added clock coscheduler function Synced keyboard to clock for idling 11-May-06 RMS Revised timer logic for EVKAE 22-Nov-05 RMS Revised for new terminal processing routines @@ -201,7 +202,7 @@ t_stat fl_reset (DEVICE *dptr); int32 icr_rd (t_bool interp); void tmr_incr (uint32 inc); void tmr_sched (void); -t_stat todr_powerup (void); +t_stat todr_resync (void); t_stat fl_wr_txdb (int32 data); t_bool fl_test_xfr (UNIT *uptr, t_bool wr); void fl_protocol_error (void); @@ -372,7 +373,8 @@ return (tti_csr & RXCS_RD); void rxcs_wr (int32 data) { -if ((data & CSR_IE) == 0) tto_int = 0; +if ((data & CSR_IE) == 0) + tto_int = 0; else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) tti_int = 1; tti_csr = (tti_csr & ~RXCS_WR) | (data & RXCS_WR); @@ -396,7 +398,8 @@ return (tto_csr & TXCS_RD); void txcs_wr (int32 data) { -if ((data & CSR_IE) == 0) tto_int = 0; +if ((data & CSR_IE) == 0) + tto_int = 0; else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) tto_int = 1; tto_csr = (tto_csr & ~TXCS_WR) | (data & TXCS_WR); @@ -408,7 +411,8 @@ void txdb_wr (int32 data) tto_buf = data & WMASK; /* save data */ tto_csr = tto_csr & ~CSR_DONE; /* clear flag */ tto_int = 0; /* clear int */ -if (tto_buf & TXDB_SEL) fl_wr_txdb (tto_buf); /* floppy? */ +if (tto_buf & TXDB_SEL) /* floppy? */ + fl_wr_txdb (tto_buf); else sim_activate (&tto_unit, tto_unit.wait); /* no, console */ return; } @@ -420,13 +424,15 @@ t_stat tti_svc (UNIT *uptr) int32 c; sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; if (c & SCPE_BREAK) /* break? */ tti_buf = RXDB_ERR | RXDB_FRM; else tti_buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); uptr->pos = uptr->pos + 1; tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) tti_int = 1; +if (tti_csr & CSR_IE) + tti_int = 1; return SCPE_OK; } @@ -459,7 +465,8 @@ if ((tto_buf & TXDB_SEL) == 0) { /* for console? */ uptr->pos = uptr->pos + 1; } tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) tto_int = 1; +if (tto_csr & CSR_IE) + tto_int = 1; return SCPE_OK; } @@ -526,7 +533,8 @@ else if (val & TMR_CSR_SGL) { /* single step? */ tmr_icr = tmr_nicr; /* reload tir */ } if ((tmr_iccs & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ - (TMR_CSR_DON | TMR_CSR_IE)) tmr_int = 0; + (TMR_CSR_DON | TMR_CSR_IE)) + tmr_int = 0; return; } @@ -538,7 +546,8 @@ if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */ delta = sim_grtime () - tmr_sav; /* delta inst */ if (tmr_use_100hz && (tmr_poll > TMR_INC)) /* scale large int */ delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); - if (delta >= tmr_inc) delta = tmr_inc - 1; + if (delta >= tmr_inc) + delta = tmr_inc - 1; return tmr_icr + delta; } return tmr_icr; @@ -590,7 +599,8 @@ if (new_icr < tmr_icr) { /* ovflo? */ tmr_icr = tmr_nicr; /* reload */ tmr_sched (); /* reactivate */ } - if (tmr_iccs & TMR_CSR_IE) tmr_int = 1; /* ie? set int req */ + if (tmr_iccs & TMR_CSR_IE) /* ie? set int req */ + tmr_int = 1; else tmr_int = 0; } else { @@ -646,7 +656,7 @@ tmr_nicr = 0; tmr_int = 0; tmr_use_100hz = 1; sim_cancel (&tmr_unit); /* cancel timer */ -if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? set TODR */ +todr_resync (); /* resync TODR */ return SCPE_OK; } @@ -663,16 +673,18 @@ todr_reg = data; return; } -t_stat todr_powerup (void) +t_stat todr_resync (void) { uint32 base; time_t curr; struct tm *ctm; curr = time (NULL); /* get curr time */ -if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */ +if (curr == (time_t) -1) /* error? */ + return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ -if (ctm == NULL) return SCPE_NOFNC; /* error? */ +if (ctm == NULL) /* error? */ + return SCPE_NOFNC; base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ ctm->tm_hour) * 60) + ctm->tm_min) * 60) + @@ -689,7 +701,8 @@ int32 sel = TXDB_GETSEL (data); /* get selection */ if (sel == TXDB_FCMD) { /* floppy command? */ fl_fnc = FL_GETFNC (data); /* get function */ - if (fl_state != FL_IDLE) switch (fl_fnc) { /* cmd in prog? */ + if (fl_state != FL_IDLE) /* cmd in prog? */ + switch (fl_fnc) { case FL_FNCCA: /* cancel? */ sim_cancel (&fl_unit); /* stop op */ @@ -736,13 +749,15 @@ else if (sel == TXDB_FDAT) { /* floppy data? */ case FL_RWDT: /* expecting track */ fl_track = data & FL_M_TRACK; - if (fl_fnc == FL_FNCRD) fl_state = FL_READ; + if (fl_fnc == FL_FNCRD) + fl_state = FL_READ; else fl_state = FL_FILL; break; case FL_FILL: /* expecting wr data */ fl_buf[fl_bptr++] = data & BMASK; - if (fl_bptr >= FL_NUMBY) fl_state = FL_WRITE; + if (fl_bptr >= FL_NUMBY) + fl_state = FL_WRITE; break; default: @@ -758,7 +773,8 @@ else { data = data & COMM_MASK; /* byte to select */ tti_buf = comm_region[data] | COMM_DATA; tti_csr = tti_csr | CSR_DONE; /* set input flag */ - if (tti_csr & CSR_IE) tti_int = 1; + if (tti_csr & CSR_IE) + tti_int = 1; } else if (sel == TXDB_MISC) { /* misc function? */ switch (data & MISC_MASK) { /* case on function */ @@ -808,12 +824,14 @@ switch (fl_state) { /* case on state */ case FL_READ: case FL_WRITE: /* read, write */ fl_state = fl_state + 1; /* set next state */ t = abs (fl_track - uptr->TRACK); /* # tracks to seek */ - if (t == 0) t = 1; /* minimum 1 */ + if (t == 0) /* minimum 1 */ + t = 1; sim_activate (uptr, fl_swait * t); /* schedule seek */ /* fall thru, set flag */ case FL_RWDS: case FL_RWDT: case FL_FILL: /* rwds, rwdt, fill */ tto_csr = tto_csr | CSR_DONE; /* set output done */ - if (tto_csr & CSR_IE) tto_int = 1; + if (tto_csr & CSR_IE) + tto_int = 1; break; case FL_READ1: /* read, seek done */ @@ -823,7 +841,8 @@ switch (fl_state) { /* case on state */ fl_buf[i] = fbuf[da + i]; tti_buf = fl_esr | FL_CDONE; /* completion code */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ - if (tti_csr & CSR_IE) tti_int = 1; + if (tti_csr & CSR_IE) + tti_int = 1; fl_state = FL_EMPTY; /* go empty */ } else fl_state = FL_DONE; /* error? cmd done */ @@ -834,7 +853,8 @@ switch (fl_state) { /* case on state */ if ((tti_csr & CSR_DONE) == 0) { /* prev data taken? */ tti_buf = FL_CDATA | fl_buf[fl_bptr++]; /* get next byte */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ - if (tti_csr & CSR_IE) tti_int = 1; + if (tti_csr & CSR_IE) + tti_int = 1; if (fl_bptr >= FL_NUMBY) { /* buffer empty? */ fl_state = FL_IDLE; /* cmd done */ break; @@ -849,9 +869,11 @@ switch (fl_state) { /* case on state */ for (i = 0; i < FL_NUMBY; i++) /* copy buf to sector */ fbuf[da + i] = fl_buf[i]; da = da + FL_NUMBY; - if (da > uptr->hwmark) uptr->hwmark = da; /* update hwmark */ + if (da > uptr->hwmark) /* update hwmark */ + uptr->hwmark = da; } - if (fl_fnc == FL_FNCWD) fl_esr |= FL_STADDA; /* wrdel? set status*/ + if (fl_fnc == FL_FNCWD) /* wrdel? set status */ + fl_esr |= FL_STADDA; fl_state = FL_DONE; /* command done */ sim_activate (uptr, fl_xwait); /* schedule */ break; @@ -862,7 +884,8 @@ switch (fl_state) { /* case on state */ else { /* yes */ tti_buf = fl_esr | FL_CDONE; /* completion code */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ - if (tti_csr & CSR_IE) tti_int = 1; + if (tti_csr & CSR_IE) + tti_int = 1; fl_state = FL_IDLE; /* floppy idle */ } break; @@ -871,7 +894,8 @@ switch (fl_state) { /* case on state */ if ((tti_csr & CSR_DONE) == 0) { /* input buf empty? */ tti_buf = fl_ecode; /* return err code */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ - if (tti_csr & CSR_IE) tti_int = 1; + if (tti_csr & CSR_IE) + tti_int = 1; fl_state = FL_DONE; /* command done */ } sim_activate (uptr, fl_xwait); @@ -906,11 +930,13 @@ void fl_protocol_error (void) { if ((tto_csr & CSR_DONE) == 0) { /* output busy? */ tto_csr = tto_csr | CSR_DONE; /* set done */ - if (tto_csr & CSR_IE) tto_int = 1; + if (tto_csr & CSR_IE) + tto_int = 1; } if ((tti_csr & CSR_DONE) == 0) { /* input idle? */ tti_csr = tti_csr | CSR_DONE; /* set done */ - if (tti_csr & CSR_IE) tti_int = 1; + if (tti_csr & CSR_IE) + tti_int = 1; } tti_buf = FL_CPROT; /* status */ fl_state = FL_IDLE; /* floppy idle */ @@ -931,7 +957,8 @@ fl_state = FL_IDLE; /* ctrl idle */ fl_bptr = 0; sim_cancel (&fl_unit); /* cancel drive */ fl_unit.TRACK = 0; -for (i = 0; i < COMM_LNT; i++) comm_region[i] = 0; +for (i = 0; i < COMM_LNT; i++) + comm_region[i] = 0; comm_region[COMM_FPLV] = VER_FPLA; comm_region[COMM_PCSV] = VER_PCS; comm_region[COMM_WCSV] = VER_WCSP; diff --git a/VAX/vax780_syslist.c b/VAX/vax780_syslist.c index 6514c547..71140c05 100644 --- a/VAX/vax780_syslist.c +++ b/VAX/vax780_syslist.c @@ -1,6 +1,6 @@ /* vax_syslist.c: VAX device list - Copyright (c) 1998-2006, Robert M Supnik + Copyright (c) 1998-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -109,25 +109,30 @@ t_stat r; int32 val; uint32 origin, limit; -if (flag) return SCPE_ARG; /* dump? */ +if (flag) /* dump? */ + return SCPE_ARG; 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; + if (r != SCPE_OK) + return SCPE_ARG; } while ((val = getc (fileref)) != EOF) { /* read byte stream */ if (sim_switches & SWMASK ('R')) { /* ROM0? */ - if (origin >= ROMSIZE) return SCPE_NXM; + if (origin >= ROMSIZE) + return SCPE_NXM; rom_wr_B (ROM0BASE + origin, val); } else if (sim_switches & SWMASK ('S')) { /* ROM1? */ - if (origin >= ROMSIZE) return SCPE_NXM; + if (origin >= ROMSIZE) + return SCPE_NXM; rom_wr_B (ROM1BASE + origin, val); } else { - if (origin >= limit) return SCPE_NXM; /* NXM? */ + if (origin >= limit) /* NXM? */ + return SCPE_NXM; WriteB (origin, val); /* memory */ } origin = origin + 1; diff --git a/VAX/vax780_uba.c b/VAX/vax780_uba.c index 206e059a..e12a225d 100644 --- a/VAX/vax780_uba.c +++ b/VAX/vax780_uba.c @@ -25,6 +25,7 @@ uba DW780 Unibus adapter + 19-Nov-08 RMS Moved I/O support routines to I/O library 28-May-08 RMS Inlined physical memory routines 25-Jan-08 RMS Fixed declarations (from Mark Pizzolato) */ @@ -208,9 +209,8 @@ extern t_stat build_dib_tab (void); /* Unibus IO page dispatches */ -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]; +t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); +t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); /* Unibus interrupt request to interrupt action map */ @@ -307,11 +307,12 @@ if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? return SCPE_OK; } ofs = NEXUS_GETOFS (pa); /* get offset */ -if (uba_aiip && (ofs != UBACNF_OF) /* init in prog? */ - && (ofs != UBADR_OF)) return SCPE_NXM; /* only cnf, dr */ +if (uba_aiip && (ofs != UBACNF_OF)&& (ofs != UBADR_OF)) /* init in prog? */ + return SCPE_NXM; /* only cnf, dr */ if (ofs >= UBAMAP_OF) { /* map? */ idx = ofs - UBAMAP_OF; - if (idx >= UBA_NMAPR) return SCPE_NXM; /* valid? */ + if (idx >= UBA_NMAPR) /* valid? */ + return SCPE_NXM; *val = uba_map[idx] & UBAMAP_RD; if (DEBUG_PRI (uba_dev, UBA_DEB_MRD)) fprintf (sim_deb, ">>UBA: map %d read, value = %X\n", idx, *val); @@ -396,10 +397,12 @@ if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? } ofs = NEXUS_GETOFS (pa); /* get offset */ if (uba_aiip && (ofs != UBACNF_OF) && (ofs != UBADR_OF) && - (ofs != UBACR_OF) && (ofs != UBASR_OF)) return SCPE_NXM; + (ofs != UBACR_OF) && (ofs != UBASR_OF)) + return SCPE_NXM; if (ofs >= UBAMAP_OF) { /* map? */ idx = ofs - UBAMAP_OF; - if (idx >= UBA_NMAPR) return SCPE_NXM; /* valid? */ + if (idx >= UBA_NMAPR) /* valid? */ + return SCPE_NXM; uba_map[idx] = val & UBAMAP_WR; if (DEBUG_PRI (uba_dev, UBA_DEB_MWR)) fprintf (sim_deb, ">>UBA: map %d write, value = %X\n", idx, val); @@ -517,7 +520,8 @@ uint32 iod; if ((lnt == L_BYTE) || /* byte? */ ((lnt == L_WORD) && ((pa & 1) == 0))) { /* aligned word? */ iod = ReadUb (pa); /* DATI from Unibus */ - if (pa & 2) iod = iod << 16; /* position */ + if (pa & 2) /* position */ + iod = iod << 16; } else { printf (">>UBA: invalid read mask, pa = %x, lnt = %d\n", pa, lnt); @@ -540,7 +544,8 @@ return iod; void WriteIO (uint32 pa, int32 val, int32 lnt) { -if (lnt == L_BYTE) WriteUb (pa, val, WRITEB); /* byte? DATOB */ +if (lnt == L_BYTE) /* byte? DATOB */ + WriteUb (pa, val, WRITEB); else if ((lnt == L_WORD) && ((pa & 1) == 0)) /* aligned word? */ WriteUb (pa, val, WRITE); /* DATO */ else { @@ -562,10 +567,12 @@ for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) /* clear all UBA req */ if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */ (uba_cr & UBACR_IFS) && (uba_cr & UBACR_BRIE)) { for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) { - if (int_req[i]) nexus_req[i] |= (1 << TR_UBA); + if (int_req[i]) + nexus_req[i] |= (1 << TR_UBA); } } -if (uba_int) SET_NEXUS_INT (UBA); /* adapter int? */ +if (uba_int) /* adapter int? */ + SET_NEXUS_INT (UBA); return; } @@ -585,7 +592,8 @@ if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */ for (i = 0; int_req[lvl] && (i < 32); i++) { if ((int_req[lvl] >> i) & 1) { int_req[lvl] = int_req[lvl] & ~(1u << i); - if (int_ack[lvl][i]) return (vec | int_ack[lvl][i]()); + if (int_ack[lvl][i]) + return (vec | int_ack[lvl][i]()); return (vec | int_vec[lvl][i]); } } @@ -608,9 +616,11 @@ uint32 ma, dat; ba = ba & UBADDRMASK; /* mask UB addr */ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) fprintf (sim_deb, ">>UBA: 8b read, ma = %X, bc = %X\n", ma, pbc); if ((ma | pbc) & 3) { /* aligned LW? */ @@ -640,9 +650,11 @@ uint32 ma, dat; ba = ba & UBADDRMASK; /* mask UB addr */ bc = bc & ~01; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) fprintf (sim_deb, ">>UBA: 16b read, ma = %X, bc = %X\n", ma, pbc); if ((ma | pbc) & 1) { /* aligned word? */ @@ -678,9 +690,11 @@ uint32 ma, dat; ba = ba & UBADDRMASK; /* mask UB addr */ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) fprintf (sim_deb, ">>UBA: 8b write, ma = %X, bc = %X\n", ma, pbc); if ((ma | pbc) & 3) { /* aligned LW? */ @@ -711,9 +725,11 @@ uint32 ma, dat; ba = ba & UBADDRMASK; /* mask UB addr */ bc = bc & ~01; for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) fprintf (sim_deb, ">>UBA: 16b write, ma = %X, bc = %X\n", ma, pbc); if ((ma | pbc) & 1) { /* aligned word? */ @@ -751,7 +767,8 @@ uint32 ublk, umap; ublk = ua >> VA_V_VPN; /* Unibus blk */ if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */ - (ublk >= UBA_NMAPR)) return FALSE; /* unimplemented? */ + (ublk >= UBA_NMAPR)) /* unimplemented? */ + return FALSE; umap = uba_map[ublk]; /* get map */ if (umap & UBAMAP_VLD) { /* valid? */ *ma = ((umap & UBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (ua); @@ -771,7 +788,8 @@ uint32 ublk, umap; ublk = ua >> VA_V_VPN; /* Unibus blk */ if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */ - (ublk >= UBA_NMAPR)) return FALSE; /* unimplemented? */ + (ublk >= UBA_NMAPR)) /* unimplemented? */ + return FALSE; umap = uba_map[ublk]; /* get map */ if (umap & UBAMAP_VLD) { /* valid? */ *ma = ((umap & UBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (ua); @@ -790,7 +808,8 @@ void uba_set_dpr (uint32 ua, t_bool wr) uint32 ublk, umap, dpr; ublk = ua >> VA_V_VPN; /* Unibus blk */ -if (ublk >= UBA_NMAPR) return; /* paranoia */ +if (ublk >= UBA_NMAPR) /* paranoia */ + return; umap = uba_map[ublk]; /* get map */ dpr = UBAMAP_GETDP (umap); /* get bdp */ if (dpr) uba_dpr[dpr] = (uba_dpr[dpr] & ~(UBADPR_UA|UBADPR_DIR)) | @@ -903,8 +922,10 @@ for (i = 0; i < IPL_HLVL; i++) { uba_svr[i] = 0; uba_rvr[i] = 0; } -for (i = 0; i < UBA_NMAPR; i++) uba_map[i] = 0; -for (i = 0; i < UBA_NDPATH; i++) uba_dpr[i] = 0; +for (i = 0; i < UBA_NMAPR; i++) + uba_map[i] = 0; +for (i = 0; i < UBA_NDPATH; i++) + uba_dpr[i] = 0; uba_sr = 0; uba_cr = 0; uba_dr = 0; @@ -918,7 +939,8 @@ t_stat uba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) { uint32 ua = (uint32) exta, pa; -if ((vptr == NULL) || (ua >= UBADDRSIZE)) return SCPE_ARG; +if ((vptr == NULL) || (ua >= UBADDRSIZE)) + return SCPE_ARG; if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) { *vptr = (uint32) ReadW (pa); return SCPE_OK; @@ -932,7 +954,8 @@ t_stat uba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) { uint32 ua = (uint32) exta, pa; -if (ua >= UBADDRSIZE) return SCPE_ARG; +if (ua >= UBADDRSIZE) + return SCPE_ARG; if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) { WriteW (pa, (int32) val); return SCPE_OK; @@ -940,225 +963,6 @@ if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) { return SCPE_NXM; } -/* 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 (NULL, 0); -} - -/* Show autoconfiguration status */ - -t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "autoconfiguration "); -fprintf (st, autcon_enb? "enabled": "disabled"); -return SCPE_OK; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newba = (uint32) get_uint (cptr, 16, IOPAGEBASE+IOPAGEMASK, &r); -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 */ -return SCPE_OK; -} - -/* Show device address */ - -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08X", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (NULL, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newvec = (uint32) get_uint (cptr, 16, 01000, &r); -if ((r != SCPE_OK) || - ((newvec + (dibp->vnum * 4)) >= 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 */ -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { - fprintf (st, "vector=%X", vec); - if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1))); - } -return SCPE_OK; -} - -/* Init Unibus tables */ - -void init_ubus_tab (void) -{ -int32 i, j; - -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; - } -return; -} - -/* Build Unibus tables */ - -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 (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 */ - } -return SCPE_OK; -} - -/* Show IO space */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -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 */ -return SCPE_OK; -} - /* Show UBA virtual address */ t_stat uba_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc) @@ -1179,144 +983,3 @@ if (cptr) { fprintf (of, "Invalid argument\n"); return SCPE_OK; } - -/* Autoconfiguration - - 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). - - A minus number of vectors indicates a field that should be calculated - but not placed in the DIB (RQ, TQ dynamic vectors) */ - -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -typedef struct { - char *dnam[AUTO_MAXC]; - int32 numc; - int32 numv; - uint32 amod; - uint32 vmod; - uint32 fixa[AUTO_MAXC]; - uint32 fixv[AUTO_MAXC]; - } AUTO_CON; - -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 (char *name, int32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -AUTO_CON *autp; -DEVICE *dptr; -DIB *dibp; -uint32 j, k, vmask, amask; - -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_cis.c b/VAX/vax_cis.c index e8b3c90d..e77680e4 100644 --- a/VAX/vax_cis.c +++ b/VAX/vax_cis.c @@ -26,6 +26,8 @@ On a full VAX, this module simulates the VAX commercial instruction set (CIS). On a subset VAX, this module implements the emulated instruction fault. + 16-Oct-08 RMS Fixed bug in ASHP left overflow calc (Word/NibbleLShift) + Fixed bug in DIVx (LntDstr calculation) 28-May-08 RMS Inlined physical memory routines 16-May-06 RMS Fixed bug in length calculation (found by Tim Stark) 03-May-06 RMS Fixed MOVTC, MOVTUC to preserve cc's through page faults @@ -167,7 +169,8 @@ switch (opc) { /* case on opcode */ if (R[2]) { /* move to do? */ int32 mvl; mvl = R[0] & STR_LNMASK; /* orig move len */ - if (mvl >= (R[4] & STR_LNMASK)) mvl = R[4] & STR_LNMASK; + if (mvl >= (R[4] & STR_LNMASK)) + mvl = R[4] & STR_LNMASK; 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); @@ -322,7 +325,8 @@ switch (opc) { /* case on opcode */ t = Read ((R[3] + i) & LMASK, L_BYTE, RA); match = (c == t); /* continue if match */ } /* end for substring */ - if (match) break; /* exit if match */ + if (match) /* exit if match */ + break; 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? */ @@ -332,7 +336,8 @@ switch (opc) { /* case on opcode */ ABORT (r); /* abort flushes IB */ } SET_IRQL; /* update interrupts */ - if (trpirq) ABORT (ABORT_INTR); /* pending? stop */ + if (trpirq) /* pending? stop */ + ABORT (ABORT_INTR); } else sim_interval = sim_interval - i; } /* end for string */ @@ -462,7 +467,8 @@ switch (opc) { /* case on opcode */ 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 (opc & 2) /* sub? invert sign */ + src1.sign = src1.sign ^ 1; if (src1.sign ^ src2.sign) { /* opp signs? sub */ if (CmpDstr (&src1, &src2) < 0) { /* src1 < src2? */ SubDstr (&src1, &src2, &dst); /* src2 - src1 */ @@ -633,8 +639,10 @@ switch (opc) { /* case on opcode */ 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); + 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; @@ -678,8 +686,10 @@ switch (opc) { /* case on opcode */ 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; + if (WordLshift (&src1, shift / 8)) /* do word shifts */ + V = 1; + 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; @@ -714,13 +724,17 @@ switch (opc) { /* case on opcode */ 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; + if (result >= MAXDVAL) + V = 1; result = ((result * 10) + d) & LMASK; - if (result < d) V = 1; + 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 (src1.sign) /* negative? */ + result = (~result + 1) & LMASK; + if (src1.sign ^ ((result & LSIGN) != 0)) /* test for overflow */ + V = 1; if (op[2] < 0) /* if mem, store result */ Write (op[3], result, L_LONG, WA); /* before reg update */ R[0] = 0; /* update registers */ @@ -729,7 +743,8 @@ switch (opc) { /* case on opcode */ R[3] = 0; if (op[2] >= 0) /* if reg, store result */ R[op[2]] = result; /* after reg update */ - if (V && (PSL & PSW_IV)) SET_TRAP (TRAP_INTOV); /* ovflo and IV? trap */ + if (V && (PSL & PSW_IV)) /* ovflo and IV? trap */ + SET_TRAP (TRAP_INTOV); CC_IIZZ_L (result); return cc | (V? CC_V: 0); @@ -793,7 +808,8 @@ switch (opc) { /* case on opcode */ 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 -, */ + if (t == C_MINUS) /* sign -, */ + dst.sign = 1; else if ((t != C_PLUS) && (t != C_SPACE)) /* + or blank? */ RSVD_OPND_FAULT; for (i = 1; i <= op[0]; i++) { /* loop thru chars */ @@ -881,11 +897,13 @@ switch (opc) { /* case on opcode */ d = c & 0xF; } else { /* highest byte */ - t = Read ((op[2] + c) & LMASK, L_BYTE, RA); /* xlate */ + 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; + 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)); } @@ -923,7 +941,7 @@ switch (opc) { /* case on opcode */ 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 */ + d = (dst.val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */ c = d + C_ZERO; /* convert */ } else { /* translate last */ @@ -996,7 +1014,8 @@ switch (opc) { /* case on opcode */ R[0] = R[0] & ~0xFFE0; /* src len <= 31 */ } else { /* new instr */ - if (op[0] > 31) RSVD_OPND_FAULT; /* lnt > 31? */ + if (op[0] > 31) /* lnt > 31? */ + RSVD_OPND_FAULT; t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA) & 0xF; if ((t == 0xB) || (t == 0xD)) { cc = CC_N | CC_Z; @@ -1018,10 +1037,12 @@ switch (opc) { /* case on opcode */ for ( ;; ) { /* loop thru pattern */ pop = Read (R[3], L_BYTE, RA); /* rd pattern op */ - if (pop == EO_END) break; /* end? */ + if (pop == EO_END) /* end? */ + break; if (pop & EO_RPT_FLAG) { /* repeat class? */ rpt = pop & EO_RPT_MASK; /* isolate count */ - if (rpt == 0) RSVD_OPND_FAULT; /* can't be zero */ + if (rpt == 0) /* can't be zero */ + RSVD_OPND_FAULT; pop = pop & ~EO_RPT_MASK; /* isolate op */ } switch (pop) { /* case on op */ @@ -1059,12 +1080,14 @@ switch (opc) { /* case on opcode */ break; case EO_LOAD_PLUS: /* load sign if + */ - if (!(cc & CC_N)) sign = edit_read_sign (acc); + if (!(cc & CC_N)) + sign = edit_read_sign (acc); R[3]++; break; case EO_LOAD_MINUS: /* load sign if - */ - if (cc & CC_N) sign = edit_read_sign (acc); + if (cc & CC_N) + sign = edit_read_sign (acc); R[3]++; break; @@ -1077,7 +1100,8 @@ switch (opc) { /* case on opcode */ case EO_BLANK_ZERO: /* blank zero */ t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - if (t == 0) RSVD_OPND_FAULT; + if (t == 0) + RSVD_OPND_FAULT; if (cc & CC_Z) { /* zero? */ do { /* repeat and blank */ Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); @@ -1088,7 +1112,8 @@ switch (opc) { /* case on opcode */ case EO_REPL_SIGN: /* replace sign */ t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - if (t == 0) RSVD_OPND_FAULT; + if (t == 0) + RSVD_OPND_FAULT; if (cc & CC_Z) Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); R[3]++; /* now fault safe */ @@ -1096,12 +1121,14 @@ switch (opc) { /* case on opcode */ case EO_ADJUST_LNT: /* adjust length */ t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - if ((t == 0) || (t > 31)) RSVD_OPND_FAULT; + if ((t == 0) || (t > 31)) + RSVD_OPND_FAULT; R[0] = R[0] & WMASK; /* clr old ld zero */ if (R[0] > t) { /* decrease */ for (i = 0; i < (R[0] - t); i++) { /* loop thru src */ d = edit_read_src (i, acc); /* get nibble */ - if (d) cc = (cc | CC_V | CC_C) & ~CC_Z; + if (d) + cc = (cc | CC_V | CC_C) & ~CC_Z; } /* end for */ edit_adv_src (R[0] - t); /* adv src ptr */ } /* end else */ @@ -1118,7 +1145,8 @@ switch (opc) { /* case on opcode */ case EO_MOVE: for (i = 0; i < rpt; i++) { /* for repeat */ d = edit_read_src (i, acc); /* get nibble */ - if (d) cc = (cc | CC_C) & ~CC_Z; /* test for non-zero */ + if (d) /* test for non-zero */ + cc = (cc | CC_C) & ~CC_Z; c = (cc & CC_C)? (d | 0x30): fill; /* test for signif */ Write ((R[5] + i) & LMASK, c, L_BYTE, WA); } /* end for */ @@ -1149,9 +1177,11 @@ switch (opc) { /* case on opcode */ R[2] = ED_PUTCC (R[2], cc); /* update cc's */ } /* end for pattern */ - if (R[0]) RSVD_OPND_FAULT; /* pattern too short */ + if (R[0]) /* pattern too short */ + RSVD_OPND_FAULT; PSL = PSL & ~PSL_FPD; /* clear FPD */ - if (cc & CC_Z) cc = cc & ~CC_N; /* zero? clear n */ + if (cc & CC_Z) /* zero? clear n */ + cc = cc & ~CC_N; if ((cc & CC_V) && (PSL & PSW_DV)) /* overflow & trap enabled? */ SET_TRAP (TRAP_DECOVF); R[0] = R[4]; /* restore src len */ @@ -1193,12 +1223,15 @@ for (i = 0; i <= end; i++) { /* loop thru string */ t = c & 0xF; /* save sign */ c = c & 0xF0; /* erase sign */ } - if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; + 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 */ +/* ((c & 0x0F) > 0x09)) /* check lo digit */ +/* RSVD_OPND_FAULT; */ 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 */ +if ((t == 0xB) || (t == 0xD)) /* if -, set sign */ + src->sign = 1; return TestDstr (src); /* clean -0 */ } @@ -1268,15 +1301,20 @@ 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 (i == limit) /* at limit, get mask */ + mask = masktab[lnt % 8]; + else if (i > limit) /* beyond, all ovflo */ + mask = 0xFFFFFFFF; + if (dst->val[i] & mask) /* test for ovflo */ + pslv = 1; dst->val[i] = dst->val[i] & ~mask; /* clr digits past end */ - if (dst->val[i]) pslz = 0; /* test nz */ + if (dst->val[i]) /* test nz */ + pslz = 0; } dst->sign = dst->sign & ~(pslz & ~pslv); psln = dst->sign & ~pslz; /* N = sign, if ~zero */ -if (pslv && (PSL & PSW_DV)) SET_TRAP (TRAP_DECOVF); +if (pslv && (PSL & PSW_DV)) + SET_TRAP (TRAP_DECOVF); return (psln? CC_N: 0) | (pslz? CC_Z: 0) | (pslv? CC_V: 0); } @@ -1384,8 +1422,10 @@ 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; } @@ -1403,7 +1443,10 @@ int32 TestDstr (DSTR *dsrc) { int32 i; -for (i = DSTRMAX; i >= 0; i--) if (dsrc->val[i]) return (i + 1); +for (i = DSTRMAX; i >= 0; i--) { + if (dsrc->val[i]) + return (i + 1); + } dsrc->sign = 0; return 0; } @@ -1419,9 +1462,11 @@ int32 LntDstr (DSTR *dsrc, int32 nz) { int32 i; -if (nz == 0) return 0; -for (i = 7; i > 0; i--) { - if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; +if (nz == 0) + return 0; +for (i = 7; i >= 0; i--) { + if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) + break; } return ((nz - 1) * 8) + i; } @@ -1460,7 +1505,8 @@ int32 i; if (sc) { for (i = 0; i < DSTRLNT; i++) { - if ((i + sc) < DSTRLNT) dsrc->val[i] = dsrc->val[i + sc]; + if ((i + sc) < DSTRLNT) + dsrc->val[i] = dsrc->val[i + sc]; else dsrc->val[i] = 0; } } @@ -1481,9 +1527,12 @@ 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; + if (i >= sc) + dsrc->val[i] = dsrc->val[i - sc]; + else { + c |= dsrc->val[i]; + dsrc->val[i] = 0; + } } } return c; @@ -1499,14 +1548,13 @@ return c; uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin) { -int32 i, s, rs, nc; +int32 i, s, nc; if (s = sc * 4) { - rs = 32 - s; for (i = DSTRMAX; i >= 0; i--) { - nc = dsrc->val[i]; + nc = (dsrc->val[i] << (32 - s)) & LMASK; dsrc->val[i] = ((dsrc->val[i] >> s) | - (cin << rs)) & LMASK; + cin) & LMASK; cin = nc; } return cin; @@ -1524,14 +1572,13 @@ return 0; uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin) { -int32 i, s, rs, nc; +int32 i, s, nc; if (s = sc * 4) { - rs = 32 - s; for (i = 0; i < DSTRLNT; i++) { - nc = dsrc->val[i]; + nc = dsrc->val[i] >> (32 - s); dsrc->val[i] = ((dsrc->val[i] << s) | - (cin >> rs)) & LMASK; + cin) & LMASK; cin = nc; } return cin; @@ -1567,7 +1614,8 @@ 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 */ + if (r0 & LSIGN) /* more? return 0 */ + return 0; inc = (r0 >> 16) & 0x1F; /* effective inc */ } r1 = (R[1] + (inc / 2) + ((~R[0] & inc) & 1)) & LMASK; /* eff addr */ @@ -1584,9 +1632,11 @@ 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? */ + if (R[0] & LSIGN) /* more to do? */ + return; inc = (R[0] >> 16) & 0x1F; /* get excess */ - if (inc == 0) return; /* more to do? */ + if (inc == 0) /* more to do? */ + return; } R[1] = (R[1] + (inc / 2) + ((~R[0] & inc) & 1)) & LMASK;/* retire src */ R[0] = (R[0] - inc) & 0x1F; diff --git a/VAX/vax_cmode.c b/VAX/vax_cmode.c index b48fb7ea..8af75a03 100644 --- a/VAX/vax_cmode.c +++ b/VAX/vax_cmode.c @@ -125,7 +125,8 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ 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; + if (src2 & PSW_T) + PSL = PSL | PSW_T; else PSL = PSL & ~PSW_T; CMODE_JUMP (src); /* update PC */ break; @@ -137,8 +138,11 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ break; /* end case 0000xx */ case 001: /* JMP */ - if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ - else { CMODE_JUMP (GeteaW (dstspec)); } + if (dstreg) /* mode 0 illegal */ + CMODE_FAULT (CMODE_ILLI); + else { + CMODE_JUMP (GeteaW (dstspec)); + } break; case 002: /* 0002xx */ @@ -156,15 +160,18 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ CMODE_FAULT (CMODE_RSVI); break; } - if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */ + if (IR < 000260) /* clear CC */ + cc = cc & ~(IR & CC_MASK); else cc = cc | (IR & CC_MASK); /* set CC */ break; case 003: /* SWAB */ - if (dstreg) src = RdRegW (dstspec); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = ((src & BMASK) << 8) | ((src >> 8) & BMASK); - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZZ_B ((dst & BMASK)); break; @@ -178,188 +185,254 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ break; case 010: case 011: /* BNE */ - if ((cc & CC_Z) == 0) { BRANCH_F (IR); } + if ((cc & CC_Z) == 0) { + BRANCH_F (IR); + } break; case 012: case 013: /* BNE */ - if ((cc & CC_Z) == 0) { BRANCH_B (IR); } + if ((cc & CC_Z) == 0) { + BRANCH_B (IR); + } break; case 014: case 015: /* BEQ */ - if (cc & CC_Z) { BRANCH_F (IR); } + if (cc & CC_Z) { + BRANCH_F (IR); + } break; case 016: case 017: /* BEQ */ - if (cc & CC_Z) { BRANCH_B (IR); } + if (cc & CC_Z) { + BRANCH_B (IR); + } break; case 020: case 021: /* BGE */ - if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); } + if (CC_XOR_NV (cc) == 0) { + BRANCH_F (IR); + } break; case 022: case 023: /* BGE */ - if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); } + if (CC_XOR_NV (cc) == 0) { + BRANCH_B (IR); + } break; case 024: case 025: /* BLT */ - if (CC_XOR_NV (cc)) { BRANCH_F (IR); } + if (CC_XOR_NV (cc)) { + BRANCH_F (IR); + } break; case 026: case 027: /* BLT */ - if (CC_XOR_NV (cc)) { BRANCH_B (IR); } + 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); } + 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); } + 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); } + 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); } + 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 */ + if (dstreg) { /* mode 0 illegal */ + CMODE_FAULT (CMODE_ILLI); + } 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 */ + if (srcspec != 7) /* r <- PC */ + WrRegW (PC, srcspec); CMODE_JUMP (dst); /* PC <- dst */ } break; /* end JSR */ case 050: /* CLR */ - if (dstreg) WrRegW (0, dstspec); + if (dstreg) + WrRegW (0, dstspec); else WrMemW (0, GeteaW (dstspec)); cc = CC_Z; break; case 051: /* COM */ - if (dstreg) src = RdRegW (dstspec); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = src ^ WMASK; - if (dstreg) WrRegW (dst, dstspec); + 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); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src + 1) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZP_W (dst); - if (dst == 0100000) cc = cc | CC_V; + if (dst == 0100000) + cc = cc | CC_V; break; case 053: /* DEC */ - if (dstreg) src = RdRegW (dstspec); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src - 1) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZP_W (dst); - if (dst == 077777) cc = cc | CC_V; + if (dst == 077777) + cc = cc | CC_V; break; case 054: /* NEG */ - if (dstreg) src = RdRegW (dstspec); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (-src) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + 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; + if (dst == 0100000) + cc = cc | CC_V; + if (dst) + cc = cc | CC_C; break; case 055: /* ADC */ - if (dstreg) src = RdRegW (dstspec); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src + (cc & CC_C)) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + 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; + 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); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src - (cc & CC_C)) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + 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; + 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); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemW (GeteaW (dstspec)); CC_IIZZ_W (src); break; case 060: /* ROR */ - if (dstreg) src = RdRegW (dstspec); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src >> 1) | ((cc & CC_C)? WSIGN: 0); - if (dstreg) WrRegW (dst, dstspec); + 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; + 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); + 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); + 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; + 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); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src & WSIGN) | (src >> 1); - if (dstreg) WrRegW (dst, dstspec); + 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; + 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); + if (dstreg) + src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); dst = (src << 1) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + 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; + 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)" */ + if (dstreg) /* "mov dst,-(sp)" */ + dst = RdRegW (dstspec); else dst = RdMemW (GeteaW (dstspec)); WrMemW (dst, (R[6] - 2) & WMASK); R[6] = (R[6] - 2) & WMASK; @@ -370,14 +443,16 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ 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); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, (GeteaW (dstspec) & WMASK)); CC_IIZP_W (dst); break; case 067: /* SXT */ dst = (cc & CC_N)? 0177777: 0; - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, GeteaW (dstspec)); CC_IIZP_W (dst); break; @@ -398,62 +473,79 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ */ case 001: /* MOV */ - if (srcreg) src = RdRegW (srcspec); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) WrRegW (src, dstspec); + if (dstreg) + WrRegW (src, dstspec); else WrMemW (src, GeteaW (dstspec)); CC_IIZP_W (src); break; case 002: /* CMP */ - if (srcreg) src = RdRegW (srcspec); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); + 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; + 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); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); + 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); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); + if (dstreg) + src2 = RdRegW (dstspec); else src2 = RdMemMW (ea = GeteaW (dstspec)); dst = src2 & ~src; - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZP_W (dst); break; case 005: /* BIS */ - if (srcreg) src = RdRegW (srcspec); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); + if (dstreg) + src2 = RdRegW (dstspec); else src2 = RdMemMW (ea = GeteaW (dstspec)); dst = src2 | src; - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZP_W (dst); break; case 006: /* ADD */ - if (srcreg) src = RdRegW (srcspec); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); + if (dstreg) + src2 = RdRegW (dstspec); else src2 = RdMemMW (ea = GeteaW (dstspec)); dst = (src2 + src) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_ADD_W (dst, src, src2); break; @@ -479,20 +571,25 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ switch ((IR >> 9) & 07) { /* decode IR<11:9> */ case 0: /* MUL */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + if (dstreg) /* get src2 */ + src2 = RdRegW (dstspec); 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; + if (src2 & WSIGN) /* sext src, src2 */ + src2 = src2 | ~WMASK; + 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; + if ((dst > 077777) || (dst < -0100000)) + cc = cc | CC_C; break; case 1: /* DIV */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + if (dstreg) /* get src2 */ + src2 = RdRegW (dstspec); else src2 = RdMemW (GeteaW (dstspec)); t = RdRegW (srcspec); src = (((uint32) t) << 16) | RdRegW (srcspec | 1); @@ -504,8 +601,10 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ cc = CC_V; /* overflow */ break; /* done */ } - if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */ - if (t & WSIGN) src = src | ~LMASK; + if (src2 & WSIGN) /* sext src, src2 */ + src2 = src2 | ~WMASK; + if (t & WSIGN) + src = src | ~LMASK; dst = src / src2; /* divide */ if ((dst > 077777) || (dst < -0100000)) { /* out of range? */ cc = CC_V; /* overflow */ @@ -517,11 +616,13 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ break; case 2: /* ASH */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + if (dstreg) /* get src2 */ + src2 = RdRegW (dstspec); else src2 = RdMemW (GeteaW (dstspec)); src2 = src2 & 077; src = RdRegW (srcspec); /* get src */ - if (sign = ((src & WSIGN)? 1: 0)) src = src | ~WMASK; + if (sign = ((src & WSIGN)? 1: 0)) + src = src | ~WMASK; if (src2 == 0) { /* [0] */ dst = src; /* result */ oc = 0; /* last bit out */ @@ -530,12 +631,14 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ 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; + 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; + if (src) + oc = oc | CC_V; } else if (src2 == 32) { /* [32] = -32 */ dst = -sign; @@ -551,7 +654,8 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ break; case 3: /* ASHC */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + if (dstreg) /* get src2 */ + src2 = RdRegW (dstspec); else src2 = RdMemW (GeteaW (dstspec)); src2 = src2 & 077; t = RdRegW (srcspec); @@ -565,7 +669,8 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ 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; + if ((dst & LSIGN)? (i != LMASK): (i != 0)) + oc = oc | CC_V; } else if (src2 == 32) { /* [32] = -32 */ dst = -sign; @@ -583,10 +688,12 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ case 4: /* XOR */ src = RdRegW (srcspec); /* get src */ - if (dstreg) src2 = RdRegW (dstspec); /* get dst */ + if (dstreg) /* get dst */ + src2 = RdRegW (dstspec); else src2 = RdMemMW (ea = GeteaW (dstspec)); dst = src2 ^ src; - if (dstreg) WrRegW (dst, dstspec); /* result */ + if (dstreg) /* result */ + WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZP_W (dst); break; @@ -609,67 +716,99 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ case 010: switch ((IR >> 6) & 077) { /* decode IR<11:6> */ case 000: case 001: /* BPL */ - if ((cc & CC_N) == 0) { BRANCH_F (IR); } + if ((cc & CC_N) == 0) { + BRANCH_F (IR); + } break; case 002: case 003: /* BPL */ - if ((cc & CC_N) == 0) { BRANCH_B (IR); } + if ((cc & CC_N) == 0) { + BRANCH_B (IR); + } break; case 004: case 005: /* BMI */ - if (cc & CC_N) { BRANCH_F (IR); } + if (cc & CC_N) { + BRANCH_F (IR); + } break; case 006: case 007: /* BMI */ - if (cc & CC_N) { BRANCH_B (IR); } + if (cc & CC_N) { + BRANCH_B (IR); + } break; case 010: case 011: /* BHI */ - if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); } + 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); } + 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); } + if (cc & (CC_C | CC_Z)) { + BRANCH_F (IR); + } break; case 016: case 017: /* BLOS */ - if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); } + if (cc & (CC_C | CC_Z)) { + BRANCH_B (IR); + } break; case 020: case 021: /* BVC */ - if ((cc & CC_V) == 0) { BRANCH_F (IR); } + if ((cc & CC_V) == 0) { + BRANCH_F (IR); + } break; case 022: case 023: /* BVC */ - if ((cc & CC_V) == 0) { BRANCH_B (IR); } + if ((cc & CC_V) == 0) { + BRANCH_B (IR); + } break; case 024: case 025: /* BVS */ - if (cc & CC_V) { BRANCH_F (IR); } + if (cc & CC_V) { + BRANCH_F (IR); + } break; case 026: case 027: /* BVS */ - if (cc & CC_V) { BRANCH_B (IR); } + if (cc & CC_V) { + BRANCH_B (IR); + } break; case 030: case 031: /* BCC */ - if ((cc & CC_C) == 0) { BRANCH_F (IR); } + if ((cc & CC_C) == 0) { + BRANCH_F (IR); + } break; case 032: case 033: /* BCC */ - if ((cc & CC_C) == 0) { BRANCH_B (IR); } + if ((cc & CC_C) == 0) { + BRANCH_B (IR); + } break; case 034: case 035: /* BCS */ - if (cc & CC_C) { BRANCH_F (IR); } + if (cc & CC_C) { + BRANCH_F (IR); + } break; case 036: case 037: /* BCS */ - if (cc & CC_C) { BRANCH_B (IR); } + if (cc & CC_C) { + BRANCH_B (IR); + } break; case 040: case 041: case 042: case 043: /* EMT */ @@ -681,126 +820,165 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ break; case 050: /* CLRB */ - if (dstreg) WrRegB (0, dstspec); + if (dstreg) + WrRegB (0, dstspec); else WrMemB (0, GeteaB (dstspec)); cc = CC_Z; break; case 051: /* COMB */ - if (dstreg) src = RdRegB (dstspec); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = src ^ BMASK; - if (dstreg) WrRegB (dst, dstspec); + 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); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src + 1) & BMASK; - if (dstreg) WrRegB (dst, dstspec); + if (dstreg) + WrRegB (dst, dstspec); else WrMemB (dst, ea); CC_IIZP_B (dst); - if (dst == 0200) cc = cc | CC_V; + if (dst == 0200) + cc = cc | CC_V; break; case 053: /* DECB */ - if (dstreg) src = RdRegB (dstspec); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src - 1) & BMASK; - if (dstreg) WrRegB (dst, dstspec); + if (dstreg) + WrRegB (dst, dstspec); else WrMemB (dst, ea); CC_IIZP_B (dst); - if (dst == 0177) cc = cc | CC_V; + if (dst == 0177) + cc = cc | CC_V; break; case 054: /* NEGB */ - if (dstreg) src = RdRegB (dstspec); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (-src) & BMASK; - if (dstreg) WrRegB (dst, dstspec); + 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; + if (dst == 0200) + cc = cc | CC_V; + if (dst) + cc = cc | CC_C; break; case 055: /* ADCB */ - if (dstreg) src = RdRegB (dstspec); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src + (cc & CC_C)) & BMASK; - if (dstreg) WrRegB (dst, dstspec); + 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; + 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); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src - (cc & CC_C)) & BMASK; - if (dstreg) WrRegB (dst, dstspec); + 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; + 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); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemB (GeteaB (dstspec)); CC_IIZZ_B (src); break; case 060: /* RORB */ - if (dstreg) src = RdRegB (dstspec); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src >> 1) | ((cc & CC_C)? BSIGN: 0); - if (dstreg) WrRegB (dst, dstspec); + 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; + 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); + 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); + 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; + 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); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src >> 1) | (src & BSIGN); - if (dstreg) WrRegB (dst, dstspec); + 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; + 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); + if (dstreg) + src = RdRegB (dstspec); else src = RdMemMB (ea = GeteaB (dstspec)); dst = (src << 1) & BMASK; - if (dstreg) WrRegB (dst, dstspec); + 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; + 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)" */ + if (dstreg) /* "mov dst,-(sp)" */ + dst = RdRegW (dstspec); else dst = RdMemW (GeteaW (dstspec)); WrMemW (dst, (R[6] - 2) & WMASK); R[6] = (R[6] - 2) & WMASK; @@ -811,7 +989,8 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ 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); + if (dstreg) + WrRegW (dst, dstspec); else WrMemW (dst, (GeteaW (dstspec) & WMASK)); CC_IIZP_W (dst); break; @@ -828,66 +1007,85 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ */ case 011: /* MOVB */ - if (srcreg) src = RdRegB (srcspec); + if (srcreg) + src = RdRegB (srcspec); else src = RdMemB (GeteaB (srcspec)); - if (dstreg) WrRegW ((src & BSIGN)? (0xFF00 | src): src, dstspec); + 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); + if (srcreg) + src = RdRegB (srcspec); else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); + 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; + 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); + if (srcreg) + src = RdRegB (srcspec); else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); + 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); + if (srcreg) + src = RdRegB (srcspec); else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); + if (dstreg) + src2 = RdRegB (dstspec); else src2 = RdMemMB (ea = GeteaB (dstspec)); dst = src2 & ~src; - if (dstreg) WrRegB (dst, dstspec); + if (dstreg) + WrRegB (dst, dstspec); else WrMemB (dst, ea); CC_IIZP_B (dst); break; case 015: /* BISB */ - if (srcreg) src = RdRegB (srcspec); + if (srcreg) + src = RdRegB (srcspec); else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); + if (dstreg) + src2 = RdRegB (dstspec); else src2 = RdMemMB (ea = GeteaB (dstspec)); dst = src2 | src; - if (dstreg) WrRegB (dst, dstspec); + if (dstreg) + WrRegB (dst, dstspec); else WrMemB (dst, ea); CC_IIZP_B (dst); break; case 016: /* SUB */ - if (srcreg) src = RdRegW (srcspec); + if (srcreg) + src = RdRegW (srcspec); else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); + if (dstreg) + src2 = RdRegW (dstspec); else src2 = RdMemMW (ea = GeteaW (dstspec)); dst = (src2 - src) & WMASK; - if (dstreg) WrRegW (dst, dstspec); + 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; + if (((src ^ src2) & (~src ^ dst)) & WSIGN) + cc = cc | CC_V; + if (src2 < src) + cc = cc | CC_C; break; default: @@ -915,11 +1113,13 @@ switch (spec >> 3) { /* decode spec<5:3> */ default: /* can't get here */ case 1: /* (R) */ - if (reg == 7) return (PC & WMASK); + if (reg == 7) + return (PC & WMASK); else return (R[reg] & WMASK); case 2: /* (R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + if (reg == 7) + PC = ((adr = PC) + 2) & WMASK; else { R[reg] = ((adr = R[reg]) + 2) & WMASK; recq[recqptr++] = RQ_REC (AIN|RW, reg); @@ -927,7 +1127,8 @@ switch (spec >> 3) { /* decode spec<5:3> */ return adr; case 3: /* @(R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + if (reg == 7) + PC = ((adr = PC) + 2) & WMASK; else { R[reg] = ((adr = R[reg]) + 2) & WMASK; recq[recqptr++] = RQ_REC (AIN|RW, reg); @@ -935,7 +1136,8 @@ switch (spec >> 3) { /* decode spec<5:3> */ return RdMemW (adr); case 4: /* -(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; + if (reg == 7) + adr = PC = (PC - 2) & WMASK; else { adr = R[reg] = (R[reg] - 2) & WMASK; recq[recqptr++] = RQ_REC (ADC|RW, reg); @@ -943,7 +1145,8 @@ switch (spec >> 3) { /* decode spec<5:3> */ return adr; case 5: /* @-(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; + if (reg == 7) + adr = PC = (PC - 2) & WMASK; else { adr = R[reg] = (R[reg] - 2) & WMASK; recq[recqptr++] = RQ_REC (ADC|RW, reg); @@ -953,13 +1156,15 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 6: /* d(r) */ adr = RdMemW (PC); PC = (PC + 2) & WMASK; - if (reg == 7) return ((PC + adr) & 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; + if (reg == 7) + adr = (PC + adr) & WMASK; else adr = (R[reg] + adr) & WMASK; return RdMemW (adr); } /* end switch */ @@ -974,11 +1179,13 @@ switch (spec >> 3) { /* decode spec<5:3> */ default: /* can't get here */ case 1: /* (R) */ - if (reg == 7) return (PC & WMASK); + if (reg == 7) + return (PC & WMASK); else return (R[reg] & WMASK); case 2: /* (R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + 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); @@ -990,7 +1197,8 @@ switch (spec >> 3) { /* decode spec<5:3> */ return adr; case 3: /* @(R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + if (reg == 7) + PC = ((adr = PC) + 2) & WMASK; else { R[reg] = ((adr = R[reg]) + 2) & WMASK; recq[recqptr++] = RQ_REC (AIN|RW, reg); @@ -998,7 +1206,8 @@ switch (spec >> 3) { /* decode spec<5:3> */ return RdMemW (adr); case 4: /* -(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; + 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); @@ -1010,7 +1219,8 @@ switch (spec >> 3) { /* decode spec<5:3> */ return adr; case 5: /* @-(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; + if (reg == 7) + adr = PC = (PC - 2) & WMASK; else { adr = R[reg] = (R[reg] - 2) & WMASK; recq[recqptr++] = RQ_REC (ADC|RW, reg); @@ -1020,13 +1230,15 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 6: /* d(r) */ adr = RdMemW (PC); PC = (PC + 2) & WMASK; - if (reg == 7) return ((PC + adr) & 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; + if (reg == 7) + adr = (PC + adr) & WMASK; else adr = (R[reg] + adr) & WMASK; return RdMemW (adr); } /* end switch */ @@ -1038,7 +1250,8 @@ int32 RdMemW (int32 a) { int32 acc = ACC_MASK (USER); -if (a & 1) CMODE_FAULT (CMODE_ODD); +if (a & 1) + CMODE_FAULT (CMODE_ODD); return Read (a, L_WORD, RA); } @@ -1046,7 +1259,8 @@ int32 RdMemMW (int32 a) { int32 acc = ACC_MASK (USER); -if (a & 1) CMODE_FAULT (CMODE_ODD); +if (a & 1) + CMODE_FAULT (CMODE_ODD); return Read (a, L_WORD, WA); } @@ -1054,33 +1268,40 @@ void WrMemW (int32 d, int32 a) { int32 acc = ACC_MASK (USER); -if (a & 1) CMODE_FAULT (CMODE_ODD); +if (a & 1) + CMODE_FAULT (CMODE_ODD); Write (a, d, L_WORD, WA); return; } int32 RdRegB (int32 rn) { -if (rn == 7) return (PC & BMASK); +if (rn == 7) + return (PC & BMASK); else return (R[rn] & BMASK); } int32 RdRegW (int32 rn) { -if (rn == 7) return (PC & WMASK); +if (rn == 7) + return (PC & WMASK); else return (R[rn] & WMASK); } void WrRegB (int32 val, int32 rn) { -if (rn == 7) { CMODE_JUMP ((PC & ~BMASK) | val); } +if (rn == 7) { + CMODE_JUMP ((PC & ~BMASK) | val); + } else R[rn] = (R[rn] & ~BMASK) | val; return; } void WrRegW (int32 val, int32 rn) { -if (rn == 7) { CMODE_JUMP (val); } +if (rn == 7) { + CMODE_JUMP (val); + } else R[rn] = val; return; } diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c index ec0e4ba7..aad5a5f0 100644 --- a/VAX/vax_cpu.c +++ b/VAX/vax_cpu.c @@ -25,6 +25,7 @@ cpu VAX central processor + 21-May-08 RMS Removed inline support 28-May-08 RMS Inlined instruction prefetch, physical memory routines 13-Aug-07 RMS Fixed bug in read access g-format indexed specifiers 28-Apr-07 RMS Removed clock initialization @@ -184,14 +185,20 @@ #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); \ +#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); \ +#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); \ +#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) || \ @@ -200,7 +207,8 @@ Write (va + 4, rh, L_LONG, WA); \ } \ else { \ - if (rn >= nSP) RSVD_ADDR_FAULT; \ + if (rn >= nSP) \ + RSVD_ADDR_FAULT; \ R[rn] = rl; \ R[rn + 1] = rh; \ } @@ -488,7 +496,8 @@ int32 acc; /* set by setjmp */ int abortval; t_stat r; -if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ +if ((r = build_dib_tab ()) != SCPE_OK) /* build, chk dib_tab */ + return r; if ((PSL & PSL_MBZ) || /* validate PSL */ ((PSL & PSL_CM) && BadCmPSL (PSL)) || /* validate PSL */ ((PSL_GETCUR (PSL) != KERN) && /* esu => is, ipl = 0 */ @@ -516,7 +525,8 @@ else if (abortval < 0) { /* mm or rsrv or int */ 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; + if (recq[i] & RQ_DIR) + R[rrn] = R[rrn] - rlnt; else R[rrn] = R[rrn] + rlnt; } } @@ -529,14 +539,16 @@ else if (abortval < 0) { /* mm or rsrv or int */ 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 */ + if (in_ie) /* in exc? panic */ + ABORT (STOP_INIE); 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 */ + if (in_ie) /* in exc? panic */ + ABORT (STOP_INIE); cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ GET_CUR; in_ie = 1; @@ -548,7 +560,8 @@ else if (abortval < 0) { /* mm or rsrv or int */ 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 */ + if (PSL & PSL_IS) /* on is? panic */ + ABORT (STOP_INIE); cc = intexc (SCB_KSNV, cc, 0, IE_SVE); /* ksnv */ GET_CUR; } @@ -564,7 +577,8 @@ else if (abortval < 0) { /* mm or rsrv or int */ break; case SCB_MCHK: /* machine check */ - if (in_ie) ABORT (STOP_INIE); /* in exception? */ + if (in_ie) /* in exc? panic */ + ABORT (STOP_INIE); cc = machine_check (p1, opc, cc, delta); /* system specific */ in_ie = 0; GET_CUR; /* PSL changed */ @@ -596,7 +610,8 @@ for ( ;; ) { recqptr = 0; /* clr recovery q */ if (sim_interval <= 0) { /* chk clock queue */ temp = sim_process_event (); - if (temp) ABORT (temp); + if (temp) + ABORT (temp); SET_IRQL; /* update interrupts */ } @@ -627,13 +642,15 @@ for ( ;; ) { continue; /* continue */ } else if (temp >= IPL_HMIN) /* hardware req? */ - vec = get_vector (temp); /* get vector */ - else if (temp > IPL_SMAX) ABORT (STOP_UIPL); + 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 */ + if (vec) /* take intr */ + cc = intexc (vec, cc, temp, IE_INT); GET_CUR; /* set cur mode */ } else trpirq = 0; /* clear everything */ @@ -648,7 +665,8 @@ for ( ;; ) { GET_CUR; /* set cur mode */ continue; } - if (PSL & PSW_T) PSL = PSL | PSL_TP; /* if T, set TP */ + if (PSL & PSW_T) /* if T, set TP */ + PSL = PSL | PSL_TP; if (PSL & PSL_CM) { /* compat mode? */ cc = op_cmode (cc); /* exec instr */ continue; /* skip fetch */ @@ -668,7 +686,8 @@ for ( ;; ) { } numspec = drom[opc][0]; /* get # specs */ if (PSL & PSL_FPD) { - if ((numspec & DR_F) == 0) RSVD_INST_FAULT; + if ((numspec & DR_F) == 0) + RSVD_INST_FAULT; } else { numspec = numspec & DR_NSPMASK; /* get # specifiers */ @@ -961,7 +980,9 @@ for ( ;; ) { 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); } + 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; @@ -1485,7 +1506,8 @@ for ( ;; ) { for (i = 0; i < j; i++) hst[hst_p].opnd[i] = opnd[i]; lim = PC - fault_PC; - if ((uint32) lim > INST_SIZE) lim = INST_SIZE; + if ((uint32) lim > INST_SIZE) + lim = INST_SIZE; for (i = 0; i < lim; i++) { if ((cpu_ex (&wd, fault_PC + i, &cpu_unit, SWMASK ('V'))) == SCPE_OK) hst[hst_p].inst[i] = (uint8) wd; @@ -1495,7 +1517,8 @@ for ( ;; ) { } } hst_p = hst_p + 1; - if (hst_p >= hst_lnt) hst_p = 0; + if (hst_p >= hst_lnt) + hst_p = 0; } /* Dispatch to instructions */ @@ -1683,14 +1706,18 @@ for ( ;; ) { r = op0 & BMASK; /* set result */ WRITE_B (r); /* store result */ CC_IIZZ_B (r); /* initial cc's */ - if ((op0 > 127) || (op0 < -128)) { V_INTOV; } + 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; } + if ((op0 > 32767) || (op0 < -32768)) { + V_INTOV; + } break; case CVTWB: @@ -1698,13 +1725,16 @@ for ( ;; ) { 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; } + if ((temp > 127) || (temp < -128)) { + V_INTOV; + } break; case ADAWI: if (op1 >= 0) temp = R[op1] & WMASK; /* reg? ADDW2 */ else { - if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */ + if (op2 & 1) /* mem? chk align */ + RSVD_OPND_FAULT; temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */ } r = (op0 + temp) & WMASK; @@ -1771,7 +1801,8 @@ for ( ;; ) { 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 */ + if ((r == op1) && op0) /* special case */ + cc = cc | CC_C; break; case ADDL2: case ADDL3: @@ -1796,7 +1827,8 @@ for ( ;; ) { 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 */ + if ((op0 == op1) && r) /* special case */ + cc = cc | CC_C; break; case SUBL2: case SUBL3: @@ -1810,7 +1842,9 @@ for ( ;; ) { 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; } + if ((temp > 127) || (temp < -128)) { + V_INTOV; + } break; case MULW2: case MULW3: @@ -1818,14 +1852,18 @@ for ( ;; ) { 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; } + 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 */ + if (rh != ((r & LSIGN)? -1: 0)) { /* chk overflow */ + V_INTOV; + } break; case DIVB2: case DIVB3: @@ -1970,8 +2008,8 @@ for ( ;; ) { case ROTL: j = op0 % 32; /* reduce sc, mod 32 */ - if (j) r = ((((uint32) op1) << j) | - (((uint32) op1) >> (32 - j))) & LMASK; + 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 */ @@ -1980,21 +2018,25 @@ for ( ;; ) { case ASHL: if (op0 & BSIGN) { /* right shift? */ temp = 0x100 - op0; /* get |shift| */ - if (temp > 31) r = (op1 & LSIGN)? LMASK: 0; /* sc > 31? */ + if (temp > 31) /* sc > 31? */ + r = (op1 & LSIGN)? LMASK: 0; 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? */ + if (op0 > 31) /* sc > 31? */ + r = temp = 0; 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? */ + if (op1 != temp) { /* bits lost? */ + V_INTOV; + } } break; @@ -2002,7 +2044,9 @@ for ( ;; ) { 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 */ + if (flg) { /* if ovflo, set */ + V_INTOV; + } break; /* EMUL - emul mplr.rl,mpcn.rl,add.rl,dst.wq @@ -2031,7 +2075,8 @@ for ( ;; ) { */ case EDIV: - if (op5 < 0) Read (op6, L_LONG, WA); /* wtest remainder */ + if (op5 < 0) /* wtest remainder */ + Read (op6, L_LONG, WA); if (op0 == 0) { /* divide by zero? */ flg = CC_V; /* set V */ r = opnd[1]; /* quo = low divd */ @@ -2040,11 +2085,15 @@ for ( ;; ) { } else { r = op_ediv (opnd, &rh, &flg); /* extended divide */ - if (flg) { INTOV; } /* if ovf+IV, set trap */ + if (flg) { /* if ovf+IV, set trap */ + INTOV; + } } - if (op3 >= 0) R[op3] = r; /* store quotient */ + if (op3 >= 0) /* store quotient */ + R[op3] = r; else Write (op4, r, L_LONG, WA); - if (op5 >= 0) R[op5] = rh; /* store remainder */ + if (op5 >= 0) /* store remainder */ + R[op5] = rh; else Write (op6, rh, L_LONG, WA); CC_IIZZ_L (r); /* set cc's */ cc = cc | flg; /* set V if required */ @@ -2079,51 +2128,63 @@ for ( ;; ) { break; case BGEQ: - if (!(cc & CC_N)) BRANCHB (brdisp); /* br if N = 0 */ + if (!(cc & CC_N)) /* br if N = 0 */ + BRANCHB (brdisp); break; case BLSS: - if (cc & CC_N) BRANCHB (brdisp); /* br if N = 1 */ + if (cc & CC_N) /* br if N = 1 */ + BRANCHB (brdisp); break; case BNEQ: - if (!(cc & CC_Z)) BRANCHB (brdisp); /* br if Z = 0 */ + if (!(cc & CC_Z)) /* br if Z = 0 */ + BRANCHB (brdisp); break; case BEQL: - if (cc & CC_Z) BRANCHB (brdisp); /* br if Z = 1 */ + if (cc & CC_Z) /* br if Z = 1 */ + BRANCHB (brdisp); break; case BVC: - if (!(cc & CC_V)) BRANCHB (brdisp); /* br if V = 0 */ + if (!(cc & CC_V)) /* br if V = 0 */ + BRANCHB (brdisp); break; case BVS: - if (cc & CC_V) BRANCHB (brdisp); /* br if V = 1 */ + if (cc & CC_V) /* br if V = 1 */ + BRANCHB (brdisp); break; case BGEQU: - if (!(cc & CC_C)) BRANCHB (brdisp); /* br if C = 0 */ + if (!(cc & CC_C)) /* br if C = 0 */ + BRANCHB (brdisp); break; case BLSSU: - if (cc & CC_C) BRANCHB (brdisp); /* br if C = 1 */ + if (cc & CC_C) /* br if C = 1 */ + BRANCHB (brdisp); break; case BGTR: - if (!(cc & (CC_N | CC_Z))) BRANCHB (brdisp); /* br if N | Z = 0 */ + if (!(cc & (CC_N | CC_Z))) /* br if N | Z = 0 */ + BRANCHB (brdisp); break; case BLEQ: - if (cc & (CC_N | CC_Z)) BRANCHB (brdisp); /* br if N | Z = 1 */ + if (cc & (CC_N | CC_Z)) /* br if N | Z = 1 */ + BRANCHB (brdisp); break; case BGTRU: - if (!(cc & (CC_C | CC_Z))) BRANCHB (brdisp); /* br if C | Z = 0 */ + if (!(cc & (CC_C | CC_Z))) /* br if C | Z = 0 */ + BRANCHB (brdisp); break; case BLEQU: - if (cc & (CC_C | CC_Z)) BRANCHB (brdisp); /* br if C | Z = 1 */ + if (cc & (CC_C | CC_Z)) /* br if C | Z = 1 */ + BRANCHB (brdisp); break; /* Simple jumps and subroutine calls - op addr.ab @@ -2158,7 +2219,8 @@ for ( ;; ) { 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 */ + if (r >= 0) /* if >= 0, branch */ + BRANCHB (brdisp); break; case SOBGTR: @@ -2166,7 +2228,8 @@ for ( ;; ) { 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 */ + if (r > 0) /* if >= 0, branch */ + BRANCHB (brdisp); break; /* AOB instructions - op limit.rl,idx.ml,disp.bb @@ -2183,7 +2246,8 @@ for ( ;; ) { 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 */ + if (r < op0) /* if < lim, branch */ + BRANCHB (brdisp); break; case AOBLEQ: @@ -2191,7 +2255,8 @@ for ( ;; ) { 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 */ + if (r <= op0) /* if < lim, branch */ + BRANCHB (brdisp); break; /* ACB instructions - op limit.rx,add.rx,index.mx,disp.bw @@ -2209,8 +2274,8 @@ for ( ;; ) { 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); + if ((op1 & BSIGN)? (SXTB (r) >= SXTB (op0)): (SXTB (r) <= SXTB (op0))) + BRANCHW (brdisp); break; case ACBW: @@ -2218,8 +2283,8 @@ for ( ;; ) { 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); + if ((op1 & WSIGN)? (SXTW (r) >= SXTW (op0)): (SXTW (r) <= SXTW (op0))) + BRANCHW (brdisp); break; case ACBL: @@ -2241,7 +2306,8 @@ for ( ;; ) { 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)? */ + if (r > op2) /* r > limit (unsgnd)? */ + JUMP (PC + ((op2 + 1) * 2)); else { temp = Read (PC + (r * 2), L_WORD, RA); BRANCHW (temp); @@ -2251,7 +2317,8 @@ for ( ;; ) { 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)? */ + if (r > op2) /* r > limit (unsgnd)? */ + JUMP (PC + ((op2 + 1) * 2)); else { temp = Read (PC + (r * 2), L_WORD, RA); BRANCHW (temp); @@ -2262,7 +2329,7 @@ for ( ;; ) { 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)); + JUMP (PC + ((op2 + 1) * 2)); else { temp = Read (PC + (r * 2), L_WORD, RA); BRANCHW (temp); @@ -2277,35 +2344,43 @@ for ( ;; ) { */ case BBS: - if (op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit set */ + if (op_bb_n (opnd, acc)) /* br if bit set */ + BRANCHB (brdisp); break; case BBC: - if (!op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit clr */ + if (!op_bb_n (opnd, acc)) /* br if bit clr */ + BRANCHB (brdisp); break; case BBSS: case BBSSI: - if (op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, set */ + if (op_bb_x (opnd, 1, acc)) /* br if set, set */ + BRANCHB (brdisp); break; case BBCC: case BBCCI: - if (!op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, clr*/ + if (!op_bb_x (opnd, 0, acc)) /* br if clr, clr*/ + BRANCHB (brdisp); break; case BBSC: - if (op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, set */ + if (op_bb_x (opnd, 0, acc)) /* br if clr, set */ + BRANCHB (brdisp); break; case BBCS: - if (!op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, clr */ + if (!op_bb_x (opnd, 1, acc)) /* br if set, clr */ + BRANCHB (brdisp); break; case BLBS: - if (op0 & 1) BRANCHB (brdisp); /* br if bit set */ + if (op0 & 1) /* br if bit set */ + BRANCHB (brdisp); break; case BLBC: - if ((op0 & 1) == 0) BRANCHB (brdisp); /* br if bit clear */ + if ((op0 & 1) == 0) /* br if bit clear */ + BRANCHB (brdisp); break; /* Extract field instructions - ext?v pos.rl,size.rb,base.wb,dst.wl @@ -2321,7 +2396,8 @@ for ( ;; ) { case EXTV: r = op_extv (opnd, vfldrp1, acc); /* get field */ - if (r & byte_sign[op1]) r = r | ~byte_mask[op1]; + if (r & byte_sign[op1]) + r = r | ~byte_mask[op1]; WRITE_L (r); /* store field */ CC_IIZP_L (r); /* set cc's */ break; @@ -2343,7 +2419,8 @@ for ( ;; ) { case CMPV: r = op_extv (opnd, vfldrp1, acc); /* get field */ - if (r & byte_sign[op1]) r = r | ~byte_mask[op1]; + if (r & byte_sign[op1]) + r = r | ~byte_mask[op1]; CC_CMP_L (r, op4); /* set cc's */ break; @@ -2412,7 +2489,8 @@ for ( ;; ) { /* Miscellaneous instructions */ case HALT: - if (PSL & PSL_CUR) RSVD_INST_FAULT; /* not kern? rsvd inst */ + if (PSL & PSL_CUR) /* not kern? rsvd inst */ + RSVD_INST_FAULT; else if (cpu_unit.flags & UNIT_CONH) /* halt to console? */ cc = con_halt (CON_HLTINS, cc); /* enter firmware */ else { @@ -2435,13 +2513,15 @@ for ( ;; ) { break; case BISPSW: - if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT; + 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; + if (opnd[0] & PSW_MBZ) + RSVD_OPND_FAULT; PSL = PSL & ~opnd[0]; cc = cc & ~opnd[0]; break; @@ -2460,7 +2540,8 @@ for ( ;; ) { break; case INDEX: - if ((op0 < op1) || (op0 > op2)) SET_TRAP (TRAP_SUBSCR); + if ((op0 < op1) || (op0 > op2)) + SET_TRAP (TRAP_SUBSCR); r = (op0 + op4) * op3; WRITE_L (r); CC_IIZZ_L (r); @@ -2529,13 +2610,15 @@ for ( ;; ) { break; case MOVD: - if ((r = op_movfd (op0)) == 0) op1 = 0; + 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; + if ((r = op_movg (op0)) == 0) + op1 = 0; WRITE_Q (r, op1); CC_IIZP_FP (r); break; @@ -2547,13 +2630,15 @@ for ( ;; ) { break; case MNEGD: - if ((r = op_mnegfd (op0)) == 0) op1 = 0; + 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; + if ((r = op_mnegg (op0)) == 0) + op1 = 0; WRITE_Q (r, op1); CC_IIZZ_FP (r); break; @@ -2610,14 +2695,18 @@ for ( ;; ) { r = op_cvtfdgi (opnd, &flg, opc) & BMASK; WRITE_B (r); CC_IIZZ_B (r); - if (flg) { V_INTOV; } + if (flg) { + V_INTOV; + } break; case CVTFW: case CVTDW: case CVTGW: r = op_cvtfdgi (opnd, &flg, opc) & WMASK; WRITE_W (r); CC_IIZZ_W (r); - if (flg) { V_INTOV; } + if (flg) { + V_INTOV; + } break; case CVTFL: case CVTDL: case CVTGL: @@ -2625,7 +2714,9 @@ for ( ;; ) { r = op_cvtfdgi (opnd, &flg, opc) & LMASK; WRITE_L (r); CC_IIZZ_L (r); - if (flg) { V_INTOV; } + if (flg) { + V_INTOV; + } break; case CVTFD: @@ -2730,7 +2821,8 @@ for ( ;; ) { 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); + !(temp & CC_N): (temp & CC_N))) + BRANCHW (brdisp); break; case ACBD: @@ -2739,7 +2831,8 @@ for ( ;; ) { WRITE_Q (r, rh); CC_IIZP_FP (r); if ((temp & CC_Z) || ((op2 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); + !(temp & CC_N): (temp & CC_N))) + BRANCHW (brdisp); break; case ACBG: @@ -2748,7 +2841,8 @@ for ( ;; ) { WRITE_Q (r, rh); CC_IIZP_FP (r); if ((temp & CC_Z) || ((op2 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); + !(temp & CC_N): (temp & CC_N))) + BRANCHW (brdisp); break; /* EMODF @@ -2762,12 +2856,16 @@ for ( ;; ) { case EMODF: r = op_emodf (opnd, &temp, &flg); - if (op5 < 0) Read (op6, L_LONG, WA); - if (op3 >= 0) R[op3] = temp; + 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; } + if (flg) { + V_INTOV; + } break; /* EMODD, EMODG @@ -2785,11 +2883,14 @@ for ( ;; ) { Read (op8, L_BYTE, WA); Read ((op8 + 7) & LMASK, L_BYTE, WA); } - if (op5 >= 0) R[op5] = temp; + 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; } + if (flg) { + V_INTOV; + } break; case EMODG: @@ -2798,11 +2899,14 @@ for ( ;; ) { Read (op8, L_BYTE, WA); Read ((op8 + 7) & LMASK, L_BYTE, WA); } - if (op5 >= 0) R[op5] = temp; + 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; } + if (flg) { + V_INTOV; + } break; /* POLY */ @@ -2923,17 +3027,21 @@ 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 (ppc < 0) + Read ((PC + ibcnt) & ~03, L_LONG, RA); } - if (ibcnt == 0) ibufl = ReadLP (ppc); /* fill low */ + if (ibcnt == 0) /* fill low */ + ibufl = ReadLP (ppc); 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? */ +if (lnt == L_BYTE) /* byte? */ + val = (ibufl >> (bo << 3)) & BMASK; else if (lnt == L_WORD) { /* word? */ - if (bo == 3) val = ((ibufl >> 24) & 0xFF) | ((ibufh & 0xFF) << 8); + if (bo == 3) + val = ((ibufl >> 24) & 0xFF) | ((ibufh & 0xFF) << 8); else val = (ibufl >> (bo << 3)) & WMASK; } else if (bo) { /* unaligned lw? */ @@ -2996,10 +3104,13 @@ PSL = PSL_IS | PSL_IPL1F; SISR = 0; ASTLVL = 4; mapen = 0; -if (M == NULL) M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32)); -if (M == NULL) return SCPE_MEM; +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; +if (pcq_r) + pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = sim_brk_dflt = SWMASK ('E'); return build_dib_tab (); @@ -3012,7 +3123,8 @@ t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) int32 st; uint32 addr = (uint32) exta; -if (vptr == NULL) return SCPE_ARG; +if (vptr == NULL) + return SCPE_ARG; if (sw & SWMASK ('V')) { int32 acc = cpu_get_vsw (sw); addr = Test (addr, acc, &st); @@ -3058,14 +3170,18 @@ int32 mc = 0; uint32 i, clim; uint32 *nM = NULL; -if ((val <= 0) || (val > MAXMEMSIZE_X)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2]; +if ((val <= 0) || (val > MAXMEMSIZE_X)) + 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 = (uint32 *) calloc (val >> 2, sizeof (uint32)); -if (nM == NULL) return SCPE_MEM; +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]; +for (i = 0; i < clim; i = i + 4) + nM[i >> 2] = M[i >> 2]; free (M); M = nM; MEMSIZE = val; @@ -3095,7 +3211,8 @@ if (cptr) { if (r == SCPE_OK) { int32 acc = cpu_get_vsw (sim_switches); pa = Test (va, acc, &st); - if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X\n", va, pa); + if (st == PR_OK) + fprintf (of, "Virtual %-X = physical %-X\n", va, pa); else fprintf (of, "Virtual %-X: %s\n", va, mm_str[st]); return SCPE_OK; } @@ -3111,10 +3228,14 @@ int32 cpu_get_vsw (int32 sw) int32 md; set_map_reg (); /* update dyn reg */ -if (sw & SWMASK ('K')) md = KERN; -else if (sw & SWMASK ('E')) md = EXEC; -else if (sw & SWMASK ('S')) md = SUPV; -else if (sw & SWMASK ('U')) md = USER; +if (sw & SWMASK ('K')) + md = KERN; +else if (sw & SWMASK ('E')) + md = EXEC; +else if (sw & SWMASK ('S')) + md = SUPV; +else if (sw & SWMASK ('U')) + md = USER; else md = PSL_GETCUR (PSL); return ACC_MASK (md); } @@ -3127,12 +3248,14 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].iPC = 0; + 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; +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); @@ -3141,7 +3264,8 @@ if (hst_lnt) { } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); - if (hst == NULL) return SCPE_MEM; + if (hst == NULL) + return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; @@ -3160,18 +3284,22 @@ extern t_value *sim_eval; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ -if (di < 0) di = di + hst_lnt; +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? */ + if (h->iPC == 0) /* filled in? */ + continue; fprintf(st, "%08X %08X| ", h->iPC, h->PSL); /* PC, PSL */ numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */ if (opcode[h->opc] == NULL) /* undefined? */ @@ -3179,7 +3307,8 @@ for (k = 0; k < lnt; k++) { /* print specified */ else if (h->PSL & PSL_FPD) /* FPD set? */ fprintf (st, "%s FPD set", opcode[h->opc]); else { /* normal */ - for (i = 0; i < INST_SIZE; i++) sim_eval[i] = h->inst[i]; + for (i = 0; i < INST_SIZE; i++) + sim_eval[i] = h->inst[i]; if ((fprint_sym (st, h->iPC, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) fprintf (st, "%03X (undefined)", h->opc); if ((numspec > 1) || @@ -3207,21 +3336,26 @@ numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */ fputs ("\n ", st); /* space */ for (i = 1, j = 0, more = FALSE; i <= numspec; i++) { /* loop thru specs */ disp = drom[h->opc][i]; /* specifier type */ - if (disp == RG) disp = RQ; /* fix specials */ - else if (disp >= BB) break; /* ignore branches */ + if (disp == RG) /* fix specials */ + disp = RQ; + else if (disp >= BB) + break; /* ignore branches */ 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 */ - if (line == 0) fprintf (st, " %08X", h->opnd[j]); + if (line == 0) + fprintf (st, " %08X", h->opnd[j]); else fputs (" ", st); j = j + 1; break; case RQ: case MQ: /* read, modify quad */ - if (line <= 1) fprintf (st, " %08X", h->opnd[j + line]); + if (line <= 1) + fprintf (st, " %08X", h->opnd[j + line]); else fputs (" ", st); - if (line == 0) more = TRUE; + if (line == 0) + more = TRUE; j = j + 2; break; case RO: case MO: /* read, modify octa */ @@ -3230,7 +3364,8 @@ for (i = 1, j = 0, more = FALSE; i <= numspec; i++) { /* loop thru specs */ j = j + 4; break; case WB: case WW: case WL: case WQ: case WO: /* write */ - if (line == 0) fprintf (st, " %08X", h->opnd[j + 1]); + if (line == 0) + fprintf (st, " %08X", h->opnd[j + 1]); else fputs (" ", st); j = j + 2; break; diff --git a/VAX/vax_cpu1.c b/VAX/vax_cpu1.c index d0ba90cf..8e1b71ab 100644 --- a/VAX/vax_cpu1.c +++ b/VAX/vax_cpu1.c @@ -129,7 +129,8 @@ int32 rn = opnd[1]; int32 ea, by; if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ + if (((uint32) pos) > 31) /* pos > 31? fault */ + RSVD_OPND_FAULT; return (R[rn] >> pos) & 1; /* get bit */ } ea = opnd[2] + (pos >> 3); /* base byte addr */ @@ -145,7 +146,8 @@ int32 rn = opnd[1]; int32 ea, by, bit; if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ + if (((uint32) pos) > 31) /* pos > 31? fault */ + RSVD_OPND_FAULT; bit = (R[rn] >> pos) & 1; /* get bit */ R[rn] = newb? (R[rn] | (1u << pos)): (R[rn] & ~(1u << pos)); return bit; @@ -177,21 +179,27 @@ 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 (size == 0) /* size 0? field = 0 */ + return 0; +if (size > 32) /* size > 32? fault */ + RSVD_OPND_FAULT; if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ + if (((uint32) pos) > 31) /* pos > 31? fault */ + RSVD_OPND_FAULT; if (((pos + size) > 32) && (rn >= nSP)) /* span 2 reg, PC? */ RSVD_ADDR_FAULT; /* fault */ - if (pos) wd = (wd >> pos) | (((uint32) vfldrp1) << (32 - pos)); + 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 + pos) > 32) + wd1 = Read (ba + 4, L_LONG, RA); + if (pos) + wd = (wd >> pos) | (((uint32) wd1) << (32 - pos)); } return wd & byte_mask[size]; } @@ -215,12 +223,16 @@ 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 (size == 0) /* size = 0? done */ + return; +if (size > 32) /* size > 32? fault */ + RSVD_OPND_FAULT; if (rn >= 0) { /* in registers? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ + if (((uint32) pos) > 31) /* pos > 31? fault */ + RSVD_OPND_FAULT; if ((pos + size) > 32) { /* span two reg? */ - if (rn >= nSP) RSVD_ADDR_FAULT; /* if PC, fault */ + if (rn >= nSP) /* if PC, fault */ + RSVD_ADDR_FAULT; mask = byte_mask[pos + size - 32]; /* insert fragment */ val = ins >> (32 - pos); R[rn + 1] = (vfldrp1 & ~mask) | (val & mask); @@ -253,7 +265,10 @@ int32 op_ffs (uint32 wd, int32 size) { int32 i; -for (i = 0; wd; i++, wd = wd >> 1) if (wd & 1) return i; +for (i = 0; wd; i++, wd = wd >> 1) { + if (wd & 1) + return i; + } return size; } @@ -345,7 +360,8 @@ 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 */ +if (mask & CALL_MBZ) /* test mbz */ + RSVD_OPND_FAULT; stklen = rcnt[mask & 077] + rcnt[(mask >> 6) & 077] + (gs? 24: 20); Read (SP - stklen, L_BYTE, WA); /* wchk stk */ if (gs) { @@ -372,7 +388,8 @@ 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 */ +if (gs) /* update AP */ + AP = SP; else AP = opnd[0]; SP = FP = tsp - 20; /* update FP, SP */ PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV)) | /* update PSW */ @@ -388,7 +405,8 @@ 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 */ +if (spamask & PSW_MBZ) /* test mbz */ + RSVD_OPND_FAULT; 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 */ @@ -426,7 +444,8 @@ void op_pushr (int32 *opnd, int32 acc) int32 mask = opnd[0] & 0x7FFF; int32 stklen, tsp; -if (mask == 0) return; +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 */ @@ -455,7 +474,8 @@ void op_popr (int32 *opnd, int32 acc) int32 mask = opnd[0] & 0x7FFF; int32 stklen; -if (mask == 0) return; +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 */ @@ -473,7 +493,8 @@ 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) /* if pop SP, no inc */ + SP = Read (SP, L_LONG, RA); return; } @@ -552,12 +573,14 @@ 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 */ + if (opnd[1] < 0) /* wchk dest */ + Read (opnd[2], L_LONG, WA); 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 */ +if (opnd[1] >= 0) /* store result */ + R[opnd[1]] = e; else Write (opnd[2], e, L_LONG, WA); return cc; } @@ -598,14 +621,18 @@ int32 h = opnd[1]; int32 d = opnd[0]; int32 a, t; -if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */ +if ((h == d) || ((h | d) & 07)) /* h, d quad align? */ + RSVD_OPND_FAULT; 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 */ +if (a & 06) /* chk quad align */ + RSVD_OPND_FAULT; +if (a & 01) /* busy, cc = 0001 */ + return CC_C; 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 */ +if (Test (a, WA, &t) < 0) /* wtst a, rls if err */ + Write (h, a - h, L_LONG, WA); 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 */ @@ -619,19 +646,24 @@ 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? */ +if ((h == d) || ((h | d) & 07)) /* h, d quad align? */ + RSVD_OPND_FAULT; 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 */ +if (a == 0) /* if empty, ins hd */ + return op_insqhi (opnd, acc); +if (a & 06) /* chk quad align */ + RSVD_OPND_FAULT; +if (a & 01) /* busy, cc = 0001 */ + return CC_C; 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 */ +if (Test (c, WA, &t) < 0) /* wtst c, rls if err */ + Write (h, a, L_LONG, WA); 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 */ @@ -671,14 +703,18 @@ 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 (h & 07) /* h quad aligned? */ + RSVD_OPND_FAULT; if (opnd[1] < 0) { /* mem destination? */ - if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */ + if (h == opnd[2]) /* hdr = dst? */ + RSVD_OPND_FAULT; 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 */ +if (ar & 06) /* a quad aligned? */ + RSVD_OPND_FAULT; +if (ar & 01) /* busy, cc = 0011 */ + return CC_V | CC_C; a = ar + h; /* abs addr of a */ if (ar) { /* queue not empty? */ Write (h, ar | 1, L_LONG, WA); /* acquire interlock */ @@ -694,9 +730,11 @@ if (ar) { /* queue not empty? */ 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 (opnd[1] >= 0) /* store result */ + R[opnd[1]] = a; else Write (opnd[2], a, L_LONG, WA); -if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */ +if (ar == 0) /* empty, cc = 0110 */ + return CC_Z | CC_V; return (b == h)? CC_Z: 0; /* if b = h, q empty */ } @@ -705,14 +743,18 @@ 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 (h & 07) /* h quad aligned? */ + RSVD_OPND_FAULT; if (opnd[1] < 0) { /* mem destination? */ - if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */ + if (h == opnd[2]) /* hdr = dst? */ + RSVD_OPND_FAULT; 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 & 06) /* a quad aligned? */ + RSVD_OPND_FAULT; +if (ar & 01) /* busy, cc = 0011 */ + return CC_V | CC_C; if (ar) { /* queue not empty */ Write (h, ar | 1, L_LONG, WA); /* acquire interlock */ c = Read (h + 4, L_LONG, RA); /* c <- (h+4) */ @@ -739,9 +781,11 @@ if (ar) { /* queue not empty */ 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 (opnd[1] >= 0) /* store result */ + R[opnd[1]] = c; else Write (opnd[2], c, L_LONG, WA); -if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */ +if (ar == 0) /* empty, cc = 0110 */ + return CC_Z | CC_V; return 0; /* q can't be empty */ } @@ -786,7 +830,8 @@ 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; + if (R[4] > 0) + R[4] = R[4] & STR_LNMASK; } else { R[1] = opnd[1]; /* src addr */ @@ -831,7 +876,8 @@ 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 */ + if (mlnt[0] > R[2]) /* cant exceed total */ + mlnt[0] = R[2]; 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 */ @@ -848,7 +894,8 @@ switch (R[5] & MVC_M_STATE) { /* case on state */ 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 */ + if (mlnt[0] > R[2]) /* cant exceed total */ + mlnt[0] = R[2]; 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 */ @@ -866,17 +913,19 @@ switch (R[5] & MVC_M_STATE) { /* case on state */ case MVC_FILL: /* fill */ FILL: - if (R[4] <= 0) break; /* any fill? */ + if (R[4] <= 0) /* any fill? */ + break; 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 */ + if (mlnt[0] > R[4]) /* cant exceed total */ + mlnt[0] = R[4]; 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; + 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 */ @@ -942,11 +991,14 @@ else { } 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 */ + if (R[0] & STR_LNMASK) /* src1? read */ + s1 = Read (R[1], L_BYTE, RA); else s1 = fill; /* no, use fill */ - if (R[2]) s2 = Read (R[3], L_BYTE, RA); /* src2? read */ + if (R[2]) /* src2? read */ + s2 = Read (R[3], L_BYTE, RA); else s2 = fill; /* no, use fill */ - if (s1 != s2) break; /* src1 = src2? */ + if (s1 != s2) /* src1 = src2? */ + break; if (R[0] & STR_LNMASK) { /* if src1, decr */ R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); R[1] = R[1] + 1; @@ -990,7 +1042,8 @@ else { } 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? */ + if ((c == match) ^ skpc) /* match & locc? */ + break; R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); R[1] = R[1] + 1; /* incr src1adr */ } @@ -1031,7 +1084,8 @@ else { 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 */ + if (((t & mask) != 0) ^ spanc) /* test vs instr */ + break; R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); R[1] = R[1] + 1; } @@ -1065,9 +1119,12 @@ 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? */ +if (ei < 0) /* severe? on istk */ + newpc = newpc | 1; +if (newpc & 2) /* bad flags? */ + ABORT (STOP_ILLVEC); +if (oldpsl & PSL_IS) /* on int stk? */ + newpsl = PSL_IS; else { STK[oldcur] = SP; /* no, save cur stk */ if (newpc & 1) { /* to int stk? */ @@ -1083,9 +1140,9 @@ if (ei > 0) /* if int, new IPL */ PSL = cpu_psl_ipl_idle (newpsl | (ipl << PSL_V_IPL)); else PSL = cpu_psl_ipl_idle (newpsl | /* exc, old IPL/1F */ ((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (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); +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 */ @@ -1106,9 +1163,11 @@ int32 mode = opc & PSL_M_MODE; int32 cur = PSL_GETCUR (PSL); int32 tsp, newpc, acc, sta; -if (PSL & PSL_IS) ABORT (STOP_CHMFI); +if (PSL & PSL_IS) + ABORT (STOP_CHMFI); newpc = ReadLP ((SCBB + SCB_CHMK + (mode << 2)) & PAMASK); -if (cur < mode) mode = cur; /* only inward */ +if (cur < mode) /* only inward */ + mode = cur; STK[cur] = SP; /* save stack */ tsp = STK[mode]; /* get new stk */ acc = ACC_MASK (mode); /* set new mode */ @@ -1161,7 +1220,8 @@ int32 oldcur = PSL_GETCUR (PSL); int32 newipl, i; if ((newpsl & PSL_MBZ) || /* rule 8 */ - (newcur < oldcur)) RSVD_OPND_FAULT; /* rule 1 */ + (newcur < oldcur)) /* rule 1 */ + RSVD_OPND_FAULT; if (newcur) { /* to esu, skip 2,4,7 */ if ((newpsl & (PSL_IS | PSL_IPL)) || /* rules 3,5 */ (newcur > PSL_GETPRV (newpsl))) /* rule 6 */ @@ -1172,26 +1232,31 @@ else { /* to k, skip 3,5,6 */ 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 */ + if (newipl > PSL_GETIPL (PSL)) /* test rule 7 */ + RSVD_OPND_FAULT; } /* 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 */ + if (BadCmPSL (newpsl)) /* validate PSL */ + RSVD_OPND_FAULT; + for (i = 0; i < 7; i++) /* mask R0-R6, PC */ + R[i] = R[i] & WMASK; newpc = newpc & WMASK; } SP = SP + 8; /* pop stack */ -if (PSL & PSL_IS) IS = SP; /* save stack */ +if (PSL & PSL_IS) /* save stack */ + IS = SP; 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])); +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 = cpu_psl_ipl_idle ((PSL & PSL_TP) | (newpsl & ~CC_MASK)); /* set PSL */ -if (PSL & PSL_IS) SP = IS; /* set new stack */ +if (PSL & PSL_IS) /* set new stack */ + SP = IS; 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"); + if (DEBUG_PRI (cpu_dev, LOG_CPU_R)) + fprintf (sim_deb, ">>REI: AST delivered\n"); SISR = SISR | SISR_2; } } @@ -1205,7 +1270,8 @@ void op_ldpctx (int32 acc) { int32 newpc, newpsl, pcbpa, t; -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ +if (PSL & PSL_CUR) /* must be kernel */ + RSVD_INST_FAULT; pcbpa = PCBB & PAMASK; /* phys address */ KSP = ReadLP (pcbpa); /* restore stk ptrs */ ESP = ReadLP (pcbpa + 4); @@ -1249,10 +1315,11 @@ pme = (t >> 31) & 1; /* restore PME */ 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, */ +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) /* if istk, */ + IS = SP; PSL = PSL & ~PSL_IS; /* switch to kstk */ SP = KSP - 8; Write (SP, newpc, L_LONG, WA); /* push PC, PSL */ @@ -1266,13 +1333,15 @@ void op_svpctx (int32 acc) { int32 savpc, savpsl, pcbpa; -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ +if (PSL & PSL_CUR) /* must be kernel */ + RSVD_INST_FAULT; 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? */ +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) /* int stack? */ + SP = SP + 8; else { KSP = SP + 8; /* pop kernel stack */ SP = IS; /* switch to int stk */ @@ -1319,7 +1388,8 @@ int32 ba = opnd[2]; int32 prv = PSL_GETPRV (PSL); int32 acc, sta, sta1; -if (prv > mode) mode = prv; /* maximize mode */ +if (prv > mode) /* maximize mode */ + mode = prv; acc = ACC_MASK (mode) << (rw? TLB_V_WACC: 0); /* set acc mask */ Test (ba, acc, &sta); /* probe */ switch (sta) { /* case on status */ @@ -1366,13 +1436,16 @@ 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 */ +if (PSL & PSL_CUR) /* must be kernel */ + RSVD_INST_FAULT; +if (prn > 63) /* reg# > 63? fault */ + RSVD_OPND_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 */ + if (PSL & PSL_IS) /* on IS? store KSP */ + KSP = val; else SP = val; /* else store SP */ break; @@ -1381,7 +1454,8 @@ switch (prn) { /* case on reg # */ break; case MT_IS: /* IS */ - if (PSL & PSL_IS) SP = val; /* on IS? store SP */ + if (PSL & PSL_IS) /* on IS? store SP */ + SP = val; else IS = val; /* else store IS */ break; @@ -1442,12 +1516,14 @@ switch (prn) { /* case on reg # */ break; case MT_ASTLVL: /* ASTLVL */ - if (val > AST_MAX) RSVD_OPND_FAULT; /* > 4? fault */ + if (val > AST_MAX) /* > 4? fault */ + RSVD_OPND_FAULT; ASTLVL = val; break; case MT_SIRR: /* SIRR */ - if ((val > 0xF) || (val == 0)) RSVD_OPND_FAULT; + if ((val > 0xF) || (val == 0)) + RSVD_OPND_FAULT; SISR = SISR | (1 << val); /* set bit in SISR */ break; @@ -1466,7 +1542,8 @@ switch (prn) { /* case on reg # */ break; case MT_TBCHK: /* TBCHK */ - if (chk_tb_ent (val)) cc = cc | CC_V; + if (chk_tb_ent (val)) + cc = cc | CC_V; break; case MT_PME: /* PME */ @@ -1486,8 +1563,10 @@ 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 */ +if (PSL & PSL_CUR) /* must be kernel */ + RSVD_INST_FAULT; +if (prn > 63) /* reg# > 63? fault */ + RSVD_OPND_FAULT; switch (prn) { /* case on reg# */ case MT_KSP: /* KSP */ diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h index 3b0b16f6..a6087fef 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-2006, Robert M Supnik + Copyright (c) 1998-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/VAX/vax_fpa.c b/VAX/vax_fpa.c index 5dea5ad2..9a88bb57 100644 --- a/VAX/vax_fpa.c +++ b/VAX/vax_fpa.c @@ -124,7 +124,8 @@ 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? */ + if (sc > 63) /* sc > 63? */ + r = (opnd[2] & LSIGN)? -1: 0; else r = src >> sc; } else { @@ -168,16 +169,21 @@ int32 quo, rem; *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? */ +if (opnd[2] & LSIGN) /* |dividend| */ + ldvd = -ldvd; +if (((ldvd >> 32) & LMASK) >= ldvr) /* divide work? */ + return opnd[1]; 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 (quo && ((quo & LSIGN) == 0)) /* right sign? */ + return opnd[1]; } -else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) rem = -rem; /* sign of rem */ +else if (quo & LSIGN) + return opnd[1]; +if (opnd[2] & LSIGN) /* sign of rem */ + rem = -rem; *flg = 0; /* no overflow */ *rh = rem & LMASK; /* set rem */ return (quo & LMASK); /* return quo */ @@ -190,17 +196,21 @@ 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; + if (h1 & FPSIGN) + RSVD_OPND_FAULT; h1 = l1 = 0; } if ((h2 & FD_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; + if (h2 & FPSIGN) + RSVD_OPND_FAULT; h2 = l2 = 0; } -if ((h1 ^ h2) & FPSIGN) return ((h1 & FPSIGN)? CC_N: 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; +if (n1 == n2) + return CC_Z; return (((n1 < n2) ^ ((h1 & FPSIGN) != 0))? CC_N: 0); } @@ -209,17 +219,21 @@ 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; + if (h1 & FPSIGN) + RSVD_OPND_FAULT; h1 = l1 = 0; } if ((h2 & G_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; + if (h2 & FPSIGN) + RSVD_OPND_FAULT; h2 = l2 = 0; } -if ((h1 ^ h2) & FPSIGN) return ((h1 & FPSIGN)? CC_N: 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; +if (n1 == n2) + return CC_Z; return (((n1 < n2) ^ ((h1 & FPSIGN) != 0))? CC_N: 0); } @@ -230,7 +244,8 @@ int32 op_cvtifdg (int32 val, int32 *rh, int32 opc) UFP a; if (val == 0) { - if (rh) *rh = 0; + if (rh) + *rh = 0; return 0; } if (val < 0) { @@ -241,7 +256,8 @@ else a.sign = 0; a.exp = 32 + ((opc & 0x100)? G_BIAS: FD_BIAS); a.frac = ((t_uint64) val) << (UF_V_NM - 31); norm (&a); -if (opc & 0x100) return rpackg (&a, rh); +if (opc & 0x100) + return rpackg (&a, rh); return rpackfd (&a, rh); } @@ -260,20 +276,25 @@ if (opc & 0x100) { ubexp = a.exp - G_BIAS; } else { - if (opc & 0x20) unpackd (opnd[0], opnd[1], &a); + 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 ((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 */ + if ((opc & 03) == 03) /* if CVTR, round */ + a.frac = a.frac + 1; a.frac = a.frac >> 1; /* now justified */ - if (a.frac > (maxv[lnt] + (a.sign? 1: 0))) *flg = CC_V; + 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; + 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)); @@ -335,7 +356,8 @@ if (a->frac == 0) { /* s1 = 0? */ *a = *b; return; } -if (b->frac == 0) return; /* s2 = 0? */ +if (b->frac == 0) /* s2 = 0? */ + return; if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ ((a->exp == b->exp) && (a->frac < b->frac))) { t = *a; @@ -345,7 +367,8 @@ if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ 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 */ + if (ediff > 63) /* retain sticky */ + b->frac = M64; else b->frac = ((-((t_int64) b->frac) >> ediff) | /* denormalize */ (M64 << (64 - ediff))); /* preserve sign */ a->frac = a->frac + b->frac; /* add frac */ @@ -354,8 +377,10 @@ if (a->sign ^ b->sign) { /* eff sub? */ norm (a); /* normalize */ } else { - if (ediff > 63) b->frac = 0; /* add */ - else if (ediff) b->frac = b->frac >> ediff; /* denormalize */ + if (ediff > 63) /* add */ + b->frac = 0; + else if (ediff) /* denormalize */ + b->frac = b->frac >> ediff; 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 */ @@ -389,9 +414,11 @@ if (qd) { /* 64b needed? */ 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 */ + if (rmid1 < rlo) /* carry? incr hi */ + rhi = rhi + 1; rmid2 = rmid1 + (rmid2 << 32); /* add mid2 to lo */ - if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ + if (rmid2 < rmid1) /* carry? incr hi */ + rhi = rhi + 1; } a->frac = rhi & ~mask; norm (a); /* normalize */ @@ -410,7 +437,8 @@ return; void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg) { -if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ +if (a->exp <= bias) /* 0 or <1? int = 0 */ + *intgr = *flg = 0; else if (a->exp <= (bias + 64)) { /* in range [1,64]? */ *intgr = (int32) (a->frac >> (64 - (a->exp - bias))); if ((a->exp > (bias + 32)) || /* test ovflo */ @@ -418,8 +446,10 @@ else if (a->exp <= (bias + 64)) { /* in range [1,64]? */ (((uint32) *intgr) > (a->sign? 0x80000000: 0x7FFFFFFF)))) *flg = CC_V; else *flg = 0; - if (a->sign) *intgr = -*intgr; /* -? comp int */ - if (a->exp == (bias + 64)) a->frac = 0; /* special case 64 */ + if (a->sign) /* -? comp int */ + *intgr = -*intgr; + if (a->exp == (bias + 64)) /* special case 64 */ + a->frac = 0; else a->frac = a->frac << (a->exp - bias); a->exp = bias; } @@ -443,8 +473,10 @@ 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? */ +if (a->exp == 0) /* divr = 0? */ + FLT_DZRO_FAULT; +if (b->exp == 0) /* divd = 0? */ + return; 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 */ @@ -469,7 +501,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac = 0; /* else 0 */ return; } @@ -483,7 +516,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac = 0; /* else 0 */ return; } @@ -497,7 +531,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac = 0; /* else 0 */ return; } @@ -521,7 +556,8 @@ if (r->frac == 0) { /* if fraction = 0 */ } while ((r->frac & UF_NM) == 0) { /* normalized? */ for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac & normmask[i]) break; + if (r->frac & normmask[i]) + break; } r->frac = r->frac << normtab[i]; /* shift frac */ r->exp = r->exp - normtab[i]; /* decr exp */ @@ -531,37 +567,45 @@ return; int32 rpackfd (UFP *r, int32 *rh) { -if (rh) *rh = 0; /* assume 0 */ -if (r->frac == 0) return 0; /* result 0? */ +if (rh) /* assume 0 */ + *rh = 0; +if (r->frac == 0) /* result 0? */ + return 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 > (int32) FD_M_EXP) /* ovflo? fault */ + FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } -if (rh) *rh = UF_GETFDLO (r->frac); /* get low */ +if (rh) /* get low */ + *rh = UF_GETFDLO (r->frac); 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? */ +if (r->frac == 0) /* result 0? */ + return 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 > (int32) G_M_EXP) /* ovflo? fault */ + FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } -if (rh) *rh = UF_GETGLO (r->frac); /* get low */ +*rh = UF_GETGLO (r->frac); /* get low */ return r->sign | (r->exp << G_V_EXP) | UF_GETGHI (r->frac); } @@ -644,10 +688,13 @@ int32 op_emul (int32 mpy, int32 mpc, int32 *rh) UDP r; int32 sign = mpy ^ mpc; /* sign of result */ -if (mpy & LSIGN) mpy = -mpy; /* abs value */ -if (mpc & LSIGN) mpc = -mpc; +if (mpy & LSIGN) /* abs value */ + mpy = -mpy; +if (mpc & LSIGN) + mpc = -mpc; dp_imul (mpy & LMASK, mpc & LMASK, &r); /* 32b * 32b -> 64b */ -if (sign & LSIGN) dp_neg (&r); /* negative result? */ +if (sign & LSIGN) /* negative result? */ + dp_neg (&r); *rh = r.hi; return r.lo; } @@ -668,9 +715,12 @@ dvd.lo = opnd[1]; /* get dividend */ dvd.hi = opnd[2]; *flg = CC_V; /* assume error */ *rh = 0; -if (dvd.hi & LSIGN) dp_neg (&dvd); /* |dividend| */ -if (dvr & LSIGN) dvr = NEG (dvr); /* |divisor| */ -if (dvd.hi >= dvr) return opnd[1]; /* divide work? */ +if (dvd.hi & LSIGN) /* |dividend| */ + dp_neg (&dvd); +if (dvr & LSIGN) /* |divisor| */ + dvr = NEG (dvr); +if (dvd.hi >= dvr) /* divide work? */ + return opnd[1]; for (i = quo = 0; i < 32; i++) { /* 32 iterations */ quo = quo << 1; /* shift quotient */ dp_lsh (&dvd, 1); /* shift dividend */ @@ -681,10 +731,13 @@ for (i = quo = 0; i < 32; i++) { /* 32 iterations */ } if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ quo = NEG (quo); /* negate */ - if (quo && ((quo & LSIGN) == 0)) return opnd[1]; /* right sign? */ + if (quo && ((quo & LSIGN) == 0)) /* right sign? */ + return opnd[1]; } -else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) *rh = NEG (dvd.hi); /* sign of rem */ +else if (quo & LSIGN) + return opnd[1]; +if (opnd[2] & LSIGN) /* sign of rem */ + *rh = NEG (dvd.hi); else *rh = dvd.hi; *flg = 0; /* no overflow */ return quo; /* return quo */ @@ -699,11 +752,15 @@ int32 r; unpackd (h1, l1, &a); unpackd (h2, l2, &b); -if (a.sign != b.sign) return (a.sign? CC_N: 0); +if (a.sign != b.sign) + return (a.sign? CC_N: 0); r = a.exp - b.exp; -if (r == 0) r = dp_cmp (&a.frac, &b.frac); -if (r < 0) return (a.sign? 0: CC_N); -if (r > 0) return (a.sign? CC_N: 0); +if (r == 0) + r = dp_cmp (&a.frac, &b.frac); +if (r < 0) + return (a.sign? 0: CC_N); +if (r > 0) + return (a.sign? CC_N: 0); return CC_Z; } @@ -714,11 +771,15 @@ int32 r; unpackg (h1, l1, &a); unpackg (h2, l2, &b); -if (a.sign != b.sign) return (a.sign? CC_N: 0); +if (a.sign != b.sign) + return (a.sign? CC_N: 0); r = a.exp - b.exp; -if (r == 0) r = dp_cmp (&a.frac, &b.frac); -if (r < 0) return (a.sign? 0: CC_N); -if (r > 0) return (a.sign? CC_N: 0); +if (r == 0) + r = dp_cmp (&a.frac, &b.frac); +if (r < 0) + return (a.sign? 0: CC_N); +if (r > 0) + return (a.sign? CC_N: 0); return CC_Z; } @@ -741,7 +802,8 @@ 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 */ +if (opc & 0x100) /* pack and return */ + return rpackg (&a, rh); return rpackfd (&a, rh); } @@ -760,21 +822,26 @@ if (opc & 0x100) { /* G? */ ubexp = a.exp - G_BIAS; /* unbiased exp */ } else { - if (opc & 0x20) unpackd (opnd[0], opnd[1], &a); /* F or D */ + if (opc & 0x20) /* F or D */ + unpackd (opnd[0], opnd[1], &a); 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 ((a.exp == 0) || (ubexp < 0)) /* true zero or frac? */ + return 0; 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 */ + if (lnt == 03) /* if CVTR, round */ + dp_inc (&a.frac); dp_rsh (&a.frac, 1); /* now justified */ if ((a.frac.hi != 0) || - (a.frac.lo > (maxv[lnt] + (a.sign? 1: 0)))) *flg = CC_V; + (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? */ + if (ubexp > (UF_V_NM + 32)) /* in ext range? */ + return 0; 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 */ @@ -838,7 +905,8 @@ if ((a->frac.hi == 0) && (a->frac.lo == 0)) { /* s1 = 0? */ *a = *b; return; } -if ((b->frac.hi == 0) && (b->frac.lo == 0)) return; /* s2 = 0? */ +if ((b->frac.hi == 0) && (b->frac.lo == 0)) /* s2 = 0? */ + return; if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ ((a->exp == b->exp) && (dp_cmp (&a->frac, &b->frac) < 0))) { t = *a; @@ -856,7 +924,8 @@ if (a->sign ^ b->sign) { /* eff sub? */ norm (a); /* normalize */ } else { - if (ediff) dp_rsh (&b->frac, ediff); /* add, denormalize */ + if (ediff) /* add, denormalize */ + dp_rsh (&b->frac, ediff); 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 */ @@ -892,9 +961,11 @@ if (qd) { /* 64b needed? */ 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 */ + if (rlo.hi < rmid1.lo) /* carry? incr high res */ + dp_inc (&rhi); rlo.hi = (rlo.hi + rmid2.lo) & LMASK; /* add mid2 to low res */ - if (rlo.hi < rmid2.lo) dp_inc (&rhi); /* carry? incr high res */ + if (rlo.hi < rmid2.lo) /* carry? incr high res */ + dp_inc (&rhi); } a->frac.hi = rhi.hi & ~mhi; /* mask fraction */ a->frac.lo = rhi.lo & ~mlo; @@ -916,7 +987,8 @@ 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 */ +if (a->exp <= bias) /* 0 or <1? int = 0 */ + *intgr = *flg = 0; else if (a->exp <= (bias + 64)) { /* in range [1,64]? */ ifr = a->frac; dp_rsh (&ifr, 64 - (a->exp - bias)); /* separate integer */ @@ -926,7 +998,8 @@ else if (a->exp <= (bias + 64)) { /* in range [1,64]? */ *flg = CC_V; else *flg = 0; *intgr = ifr.lo; - if (a->sign) *intgr = -*intgr; /* -? comp int */ + if (a->sign) /* -? comp int */ + *intgr = -*intgr; dp_lsh (&a->frac, a->exp - bias); /* excise integer */ a->exp = bias; } @@ -950,8 +1023,10 @@ 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? */ +if (a->exp == 0) /* divr = 0? */ + FLT_DZRO_FAULT; +if (b->exp == 0) /* divd = 0? */ + return; 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 */ @@ -974,17 +1049,22 @@ return; int32 dp_cmp (UDP *a, UDP *b) { -if (a->hi < b->hi) return -1; /* compare hi */ -if (a->hi > b->hi) return +1; -if (a->lo < b->lo) return -1; /* hi =, compare lo */ -if (a->lo > b->lo) return +1; +if (a->hi < b->hi) /* compare hi */ + return -1; +if (a->hi > b->hi) + return +1; +if (a->lo < b->lo) /* hi =, compare lo */ + return -1; +if (a->lo > b->lo) + return +1; return 0; /* hi, lo equal */ } void dp_add (UDP *a, UDP *b) { a->lo = (a->lo + b->lo) & LMASK; /* add lo */ -if (a->lo < b->lo) a->hi = a->hi + 1; /* carry? */ +if (a->lo < b->lo) /* carry? */ + a->hi = a->hi + 1; a->hi = (a->hi + b->hi) & LMASK; /* add hi */ return; } @@ -992,13 +1072,15 @@ 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 */ +if (a->lo == 0) /* carry? inc hi */ + a->hi = (a->hi + 1) & LMASK; return; } void dp_sub (UDP *a, UDP *b) { -if (a->lo < b->lo) a->hi = a->hi - 1; /* borrow? decr hi */ +if (a->lo < b->lo) /* borrow? decr hi */ + a->hi = a->hi - 1; a->lo = (a->lo - b->lo) & LMASK; /* sub lo */ a->hi = (a->hi - b->hi) & LMASK; /* sub hi */ return; @@ -1006,7 +1088,8 @@ return; void dp_lsh (UDP *r, uint32 sc) { -if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ +if (sc > 63) /* > 63? result 0 */ + r->hi = r->lo = 0; else if (sc > 31) { /* [32,63]? */ r->hi = (r->lo << (sc - 32)) & LMASK; r->lo = 0; @@ -1020,7 +1103,8 @@ return; void dp_rsh (UDP *r, uint32 sc) { -if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ +if (sc > 63) /* > 63? result 0 */ + r->hi = r->lo = 0; else if (sc > 31) { /* [32,63]? */ r->lo = (r->hi >> (sc - 32)) & LMASK; r->hi = 0; @@ -1036,7 +1120,8 @@ 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 */ + if (sc > 63) /* > 63? result -1 */ + r->hi = r->lo = LMASK; else { UDP ones = { LMASK, LMASK }; dp_lsh (&ones, 64 - sc); /* shift ones */ @@ -1065,9 +1150,11 @@ 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 */ +if (rmid1 < rlo) /* carry? incr hi */ + rhi = rhi + 1; rmid2 = (rmid1 + (rmid2 << 16)) & LMASK; /* add mid2 to to */ -if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ +if (rmid2 < rmid1) /* carry? incr hi */ + rhi = rhi + 1; r->hi = rhi & LMASK; /* mask result */ r->lo = rmid2; return; @@ -1087,7 +1174,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac.hi = r->frac.lo = 0; /* else 0 */ return; } @@ -1102,7 +1190,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac.hi = r->frac.lo = 0; /* else 0 */ return; } @@ -1117,7 +1206,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac.hi = r->frac.lo = 0; /* else 0 */ return; } @@ -1141,7 +1231,8 @@ if ((r->frac.hi == 0) && (r->frac.lo == 0)) { /* if fraction = 0 */ } 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; + if (r->frac.hi & normmask[i]) + break; } dp_lsh (&r->frac, normtab[i]); /* shift frac */ r->exp = r->exp - normtab[i]; /* decr exp */ @@ -1154,21 +1245,27 @@ 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) /* assume 0 */ + *rh = 0; +if ((r->frac.hi == 0) && (r->frac.lo == 0)) /* result 0? */ + return 0; +if (rh) /* round */ + dp_add (&r->frac, &d_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 > (int32) FD_M_EXP) /* ovflo? fault */ + FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } dp_rsh (&r->frac, FD_GUARD); /* remove guard */ -if (rh) *rh = WORDSWAP (r->frac.lo); /* get low */ +if (rh) /* get low */ + *rh = WORDSWAP (r->frac.lo); return r->sign | (r->exp << FD_V_EXP) | (WORDSWAP (r->frac.hi) & ~(FD_HB | FPSIGN | FD_EXP)); } @@ -1178,15 +1275,18 @@ 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? */ +if ((r->frac.hi == 0) && (r->frac.lo == 0)) /* result 0? */ + return 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 > (int32) G_M_EXP) /* ovflo? fault */ +FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } dp_rsh (&r->frac, G_GUARD); /* remove guard */ @@ -1207,29 +1307,37 @@ return r->sign | (r->exp << G_V_EXP) | int32 op_movfd (int32 val) { -if (val & FD_EXP) return val; -if (val & FPSIGN) RSVD_OPND_FAULT; +if (val & FD_EXP) + return val; +if (val & FPSIGN) + RSVD_OPND_FAULT; return 0; } int32 op_mnegfd (int32 val) { -if (val & FD_EXP) return (val ^ FPSIGN); -if (val & FPSIGN) RSVD_OPND_FAULT; +if (val & FD_EXP) + return (val ^ FPSIGN); +if (val & FPSIGN) + RSVD_OPND_FAULT; return 0; } int32 op_movg (int32 val) { -if (val & G_EXP) return val; -if (val & FPSIGN) RSVD_OPND_FAULT; +if (val & G_EXP) + return val; +if (val & FPSIGN) + RSVD_OPND_FAULT; return 0; } int32 op_mnegg (int32 val) { -if (val & G_EXP) return (val ^ FPSIGN); -if (val & FPSIGN) RSVD_OPND_FAULT; +if (val & G_EXP) + return (val ^ FPSIGN); +if (val & FPSIGN) + RSVD_OPND_FAULT; return 0; } @@ -1269,7 +1377,8 @@ UFP a, b; unpackf (opnd[0], &a); /* F format */ unpackf (opnd[1], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ +if (sub) /* sub? -s1 */ + a.sign = a.sign ^ FPSIGN; vax_fadd (&a, &b); /* add fractions */ return rpackfd (&a, NULL); } @@ -1280,7 +1389,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 */ +if (sub) /* sub? -s1 */ + a.sign = a.sign ^ FPSIGN; vax_fadd (&a, &b); /* add fractions */ return rpackfd (&a, rh); } @@ -1291,7 +1401,8 @@ UFP a, b; unpackg (opnd[0], opnd[1], &a); unpackg (opnd[2], opnd[3], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ +if (sub) /* sub? -s1 */ + a.sign = a.sign ^ FPSIGN; vax_fadd (&a, &b); /* add fractions */ return rpackg (&a, rh); /* round and pack */ } @@ -1375,7 +1486,8 @@ int32 deg = opnd[1]; int32 ptr = opnd[2]; int32 i, wd, res; -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ +if (deg > 31) /* degree > 31? fault */ + RSVD_OPND_FAULT; unpackf (opnd[0], &a); /* unpack arg */ wd = Read (ptr, L_LONG, RD); /* get C0 */ ptr = ptr + 4; @@ -1403,7 +1515,8 @@ int32 deg = opnd[2]; int32 ptr = opnd[3]; int32 i, wd, wd1, res, resh; -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ +if (deg > 31) /* degree > 31? fault */ + RSVD_OPND_FAULT; unpackd (opnd[0], opnd[1], &a); /* unpack arg */ wd = Read (ptr, L_LONG, RD); /* get C0 */ wd1 = Read (ptr + 4, L_LONG, RD); @@ -1436,7 +1549,8 @@ int32 deg = opnd[2]; int32 ptr = opnd[3]; int32 i, wd, wd1, res, resh; -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ +if (deg > 31) /* degree > 31? fault */ + RSVD_OPND_FAULT; unpackg (opnd[0], opnd[1], &a); /* unpack arg */ wd = Read (ptr, L_LONG, RD); /* get C0 */ wd1 = Read (ptr + 4, L_LONG, RD); diff --git a/VAX/vax_io.c b/VAX/vax_io.c index c8ebf2d4..a52d93ea 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -183,9 +183,8 @@ DEVICE qba_dev = { /* IO page dispatches */ -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]; +t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); +t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); /* Interrupt request to interrupt action map */ @@ -243,7 +242,8 @@ int32 ReadIO (uint32 pa, int32 lnt) int32 iod; iod = ReadQb (pa); /* wd from Qbus */ -if (lnt < L_LONG) iod = iod << ((pa & 2)? 16: 0); /* bw? position */ +if (lnt < L_LONG) /* bw? position */ + iod = iod << ((pa & 2)? 16: 0); else iod = (ReadQb (pa + 2) << 16) | iod; /* lw, get 2nd wd */ SET_IRQL; return iod; @@ -261,8 +261,10 @@ return iod; void WriteIO (uint32 pa, int32 val, int32 lnt) { -if (lnt == L_BYTE) WriteQb (pa, val, WRITEB); -else if (lnt == L_WORD) WriteQb (pa, val, WRITE); +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); @@ -285,17 +287,25 @@ static const int32 sw_int_mask[IPL_SMAX] = { 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 */ +if (hlt_pin) /* hlt pin int */ + return IPL_HLTPIN; +if ((ipl < IPL_MEMERR) && mem_err) /* mem err int */ + return IPL_MEMERR; +if ((ipl < IPL_CRDERR) && crd_err) /* crd err int */ + return IPL_CRDERR; 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 (i <= ipl) /* at ipl? no int */ + return 0; + if (int_req[i - IPL_HMIN]) /* req != 0? int */ + return i; } -if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */ -if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */ +if (ipl >= IPL_SMAX) /* ipl >= sw max? */ + return 0; +if ((t = SISR & sw_int_mask[ipl]) == 0) /* eligible req */ + return 0; for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */ - if ((t >> i) & 1) return i; /* req != 0? int */ + if ((t >> i) & 1) /* req != 0? int */ + return i; } return 0; } @@ -321,7 +331,8 @@ if (lvl > IPL_HMAX) { /* error req lvl? */ 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](); + if (int_ack[l][i]) + return int_ack[l][i](); return int_vec[l][i]; } } @@ -383,7 +394,8 @@ switch (rg) { case 1: /* DSER */ cq_dser = (cq_dser & ~val) & CQDSER_MASK; - if (val & CQDSER_SME) cq_ipc = cq_ipc & ~CQIPC_QME; + if (val & CQDSER_SME) + cq_ipc = cq_ipc & ~CQIPC_QME; break; case 2: case 3: @@ -445,7 +457,8 @@ int32 cqmap_rd (int32 pa) { int32 ma = (pa & CQMAPAMASK) + cq_mbr; /* mem addr */ -if (ADDR_IS_MEM (ma)) return M[ma >> 2]; +if (ADDR_IS_MEM (ma)) + return M[ma >> 2]; cq_serr (ma); /* set err */ MACH_CHECK (MCHK_READ); /* mcheck */ return 0; @@ -481,7 +494,8 @@ int32 cqmem_rd (int32 pa) int32 qa = pa & CQMAMASK; /* Qbus addr */ uint32 ma; -if (qba_map_addr (qa, &ma)) return M[ma >> 2]; /* map addr */ +if (qba_map_addr (qa, &ma)) /* map addr */ + return M[ma >> 2]; MACH_CHECK (MCHK_READ); /* err? mcheck */ return 0; } @@ -515,7 +529,8 @@ 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 TRUE; /* legit addr */ + if (ADDR_IS_MEM (*ma)) /* legit addr */ + return TRUE; cq_serr (*ma); /* slave nxm */ return FALSE; } @@ -547,7 +562,8 @@ return FALSE; void cq_merr (int32 pa) { -if (cq_dser & CQDSER_ERR) cq_dser = cq_dser | CQDSER_LST; +if (cq_dser & CQDSER_ERR) + cq_dser = cq_dser | CQDSER_LST; cq_dser = cq_dser | CQDSER_MNX; /* master nxm */ cq_mear = (pa >> VA_V_VPN) & CQMEAR_MASK; /* page addr */ return; @@ -557,7 +573,8 @@ return; void cq_serr (int32 pa) { -if (cq_dser & CQDSER_ERR) cq_dser = cq_dser | CQDSER_LST; +if (cq_dser & CQDSER_ERR) + cq_dser = cq_dser | CQDSER_LST; cq_dser = cq_dser | CQDSER_SNX; /* slave nxm */ cq_sear = (pa >> VA_V_VPN) & CQSEAR_MASK; return; @@ -586,10 +603,12 @@ t_stat qba_reset (DEVICE *dptr) { int32 i; -if (sim_switches & SWMASK ('P')) qba_powerup (); +if (sim_switches & SWMASK ('P')) + qba_powerup (); cq_scr = (cq_scr & CQSCR_BHL) | CQSCR_POK; cq_dser = cq_mear = cq_sear = cq_ipc = 0; -for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; +for (i = 0; i < IPL_HLVL; i++) + int_req[i] = 0; return SCPE_OK; } @@ -735,7 +754,8 @@ t_stat qba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) { uint32 qa = (uint32) exta, pa; -if ((vptr == NULL) || (qa >= CQMSIZE)) return SCPE_ARG; +if ((vptr == NULL) || (qa >= CQMSIZE)) + return SCPE_ARG; if (qba_map_addr_c (qa, &pa) && ADDR_IS_MEM (pa)) { *vptr = (uint32) ReadW (pa); return SCPE_OK; @@ -749,7 +769,8 @@ t_stat qba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) { uint32 qa = (uint32) exta, pa; -if (qa >= CQMSIZE) return SCPE_ARG; +if (qa >= CQMSIZE) + return SCPE_ARG; if (qba_map_addr_c (qa, &pa) && ADDR_IS_MEM (pa)) { WriteW (pa, (int32) val); return SCPE_OK; @@ -757,248 +778,26 @@ if (qba_map_addr_c (qa, &pa) && ADDR_IS_MEM (pa)) { return SCPE_NXM; } -/* 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 (NULL, 0); -} - -/* Show autoconfiguration status */ - -t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "autoconfiguration "); -fprintf (st, autcon_enb? "enabled": "disabled"); -return SCPE_OK; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newba = (uint32) get_uint (cptr, 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 */ -return SCPE_OK; -} - -/* Show device address */ - -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08X", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (NULL, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newvec = (uint32) get_uint (cptr, 16, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -autcon_enb = 0; /* autoconfig off */ -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { - fprintf (st, "vector=%X", vec); - if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1))); - } -return SCPE_OK; -} - -/* 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 */ - } -return SCPE_OK; -} - - -/* Build interrupt tables */ - -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 (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; - } -return SCPE_OK; -} - /* Build dib_tab from device list */ t_stat build_dib_tab (void) { -int32 i, j; +int32 i; 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; - } +init_ubus_tab (); /* init bus tables */ 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 */ + if (r = build_ubus_tab (dptr, dibp)) /* add to bus tab */ return r; } /* end if enabled */ } /* end for */ return SCPE_OK; } -/* Show IO space */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -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 */ -return SCPE_OK; -} - /* Show QBA virtual address */ t_stat qba_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc) @@ -1019,144 +818,3 @@ if (cptr) { fprintf (of, "Invalid argument\n"); return SCPE_OK; } - -/* Autoconfiguration - - 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). - - A minus number of vectors indicates a field that should be calculated - but not placed in the DIB (RQ, TQ dynamic vectors) */ - -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -typedef struct { - char *dnam[AUTO_MAXC]; - int32 numc; - int32 numv; - uint32 amod; - uint32 vmod; - uint32 fixa[AUTO_MAXC]; - uint32 fixv[AUTO_MAXC]; - } AUTO_CON; - -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 (char *name, int32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -AUTO_CON *autp; -DEVICE *dptr; -DIB *dibp; -uint32 j, k, vmask, amask; - -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 be4ff63c..1733d311 100644 --- a/VAX/vax_mmu.c +++ b/VAX/vax_mmu.c @@ -23,6 +23,7 @@ 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-Jul-08 RMS Removed inlining support 28-May-08 RMS Inlined physical memory routines 29-Apr-07 RMS Added address masking for system page table reads 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) @@ -178,8 +179,10 @@ if (mapen) { /* mapping on? */ } 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? */ + if (lnt >= L_LONG) /* long, quad? */ + return ReadL (pa); + if (lnt == L_WORD) /* word? */ + return ReadW (pa); return ReadB (pa); /* byte */ } if (mapen && ((off + lnt) > VA_PAGSIZE)) { /* cross page? */ @@ -199,7 +202,8 @@ if (lnt >= L_LONG) { /* lw unaligned? */ wh = ReadL (pa1); /* extract */ return ((((wl >> sc) & align[bo]) | (wh << (32 - sc))) & LMASK); } -else if (bo == 1) return ((ReadL (pa) >> 8) & WMASK); +else if (bo == 1) + return ((ReadL (pa) >> 8) & WMASK); else { wl = ReadL (pa); /* word cross lw */ wh = ReadL (pa1); /* read, extract */ @@ -237,8 +241,10 @@ if (mapen) { } 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? */ + if (lnt >= L_LONG) /* long, quad? */ + WriteL (pa, val); + else if (lnt == L_WORD) /* word? */ + WriteW (pa, val); else WriteB (pa, val); /* byte */ return; } @@ -292,7 +298,8 @@ if (mapen) { /* mapping on? */ 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; + if (*status == PR_OK) + return (xpte.pte & TLB_PFN) | off; else return -1; } return va & PAMASK; /* ret phys addr */ @@ -310,10 +317,12 @@ SIM_INLINE int32 ReadB (uint32 pa) { int32 dat; -if (ADDR_IS_MEM (pa)) dat = M[pa >> 2]; +if (ADDR_IS_MEM (pa)) + dat = M[pa >> 2]; else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) dat = ReadIO (pa, L_BYTE); + if (ADDR_IS_IO (pa)) + dat = ReadIO (pa, L_BYTE); else dat = ReadReg (pa, L_BYTE); } return ((dat >> ((pa & 3) << 3)) & BMASK); @@ -323,10 +332,12 @@ SIM_INLINE int32 ReadW (uint32 pa) { int32 dat; -if (ADDR_IS_MEM (pa)) dat = M[pa >> 2]; +if (ADDR_IS_MEM (pa)) + dat = M[pa >> 2]; else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) dat = ReadIO (pa, L_WORD); + if (ADDR_IS_IO (pa)) + dat = ReadIO (pa, L_WORD); else dat = ReadReg (pa, L_WORD); } return ((dat >> ((pa & 2)? 16: 0)) & WMASK); @@ -334,7 +345,8 @@ return ((dat >> ((pa & 2)? 16: 0)) & WMASK); SIM_INLINE int32 ReadL (uint32 pa) { -if (ADDR_IS_MEM (pa)) return M[pa >> 2]; +if (ADDR_IS_MEM (pa)) + return M[pa >> 2]; mchk_ref = REF_V; if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); return ReadReg (pa, L_LONG); @@ -342,10 +354,12 @@ return ReadReg (pa, L_LONG); SIM_INLINE int32 ReadLP (uint32 pa) { -if (ADDR_IS_MEM (pa)) return M[pa >> 2]; +if (ADDR_IS_MEM (pa)) + return M[pa >> 2]; mchk_va = pa; mchk_ref = REF_P; -if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); +if (ADDR_IS_IO (pa)) + return ReadIO (pa, L_LONG); return ReadReg (pa, L_LONG); } @@ -368,7 +382,8 @@ if (ADDR_IS_MEM (pa)) { } else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_BYTE); + if (ADDR_IS_IO (pa)) + WriteIO (pa, val, L_BYTE); else WriteReg (pa, val, L_BYTE); } return; @@ -383,7 +398,8 @@ if (ADDR_IS_MEM (pa)) { } else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_WORD); + if (ADDR_IS_IO (pa)) + WriteIO (pa, val, L_WORD); else WriteReg (pa, val, L_WORD); } return; @@ -391,10 +407,12 @@ return; SIM_INLINE void WriteL (uint32 pa, int32 val) { -if (ADDR_IS_MEM (pa)) M[pa >> 2] = 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); + if (ADDR_IS_IO (pa)) + WriteIO (pa, val, L_LONG); else WriteReg (pa, val, L_LONG); } return; @@ -402,11 +420,13 @@ return; void WriteLP (uint32 pa, int32 val) { -if (ADDR_IS_MEM (pa)) M[pa >> 2] = 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); + if (ADDR_IS_IO (pa)) + WriteIO (pa, val, L_LONG); else WriteReg (pa, val, L_LONG); } return; @@ -424,7 +444,10 @@ return; */ #define MM_ERR(param) { \ - if (stat) { *stat = param; return zero_pte; } \ + if (stat) { \ + *stat = param; \ + return zero_pte; \ + } \ p1 = MM_PARAM (acc & TLB_WACC, param); \ p2 = va; \ ABORT ((param & PR_TNV)? ABORT_TNV: ABORT_ACV); } @@ -442,11 +465,13 @@ if (va & VA_S0) { /* system space? */ } else { if (va & VA_P1) { /* P1? */ - if (ptidx < d_p1lr) MM_ERR (PR_LNV); + if (ptidx < d_p1lr) + MM_ERR (PR_LNV); ptead = d_p1br + ptidx; } else { /* P0 */ - if (ptidx >= d_p0lr) MM_ERR (PR_LNV); + if (ptidx >= d_p0lr) + MM_ERR (PR_LNV); ptead = d_p0br + ptidx; } if ((ptead & VA_S0) == 0) @@ -459,9 +484,11 @@ else { MM_ERR (PR_PLNV); pte = ReadLP ((d_sbr + ptidx) & PAMASK); /* get system pte */ #if defined (VAX_780) - if ((pte & PTE_ACC) == 0) MM_ERR (PR_PACV); /* spte ACV? */ + if ((pte & PTE_ACC) == 0) /* spte ACV? */ + MM_ERR (PR_PACV); #endif - if ((pte & PTE_V) == 0) MM_ERR (PR_PTNV); /* spte TNV? */ + if ((pte & PTE_V) == 0) /* spte TNV? */ + MM_ERR (PR_PTNV); stlb[tbi].tag = vpn; /* set stlb tag */ stlb[tbi].pte = cvtacc[PTE_GETACC (pte)] | ((pte << VA_N_OFF) & TLB_PFN); /* set stlb data */ @@ -471,10 +498,13 @@ else { 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 ((tlbpte & acc) == 0) /* chk access */ + MM_ERR (PR_ACV); +if ((pte & PTE_V) == 0) /* check valid */ + MM_ERR (PR_TNV); if (acc & TLB_WACC) { /* write? */ - if ((pte & PTE_M) == 0) WriteL (ptead, pte | PTE_M); + if ((pte & PTE_M) == 0) + WriteL (ptead, pte | PTE_M); tlbpte = tlbpte | TLB_M; /* set M */ } vpn = VA_GETVPN (va); @@ -510,7 +540,8 @@ 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; + if (stb) + stlb[i].tag = stlb[i].pte = -1; } return; } @@ -521,7 +552,8 @@ void zap_tb_ent (uint32 va) { int32 tbi = VA_GETTBI (VA_GETVPN (va)); -if (va & VA_S0) stlb[tbi].tag = stlb[tbi].pte = -1; +if (va & VA_S0) + stlb[tbi].tag = stlb[tbi].pte = -1; else ptlb[tbi].tag = ptlb[tbi].pte = -1; return; } @@ -535,7 +567,8 @@ int32 tbi = VA_GETTBI (vpn); TLBENT xpte; xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; -if (xpte.tag == vpn) return TRUE; +if (xpte.tag == vpn) + return TRUE; return FALSE; } @@ -546,8 +579,10 @@ t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) int32 tlbn = uptr - tlb_unit; int32 idx = (uint32) addr >> 1; -if (idx >= VA_TBSIZE) return SCPE_NXM; -if (addr & 1) *vptr = ((uint32) (tlbn? stlb[idx].pte: ptlb[idx].pte)); +if (idx >= VA_TBSIZE) + return SCPE_NXM; +if (addr & 1) + *vptr = ((uint32) (tlbn? stlb[idx].pte: ptlb[idx].pte)); else *vptr = ((uint32) (tlbn? stlb[idx].tag: ptlb[idx].tag)); return SCPE_OK; } @@ -559,7 +594,8 @@ t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) int32 tlbn = uptr - tlb_unit; int32 idx = (uint32) addr >> 1; -if (idx >= VA_TBSIZE) return SCPE_NXM; +if (idx >= VA_TBSIZE) + return SCPE_NXM; if (addr & 1) { if (tlbn) stlb[idx].pte = (int32) val; else ptlb[idx].pte = (int32) val; diff --git a/VAX/vax_octa.c b/VAX/vax_octa.c index bbed2a7d..5b0448da 100644 --- a/VAX/vax_octa.c +++ b/VAX/vax_octa.c @@ -254,21 +254,27 @@ switch (opc) { r = op_cvthi (opnd, &flg, opc) & BMASK; /* convert */ h_write_b (spec, va, r, acc); /* write result */ CC_IIZZ_B (r); /* set cc's */ - if (flg) { V_INTOV; } + if (flg) { + V_INTOV; + } break; case CVTHW: r = op_cvthi (opnd, &flg, opc) & WMASK; /* convert */ h_write_w (spec, va, r, acc); /* write result */ CC_IIZZ_W (r); /* set cc's */ - if (flg) { V_INTOV; } + if (flg) { + V_INTOV; + } break; case CVTHL: case CVTRHL: r = op_cvthi (opnd, &flg, opc) & LMASK; /* convert */ h_write_l (spec, va, r, acc); /* write result */ CC_IIZZ_L (r); /* set cc's */ - if (flg) { V_INTOV; } + if (flg) { + V_INTOV; + } break; /* CVTFH @@ -421,11 +427,14 @@ switch (opc) { 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 */ + if (opnd[9] >= 0) /* store 1st */ + R[opnd[9]] = temp; 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? */ + if (flg) { + V_INTOV; + } break; default: @@ -442,8 +451,10 @@ return cc; int32 op_tsth (int32 val) { -if (val & H_EXP) return val; /* non-zero? */ -if (val & FPSIGN) RSVD_OPND_FAULT; /* reserved? */ +if (val & H_EXP) /* non-zero? */ + return val; +if (val & FPSIGN) /* reserved? */ + RSVD_OPND_FAULT; return 0; /* clean 0 */ } @@ -456,11 +467,15 @@ 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 */ +if (a.sign != b.sign) /* opp signs? */ + return (a.sign? CC_N: 0); +if (a.exp != b.exp) /* cmp exp */ + r = a.exp - b.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); +if (r < 0) /* !=, maybe set N */ + return (a.sign? 0: CC_N); +if (r > 0) + return (a.sign? CC_N: 0); return CC_Z; /* =, set Z */ } @@ -498,17 +513,21 @@ 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 ((a.exp == 0) || (ubexp < 0)) /* true zero or frac? */ + return 0; 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 */ + if (lnt == 03) /* if CVTR, round */ + qp_inc (&a.frac); 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; + (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? */ + if (ubexp > (UH_V_NM + 32)) /* in ext range? */ + return 0; 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 */ @@ -560,7 +579,8 @@ UFPH a, b; h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ h_unpackh (&opnd[4], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ +if (sub) /* sub? -s1 */ + a.sign = a.sign ^ FPSIGN; vax_hadd (&a, &b); /* do add */ return h_rpackh (&a, hflt); /* round and pack */ } @@ -604,7 +624,8 @@ int32 deg = opnd[4]; int32 ptr = opnd[5]; int32 i, wd[4], res[4]; -if (deg > 31) RSVD_OPND_FAULT; /* deg > 31? fault */ +if (deg > 31) /* deg > 31? fault */ + RSVD_OPND_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); @@ -679,12 +700,14 @@ if ((a->exp < b->exp) || /* |s1| < |s2|? */ 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 */ + if (ediff) /* denormalize */ + qp_rsh_s (&b->frac, ediff, 1); qp_add (&a->frac, &b->frac); /* "add" frac */ h_normh (a); /* normalize */ } else { - if (ediff) qp_rsh (&b->frac, ediff); /* add, denormalize */ + if (ediff) /* add, denormalize */ + qp_rsh (&b->frac, ediff); if (qp_add (&a->frac, &b->frac)) { /* add frac, carry? */ qp_rsh (&a->frac, 1); /* renormalize */ a->frac.f3 = a->frac.f3 | UH_NM_H; /* add norm bit */ @@ -710,10 +733,12 @@ if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ 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 */ - if (a->frac.f0 & 1) c = qp_add (&accum, &b->frac); /* mplr low? add */ + if (a->frac.f0 & 1) /* mplr low? add */ + c = qp_add (&accum, &b->frac); else c = 0; qp_rsh (&accum, 1); /* shift result */ - if (c) accum.f3 = accum.f3 | UH_NM_H; /* add carry out */ + if (c) /* add carry out */ + accum.f3 = accum.f3 | UH_NM_H; qp_rsh (&a->frac, 1); /* shift mplr */ } a->frac = accum; /* result */ @@ -736,7 +761,8 @@ void vax_hmod (UFPH *a, int32 *intgr, int32 *flg) { UQP ifr; -if (a->exp <= H_BIAS) *intgr = *flg = 0; /* 0 or <1? int = 0 */ +if (a->exp <= H_BIAS) /* 0 or <1? int = 0 */ + *intgr = *flg = 0; else if (a->exp <= (H_BIAS + 128)) { /* in range? */ ifr = a->frac; qp_rsh (&ifr, 128 - (a->exp - H_BIAS)); /* separate integer */ @@ -746,7 +772,8 @@ else if (a->exp <= (H_BIAS + 128)) { /* in range? */ *flg = CC_V; else *flg = 0; *intgr = ifr.f0; - if (a->sign) *intgr = -*intgr; /* -? comp int */ + if (a->sign) /* -? comp int */ + *intgr = -*intgr; qp_lsh (&a->frac, a->exp - H_BIAS); /* excise integer */ a->exp = H_BIAS; } @@ -770,8 +797,10 @@ void vax_hdiv (UFPH *a, UFPH *b) int32 i; UQP quo = { 0, 0, 0, 0 }; -if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */ -if (b->exp == 0) return; /* divd = 0? */ +if (a->exp == 0) /* divr = 0? */ + FLT_DZRO_FAULT; +if (b->exp == 0) /* divd = 0? */ + return; 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 */ @@ -793,14 +822,22 @@ return; int32 qp_cmp (UQP *a, UQP *b) { -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; -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; +if (a->f3 < b->f3) /* compare hi */ + return -1; +if (a->f3 > b->f3) + return +1; +if (a->f2 < b->f2) /* hi =, compare mid1 */ + return -1; +if (a->f2 > b->f2) + return +1; +if (a->f1 < b->f1) /* mid1 =, compare mid2 */ + return -1; +if (a->f1 > b->f1) + return +1; +if (a->f0 < b->f0) /* mid2 =, compare lo */ + return -1; +if (a->f0 > b->f0) + return +1; return 0; /* all equal */ } @@ -855,18 +892,22 @@ uint32 cryin; cryin = 1; a->f0 = (~a->f0 + cryin) & LMASK; -if (a->f0 != 0) cryin = 0; +if (a->f0 != 0) + cryin = 0; a->f1 = (~a->f1 + cryin) & LMASK; -if (a->f1 != 0) cryin = 0; +if (a->f1 != 0) + cryin = 0; a->f2 = (~a->f2 + cryin) & LMASK; -if (a->f2 != 0) cryin = 0; +if (a->f2 != 0) + cryin = 0; a->f3 = (~a->f3 + cryin) & LMASK; return; } void qp_lsh (UQP *r, uint32 sc) { -if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */ +if (sc >= 128) /* > 127? result 0 */ + r->f3 = r->f2 = r->f1 = r->f0 = 0; else if (sc >= 96) { /* [96,127]? */ r->f3 = (r->f0 << (sc - 96)) & LMASK; r->f2 = r->f1 = r->f0 = 0; @@ -904,7 +945,8 @@ return; void qp_rsh (UQP *r, uint32 sc) { -if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */ +if (sc >= 128) /* > 127? result 0 */ + r->f3 = r->f2 = r->f1 = r->f0 = 0; else if (sc >= 96) { /* [96,127]? */ r->f0 = (r->f3 >> (sc - 96)) & LMASK; r->f1 = r->f2 = r->f3 = 0; @@ -966,7 +1008,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac.f2 = r->frac.f3 = 0; /* else 0 */ return; } @@ -982,7 +1025,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac.f2 = r->frac.f3 = 0; /* else 0 */ return; } @@ -997,7 +1041,8 @@ 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 */ + if (r->sign) /* if -, rsvd op */ + RSVD_OPND_FAULT; r->frac.f0 = r->frac.f1 = 0; /* else 0 */ r->frac.f2 = r->frac.f3 = 0; return; @@ -1019,12 +1064,13 @@ 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; - } + 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; + if (r->frac.f3 & normmask[i]) + break; } qp_lsh (&r->frac, normtab[i]); /* shift frac */ r->exp = r->exp - normtab[i]; /* decr exp */ @@ -1037,20 +1083,25 @@ 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->frac.f3 == 0) && (r->frac.f2 == 0)) return 0; /* frac = 0? done */ +if (rh) /* assume 0 */ + *rh = 0; +if ((r->frac.f3 == 0) && (r->frac.f2 == 0)) /* frac = 0? done */ + return 0; 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 > (int32) FD_M_EXP) /* ovflo? fault */ + FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } qp_rsh (&r->frac, FD_GUARD); /* remove guard */ -if (rh) *rh = WORDSWAP (r->frac.f2); +if (rh) + *rh = WORDSWAP (r->frac.f2); return r->sign | (r->exp << FD_V_EXP) | (WORDSWAP (r->frac.f3) & ~(FD_HB | FPSIGN | FD_EXP)); } @@ -1060,15 +1111,18 @@ int32 h_rpackg (UFPH *r, int32 *rh) static UQP g_round = { 0, 0, UH_GRND, 0 }; *rh = 0; /* assume 0 */ -if ((r->frac.f3 == 0) && (r->frac.f2 == 0)) return 0; /* frac = 0? done */ +if ((r->frac.f3 == 0) && (r->frac.f2 == 0)) /* frac = 0? done */ + return 0; 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 > (int32) G_M_EXP) /* ovflo? fault */ + FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } qp_rsh (&r->frac, G_GUARD); /* remove guard */ @@ -1083,14 +1137,17 @@ static UQP h_round = { UH_HRND, 0, 0, 0 }; hflt[0] = hflt[1] = hflt[2] = hflt[3] = 0; /* assume 0 */ if ((r->frac.f3 == 0) && (r->frac.f2 == 0) && /* frac = 0? done */ - (r->frac.f1 == 0) && (r->frac.f0 == 0)) return 0; + (r->frac.f1 == 0) && (r->frac.f0 == 0)) + return 0; if (qp_add (&r->frac, &h_round)) { /* round, 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 > (int32) H_M_EXP) /* ovflo? fault */ + FLT_OVFL_FAULT; if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ + if (PSL & PSW_FU) /* fault if fu */ + FLT_UNFL_FAULT; return 0; /* else 0 */ } qp_rsh (&r->frac, H_GUARD); /* remove guard */ @@ -1106,7 +1163,8 @@ void h_write_b (int32 spec, int32 va, int32 val, int32 acc) { int32 rn; -if (spec > (GRN | nPC)) Write (va, val, L_BYTE, WA); +if (spec > (GRN | nPC)) + Write (va, val, L_BYTE, WA); else { rn = spec & 0xF; R[rn] = (R[rn] & ~BMASK) | val; @@ -1118,7 +1176,8 @@ void h_write_w (int32 spec, int32 va, int32 val, int32 acc) { int32 rn; -if (spec > (GRN | nPC)) Write (va, val, L_WORD, WA); +if (spec > (GRN | nPC)) + Write (va, val, L_WORD, WA); else { rn = spec & 0xF; R[rn] = (R[rn] & ~WMASK) | val; @@ -1128,7 +1187,8 @@ return; void h_write_l (int32 spec, int32 va, int32 val, int32 acc) { -if (spec > (GRN | nPC)) Write (va, val, L_LONG, WA); +if (spec > (GRN | nPC)) + Write (va, val, L_LONG, WA); else R[spec & 0xF] = val; return; } @@ -1145,7 +1205,8 @@ if (spec > (GRN | nPC)) { } else { rn = spec & 0xF; - if (rn >= nSP) RSVD_ADDR_FAULT; + if (rn >= nSP) + RSVD_ADDR_FAULT; R[rn] = vl; R[rn + 1] = vh; } @@ -1166,7 +1227,8 @@ if (spec > (GRN | nPC)) { } else { rn = spec & 0xF; - if (rn >= nAP) RSVD_ADDR_FAULT; + if (rn >= nAP) + RSVD_ADDR_FAULT; R[rn] = val[0]; R[rn + 1] = val[1]; R[rn + 2] = val[2]; diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c index f0b22632..fb092607 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-2007, Robert M Supnik + Copyright (c) 1998-2008, Robert 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,6 +27,7 @@ tto terminal output clk 100Hz and TODR clock + 17-Aug-08 RMS Resync TODR on any clock reset 18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock 17-Oct-06 RMS Synced keyboard poll to real-time clock for idling 22-Nov-05 RMS Revised for new terminal processing routines @@ -77,6 +78,7 @@ t_stat clk_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); t_stat clk_reset (DEVICE *dptr); +t_stat todr_resync (void); extern int32 sysd_hlt_enb (void); @@ -234,7 +236,8 @@ return (tto_csr & TTOCSR_IMP); void iccs_wr (int32 data) { -if ((data & CSR_IE) == 0) CLR_INT (CLK); +if ((data & CSR_IE) == 0) + CLR_INT (CLK); clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW); return; } @@ -242,13 +245,15 @@ return; void todr_wr (int32 data) { todr_reg = data; -if (data) todr_blow = 0; +if (data) + todr_blow = 0; return; } void rxcs_wr (int32 data) { -if ((data & CSR_IE) == 0) CLR_INT (TTI); +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); @@ -257,7 +262,8 @@ return; void txcs_wr (int32 data) { -if ((data & CSR_IE) == 0) CLR_INT (TTO); +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); @@ -284,15 +290,18 @@ t_stat tti_svc (UNIT *uptr) int32 c; sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; if (c & SCPE_BREAK) { /* break? */ - if (sysd_hlt_enb ()) hlt_pin = 1; /* if enabled, halt */ + if (sysd_hlt_enb ()) /* if enabled, halt */ + hlt_pin = 1; tti_unit.buf = TTIBUF_ERR | TTIBUF_FRM | TTIBUF_RBR; } else tti_unit.buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); uptr->pos = uptr->pos + 1; tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); +if (tti_csr & CSR_IE) + SET_INT (TTI); return SCPE_OK; } @@ -324,7 +333,8 @@ if (c >= 0) { } } tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) SET_INT (TTO); +if (tto_csr & CSR_IE) + SET_INT (TTO); uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -349,12 +359,14 @@ t_stat clk_svc (UNIT *uptr) { int32 t; -if (clk_csr & CSR_IE) SET_INT (CLK); +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 */ +if (!todr_blow) /* incr TODR */ + todr_reg = todr_reg + 1; return SCPE_OK; } @@ -368,18 +380,20 @@ t = sim_is_active (&clk_unit); return (t? t - 1: wait); } -/* Powerup routine */ +/* TODR resync routine */ -t_stat todr_powerup (void) +t_stat todr_resync (void) { uint32 base; time_t curr; struct tm *ctm; curr = time (NULL); /* get curr time */ -if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */ +if (curr == (time_t) -1) /* error? */ + return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ -if (ctm == NULL) return SCPE_NOFNC; /* error? */ +if (ctm == NULL) /* error? */ + return SCPE_NOFNC; base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ ctm->tm_hour) * 60) + ctm->tm_min) * 60) + @@ -395,7 +409,7 @@ t_stat clk_reset (DEVICE *dptr) { int32 t; -if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? */ +todr_resync (); /* resync clock */ clk_csr = 0; CLR_INT (CLK); t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init timer */ diff --git a/VAX/vax_sys.c b/VAX/vax_sys.c index 63c22d57..a18a7541 100644 --- a/VAX/vax_sys.c +++ b/VAX/vax_sys.c @@ -1,6 +1,6 @@ /* vax_sys.c: VAX simulator interface - Copyright (c) 1998-2005, Robert M Supnik + Copyright (c) 1998-2008, Robert 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,6 +23,7 @@ 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-08 RMS Moved bad block routine to I/O library 03-Nov-05 RMS Added 780 stop codes 04-Sep-05 RMS Fixed missing assignment (found by Peter Schorn) 16-Aug-05 RMS Fixed C++ declaration and cast problems @@ -70,7 +71,7 @@ int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, 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); +extern t_stat parse_sym_cm (char *cptr, t_addr addr, t_value *bytes, int32 sw); /* SCP data structures and interface routines @@ -104,48 +105,6 @@ const char *sim_stop_messages[] = { "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) - - Inputs: - uptr = pointer to unit - sec = number of sectors per surface - wds = number of words per sector - Outputs: - sta = status code -*/ - -t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) -{ -int32 i; -t_addr da; -uint16 *buf; - -if ((sec < 2) || (wds < 16)) return SCPE_ARG; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK; -da = (uptr->capac - (sec * wds)) * sizeof (uint16); -if (sim_fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -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); -free (buf); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - /* Dispatch/decoder table The first entry contains: @@ -778,19 +737,28 @@ int32 c, k, num, vp, lnt, rdx; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if (uptr == NULL) /* anon = CPU */ + uptr = &cpu_unit; 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 */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('L')) lnt = 4; +if (dptr == NULL) + return SCPE_IERR; +if (dptr->dwidth != 8) /* byte dev only */ + return SCPE_ARG; +if (sw & SWMASK ('B')) /* get length */ + lnt = 1; +else if (sw & SWMASK ('W')) + lnt = 2; +else if (sw & SWMASK ('L')) + lnt = 4; else lnt = (uptr == &cpu_unit)? 4: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; +if (sw & SWMASK ('D')) /* get radix */ + rdx = 10; +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--) { @@ -803,12 +771,14 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ 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 (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 (r <= 0) + return r; } vp = 0; /* init ptr */ @@ -835,10 +805,13 @@ 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? */ +if (inst == 0xFD) /* 2 byte op? */ + inst = 0x100 | (int32) val[vp++]; +if (opcode[inst] == NULL) /* defined? */ + return SCPE_ARG; numspec = DR_GETNSP (drom[inst][0]); /* get # spec */ -if (numspec == 0) numspec = DR_GETUSP (drom[inst][0]); +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 */ @@ -878,21 +851,23 @@ for (i = 0; i < numspec; i++) { /* loop thru spec */ break; case AIN: /* (Rn)+, #n */ - if (rn != nPC) fprintf (of, "(%-s)+", regname[rn]); + 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)); + GETNUM (num, DR_LNT (disp)); fprintf (of, "#%-X", num); } } break; case AID: /* @(Rn)+, @#n */ - if (rn != nPC) fprintf (of, "@(%-s)+", regname[rn]); + if (rn != nPC) + fprintf (of, "@(%-s)+", regname[rn]); else { GETNUM (num, 4); fprintf (of, "@#%-X", num); @@ -903,7 +878,8 @@ for (i = 0; i < numspec; i++) { /* loop thru spec */ fputc ('@', of); case BDP: /* b^d(r), b^n */ GETNUM (num, 1); - if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTB (num)); + 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]); @@ -913,7 +889,8 @@ for (i = 0; i < numspec; i++) { /* loop thru spec */ fputc ('@', of); case WDP: /* w^d(r), w^n */ GETNUM (num, 2); - if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTW (num)); + 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]); @@ -923,13 +900,15 @@ for (i = 0; i < numspec; i++) { /* loop thru spec */ fputc ('@', of); case LDP: /* l^d(r),l^n */ GETNUM (num, 4); - if (rn == nPC) fprintf (of, "%-X", addr + vp + num); + 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]); + if (index) + fprintf (of, "[%-s]", regname[index & 0xF]); } /* end else */ } /* end for */ return -(vp - 1); @@ -950,9 +929,12 @@ int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt) { int32 i, k, startp, num[4]; -for (i = 0; i < lnt; i++) { GETNUM (num[lnt - 1 - i], 4); } +for (i = 0; i < lnt; i++) { + GETNUM (num[lnt - 1 - i], 4); + } for (i = startp = 0; i < lnt; i++) { - if (startp) fprintf (of, "%08X", num[i]); + if (startp) + fprintf (of, "%08X", num[i]); else if (num[i] || (i == (lnt - 1))) { fprintf (of, "#%-X", num[i]); startp = 1; @@ -984,17 +966,26 @@ t_stat r; DEVICE *dptr; static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if (uptr == NULL) /* anon = CPU */ + uptr = &cpu_unit; dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('L')) lnt = 4; +if (dptr == NULL) + return SCPE_IERR; +if (dptr->dwidth != 8) /* byte dev only */ + return SCPE_ARG; +if (sw & SWMASK ('B')) /* get length */ + lnt = 1; +else if (sw & SWMASK ('W')) + lnt = 2; +else if (sw & SWMASK ('L')) + lnt = 4; else lnt = (uptr == &cpu_unit)? 4: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; +if (sw & SWMASK ('D')) /* get radix */ + rdx = 10; +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? */ @@ -1005,16 +996,19 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) /* ASCII string? */ 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 (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 (r <= 0) + return r; } num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; vp = 0; PUTNUM (num, lnt); /* store */ return -(lnt - 1); @@ -1035,7 +1029,8 @@ t_stat parse_char (char *cptr, t_value *val, int32 lnt) { int32 vp; -if (*cptr == 0) return SCPE_ARG; +if (*cptr == 0) + return SCPE_ARG; vp = 0; while ((vp < lnt) && *cptr) { /* get chars */ val[vp++] = *cptr++; @@ -1062,29 +1057,39 @@ char gbuf[CBUFSIZE]; cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ for (i = 0, opc = -1; (i < NUM_INST) && (opc < 0); i++) { - if (opcode[i] && strcmp (gbuf, opcode[i]) == 0) opc = i; + if (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 (strcmp (gbuf, altcod[i]) == 0) + opc = altop[i]; } } -if (opc < 0) return SCPE_ARG; /* undefined? */ +if (opc < 0) + return SCPE_ARG; /* undefined? */ vp = 0; -if (opc >= 0x100) val[vp++] = 0xFD; /* 2 byte? */ +if (opc >= 0x100) /* 2 byte? */ + val[vp++] = 0xFD; val[vp++] = opc & 0xFF; /* store opcode */ numspec = DR_GETNSP (drom[opc][0]); /* get # specifiers */ -if (numspec == 0) numspec = DR_GETUSP (drom[opc][0]); +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); + 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); + 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 (r != SCPE_OK) + return r; } -if (*cptr != 0) return SCPE_ARG; +if (*cptr != 0) + return SCPE_ARG; return -(vp - 1); } @@ -1143,9 +1148,17 @@ return vp; #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 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) @@ -1162,11 +1175,13 @@ 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; + 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 */ + if (*tptr != 0) /* must be done */ + *r = SCPE_ARG; return vp; } for (i = 0; force[i]; i++) { /* look for x^ */ @@ -1181,32 +1196,38 @@ 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; + 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); + 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 (lit[i] && (i > litsize)) + litsize = i; } } if (*cptr == '(') { /* look for (Rn) */ cptr = parse_rnum (++cptr, &rn); - if ((cptr == NULL) || (*cptr++ != ')')) PARSE_LOSE; + 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; + 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; + if ((litsize > 0) || (lit[0] & ~0x3F)) + PARSE_LOSE; val[vp++] = lit[0]; break; @@ -1237,20 +1258,24 @@ switch (fl) { /* case on state */ switch (disp) { /* case spec lnt */ case 00: /* check fit */ if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; + (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; + (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) + PARSE_LOSE; SPUTNUM (lit[0], 2); break; case 02: /* check 1 lw */ - if (litsize > 0) PARSE_LOSE; + if (litsize > 0) + PARSE_LOSE; SPUTNUM (lit[0], 4); break; case 03: /* check 2 lw */ - if (litsize > 1) PARSE_LOSE; + if (litsize > 1) + PARSE_LOSE; vp = parse_sym_qoimm (lit, val, vp, 2, fl & SP_MINUS); break; case 04: @@ -1264,17 +1289,20 @@ switch (fl) { /* case on state */ break; case SP_IND|SP_LIT|SP_NUM: /* @#n */ - if (litsize > 0) PARSE_LOSE; + 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; + if (litsize > 0) + PARSE_LOSE; dispsize = 4; /* find fit for */ mode = LDP; /* displacement */ if (lit[0] >= 0) { @@ -1298,7 +1326,8 @@ switch (fl) { /* case on state */ 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; + (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) + PARSE_LOSE; val[vp++] = rn | BDP | ((fl & SP_IND)? 0x10: 0); SPUTNUM (lit[0], 1); break; @@ -1310,7 +1339,8 @@ switch (fl) { /* case on state */ 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; + (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) + PARSE_LOSE; val[vp++] = rn | WDP | ((fl & SP_IND)? 0x10: 0); SPUTNUM (lit[0], 2); break; @@ -1321,14 +1351,16 @@ switch (fl) { /* case on state */ 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; + 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; + if (litsize > 0) + PARSE_LOSE; num = lit[0] - (addr + vp + 2); /* fit in byte? */ if ((num >= -128) && (num <= 127)) { mode = BDP; @@ -1353,7 +1385,8 @@ switch (fl) { /* case on state */ 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; + if ((litsize > 0) || (num > 127) || (num < -128)) + PARSE_LOSE; val[vp++] = nPC | BDP | ((fl & SP_IND)? 1: 0); PUTNUM (num, 1); break; @@ -1361,7 +1394,8 @@ switch (fl) { /* case on state */ 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; + if ((litsize > 0) || (num > 32767) || (num < -32768)) + PARSE_LOSE; val[vp++] = nPC | WDP | ((fl & SP_IND)? 1: 0); PUTNUM (num, 2); break; @@ -1369,7 +1403,8 @@ switch (fl) { /* case on state */ 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; + if (litsize > 0) + PARSE_LOSE; val[vp++] = nPC | LDP | ((fl & SP_IND)? 1: 0); PUTNUM (num, 4); break; @@ -1378,7 +1413,8 @@ switch (fl) { /* case on state */ PARSE_LOSE; } /* end case */ -if (*cptr != 0) *r = SCPE_ARG; /* must be done */ +if (*cptr != 0) /* must be done */ + *r = SCPE_ARG; return vp; } @@ -1395,9 +1431,11 @@ for (i = 15; i >= 0; i--) { /* chk named reg */ return cptr + lnt; } } -if (*cptr++ != 'R') return NULL; /* look for R */ +if (*cptr++ != 'R') /* look for R */ + return NULL; regnum = strtotv (cptr, &tptr, 10); /* look for reg # */ -if ((cptr == tptr) || (regnum > 15)) return NULL; +if ((cptr == tptr) || (regnum > 15)) + return NULL; *rn = (int32) regnum; return tptr; } @@ -1407,7 +1445,8 @@ 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); + 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 c209104a..b55816d0 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -220,12 +220,14 @@ switch (mode) { break; case 2: - if (reg != 7) fprintf (of, "(%s)+", rname[reg]); + if (reg != 7) + fprintf (of, "(%s)+", rname[reg]); else fprintf (of, "#%-X", nval); break; case 3: - if (reg != 7) fprintf (of, "@(%s)+", rname[reg]); + if (reg != 7) + fprintf (of, "@(%s)+", rname[reg]); else fprintf (of, "@#%-X", nval); break; @@ -238,12 +240,14 @@ switch (mode) { break; case 6: - if (reg != 7) fprintf (of, "%-X(%s)", nval, rname[reg]); + 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]); + if (reg != 7) + fprintf (of, "@%-X(%s)", nval, rname[reg]); else fprintf (of, "@%-X", (nval + addr + 4) & 0177777); break; } /* end case */ @@ -274,12 +278,13 @@ 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 */ + if (val[0] > 0174777) /* max value */ + return SCPE_ARG; 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]); + r50_to_asc[c2], r50_to_asc[c3]); return -1; } if (!(sw & SWMASK ('P')) || (addr & 1) || (addr > WMASK)) @@ -382,9 +387,11 @@ int32 get_reg (char *cptr, char mchar) { int32 i; -if (*(cptr + 2) != mchar) return -1; +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; } @@ -425,11 +432,13 @@ if (*cptr == '-') { /* -? */ errno = 0; val = strtoul (cptr, &tptr, 16); if (cptr == tptr) { /* no number? */ - if (*pflag == (A_REL + A_NUM)) return NULL; /* .+, .-? */ + if (*pflag == (A_REL + A_NUM)) /* .+, .-? */ + return NULL; *dptr = 0; return cptr; } -if (errno || (*pflag == A_REL)) return NULL; /* .n? */ +if (errno || (*pflag == A_REL)) /* .n? */ + return NULL; *dptr = (minus? -val: val) & 0177777; *pflag = *pflag | A_NUM; return tptr; @@ -469,10 +478,12 @@ if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */ pflag = pflag | A_MIN; cptr++; } -else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1; +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; + if ((reg = get_reg (cptr + 1, ')')) < 0) + return 1; cptr = cptr + 4; if (*cptr == '+') { /* autoincrement? */ pflag = pflag | A_PLS; @@ -483,7 +494,8 @@ else if ((reg = get_reg (cptr, 0)) >= 0) { pflag = pflag | A_REG; cptr = cptr + 2; } -if (*cptr != 0) return 1; /* all done? */ +if (*cptr != 0) /* all done? */ + return 1; switch (pflag) { /* case on syntax */ @@ -556,14 +568,16 @@ int32 ad32 = (int32) addr; t_stat r; char *tptr, gbuf[CBUFSIZE]; -if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ +if (sw & SWMASK ('R')) /* radix 50 */ + return SCPE_ARG; if (!(sw & SWMASK ('P')) || (ad32 & 1) || (ad32 > WMASK)) return SCPE_ARG; 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; +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 */ @@ -574,43 +588,51 @@ switch (j) { /* case on class */ case I_V_REG: /* register */ cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((reg = get_reg (gbuf, 0)) < 0) return SCPE_ARG; + 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; + 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 ((tptr == NULL) || (*tptr != 0)) + return SCPE_ARG; if ((pflag & A_REL) == 0) disp = (disp - ad32) & 0177777; - if ((disp & 1) || (disp > 0400) && (disp < 0177402)) 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, 0)) < 0) return SCPE_ARG; + 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 ((tptr == NULL) || (*tptr != 0)) + return SCPE_ARG; if ((pflag & A_REL) == 0) disp = (disp - ad32) & 0177777; - if ((disp & 1) || ((disp > 2) && (disp < 0177604))) 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, 0)) < 0) return SCPE_ARG; + 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 */ @@ -625,7 +647,8 @@ switch (j) { /* case on class */ return SCPE_ARG; val[0] = val[0] | spec; cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((reg = get_reg (gbuf, 0)) < 0) return SCPE_ARG; + if ((reg = get_reg (gbuf, 0)) < 0) + return SCPE_ARG; val[0] = val[0] | (reg << 6); break; @@ -646,8 +669,9 @@ switch (j) { /* case on class */ 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); + (opcode[i] == NULL)) + return SCPE_ARG; + val[0] = val[0] | (opc_val[i] & 0177777); } break; diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c index 3940f925..5f575bd9 100644 --- a/VAX/vax_sysdev.c +++ b/VAX/vax_sysdev.c @@ -1,6 +1,6 @@ /* vax_sysdev.c: VAX 3900 system-specific logic - Copyright (c) 1998-2005, Robert M Supnik + Copyright (c) 1998-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -480,7 +480,8 @@ int32 rom_read_delay (int32 val) uint32 i, l = rom_delay; int32 loopval = 0; -if (rom_unit.flags & UNIT_NODELAY) return val; +if (rom_unit.flags & UNIT_NODELAY) + return val; /* Calibrate the loop delay factor when first used. Do this 4 times to and use the largest value computed. */ @@ -501,13 +502,16 @@ if (rom_delay == 0) { 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 ((te - ts) < 50) /* sample big enough? */ + continue; if (rom_delay < (loopval + (c / (te - ts) / 1000) + 1)) rom_delay = loopval + (c / (te - ts) / 1000) + 1; - if (++samples >= 4) break; + if (++samples >= 4) + break; c = c / 2; } - if (rom_delay < 5) rom_delay = 5; + if (rom_delay < 5) + rom_delay = 5; } for (i = 0; i < l; i++) @@ -537,8 +541,10 @@ t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) { uint32 addr = (uint32) exta; -if ((vptr == NULL) || (addr & 03)) return SCPE_ARG; -if (addr >= ROMSIZE) return SCPE_NXM; +if ((vptr == NULL) || (addr & 03)) + return SCPE_ARG; +if (addr >= ROMSIZE) + return SCPE_NXM; *vptr = rom[addr >> 2]; return SCPE_OK; } @@ -549,8 +555,10 @@ t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) { uint32 addr = (uint32) exta; -if (addr & 03) return SCPE_ARG; -if (addr >= ROMSIZE) return SCPE_NXM; +if (addr & 03) + return SCPE_ARG; +if (addr >= ROMSIZE) + return SCPE_NXM; rom[addr >> 2] = (uint32) val; return SCPE_OK; } @@ -559,8 +567,10 @@ return SCPE_OK; t_stat rom_reset (DEVICE *dptr) { -if (rom == NULL) rom = (uint32 *) calloc (ROMSIZE >> 2, sizeof (uint32)); -if (rom == NULL) return SCPE_MEM; +if (rom == NULL) + rom = (uint32 *) calloc (ROMSIZE >> 2, sizeof (uint32)); +if (rom == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -592,8 +602,10 @@ t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) { uint32 addr = (uint32) exta; -if ((vptr == NULL) || (addr & 03)) return SCPE_ARG; -if (addr >= NVRSIZE) return SCPE_NXM; +if ((vptr == NULL) || (addr & 03)) + return SCPE_ARG; +if (addr >= NVRSIZE) + return SCPE_NXM; *vptr = nvr[addr >> 2]; return SCPE_OK; } @@ -604,8 +616,10 @@ t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) { uint32 addr = (uint32) exta; -if (addr & 03) return SCPE_ARG; -if (addr >= NVRSIZE) return SCPE_NXM; +if (addr & 03) + return SCPE_ARG; +if (addr >= NVRSIZE) + return SCPE_NXM; nvr[addr >> 2] = (uint32) val; return SCPE_OK; } @@ -619,7 +633,8 @@ if (nvr == NULL) { nvr_unit.filebuf = nvr; ssc_cnf = ssc_cnf | SSCCNF_BLO; } -if (nvr == NULL) return SCPE_MEM; +if (nvr == NULL) + return SCPE_MEM; return SCPE_OK; } @@ -668,7 +683,8 @@ return (csi_unit.buf & 0377); void csrs_wr (int32 data) { -if ((data & CSR_IE) == 0) CLR_INT (CSI); +if ((data & CSR_IE) == 0) + CLR_INT (CSI); else if ((csi_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) SET_INT (CSI); csi_csr = (csi_csr & ~CSICSR_RW) | (data & CSICSR_RW); @@ -692,7 +708,8 @@ return (cso_csr & CSOCSR_IMP); void csts_wr (int32 data) { -if ((data & CSR_IE) == 0) CLR_INT (CSO); +if ((data & CSR_IE) == 0) + CLR_INT (CSO); else if ((cso_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) SET_INT (CSO); cso_csr = (cso_csr & ~CSOCSR_RW) | (data & CSOCSR_RW); @@ -711,8 +728,10 @@ return; t_stat cso_svc (UNIT *uptr) { cso_csr = cso_csr | CSR_DONE; -if (cso_csr & CSR_IE) SET_INT (CSO); -if ((cso_unit.flags & UNIT_ATT) == 0) return SCPE_OK; +if (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); @@ -1105,7 +1124,8 @@ 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; } @@ -1337,7 +1357,8 @@ if (interp || (tmr_csr[tmr] & TMR_CSR_RUN)) { /* interp, running? */ 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; + if (delta >= tmr_inc[tmr]) + delta = tmr_inc[tmr] - 1; return tmr_tir[tmr] + delta; } return tmr_tir[tmr]; @@ -1345,7 +1366,8 @@ return tmr_tir[tmr]; void tmr_csr_wr (int32 tmr, int32 val) { -if ((tmr < 0) || (tmr > 1)) return; +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? */ @@ -1354,7 +1376,8 @@ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ 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_XFR) /* xfr set? */ + tmr_tir[tmr] = tmr_tnir[tmr]; if (val & TMR_CSR_RUN) { /* run? */ if (val & TMR_CSR_XFR) /* new tir? */ sim_cancel (&sysd_unit[tmr]); /* stop prev */ @@ -1368,7 +1391,8 @@ else if (val & TMR_CSR_SGL) { /* single step? */ } if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ (TMR_CSR_DON | TMR_CSR_IE)) { - if (tmr) CLR_INT (TMR1); + if (tmr) + CLR_INT (TMR1); else CLR_INT (TMR0); } return; @@ -1402,7 +1426,8 @@ if (new_tir < tmr_tir[tmr]) { /* ovflo? */ tmr_sched (tmr); /* reactivate */ } if (tmr_csr[tmr] & TMR_CSR_IE) { /* set int req */ - if (tmr) SET_INT (TMR1); + if (tmr) + SET_INT (TMR1); else SET_INT (TMR0); } } @@ -1430,7 +1455,8 @@ else { tmr_inc[tmr] = TMR_INC; /* usec/interval */ tmr_time = tmr_poll; } -if (tmr_time == 0) tmr_time = 1; +if (tmr_time == 0) + tmr_time = 1; if ((tmr_inc[tmr] == TMR_INC) && (tmr_time > clk_time)) { /* Align scheduled event to be identical to the event for the next clock @@ -1462,10 +1488,12 @@ 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 */ +if (p1 & 0x80) /* mref? set v/p */ + p1 = p1 + mchk_ref; p2 = mchk_va + 4; /* save vap */ for (i = hsir = 0; i < 16; i++) { /* find hsir */ - if ((SISR >> i) & 1) hsir = i; + if ((SISR >> i) & 1) + hsir = i; } st1 = ((((uint32) opc) & 0xFF) << 24) | (hsir << 16) | @@ -1494,9 +1522,11 @@ 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? */ +if (temp > 4) /* invalid? */ + conpsl = conpsl | CON_BADPSL; else STK[temp] = SP; /* save stack */ -if (mapen) conpsl = conpsl | CON_MAPON; /* mapping on? */ +if (mapen) /* mapping on? */ + conpsl = conpsl | CON_MAPON; mapen = 0; /* turn off map */ SP = IS; /* set SP from IS */ PSL = PSL_IS | PSL_IPL1F; /* PSL = 41F0000 */ @@ -1516,13 +1546,15 @@ PC = ROMBASE; PSL = PSL_IS | PSL_IPL1F; conpc = 0; conpsl = PSL_IS | PSL_IPL1F | CON_PWRUP; -if (rom == NULL) return SCPE_IERR; +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"); + 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 (r != SCPE_OK) + return r; } return SCPE_OK; } @@ -1556,7 +1588,8 @@ t_stat sysd_powerup (void) { int32 i; -for (i = 0; i < (CMCTLSIZE >> 2); i++) cmctl_reg[i] = 0; +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; diff --git a/VAX/vax_syslist.c b/VAX/vax_syslist.c index f19fb28b..f2e4eefe 100644 --- a/VAX/vax_syslist.c +++ b/VAX/vax_syslist.c @@ -1,6 +1,6 @@ /* vax_sys.c: VAX simulator interface - Copyright (c) 1998-2006, Robert M Supnik + Copyright (c) 1998-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -105,7 +105,8 @@ uint32 origin, limit; extern int32 ssc_cnf; #define SSCCNF_BLO 0x80000000 -if (flag) return SCPE_ARG; /* dump? */ +if (flag) /* dump? */ + return SCPE_ARG; if (sim_switches & SWMASK ('R')) { /* ROM? */ origin = ROMBASE; limit = ROMBASE + ROMSIZE; @@ -120,11 +121,13 @@ else { 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; + if (r != SCPE_OK) + return SCPE_ARG; } } while ((i = getc (fileref)) != EOF) { /* read byte stream */ - if (origin >= limit) return SCPE_NXM; /* NXM? */ + if (origin >= limit) /* NXM? */ + return SCPE_NXM; if (sim_switches & SWMASK ('R')) /* ROM? */ rom_wr_B (origin, i); /* not writeable */ else WriteB (origin, i); /* store byte */ diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 6dc06dae..c8584397 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -239,6 +239,8 @@ #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 DLX_LINES 16 /* max # of KL11/DL11's */ +#define DCX_LINES 16 /* max # of DC11's */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define AUTO_LNT 34 /* autoconfig ranks */ @@ -464,13 +466,8 @@ int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf); int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf); int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (char *name, int32 num); - int32 clk_cosched (int32 wait); +#include "pdp11_io_lib.h" + #endif diff --git a/descrip.mms b/descrip.mms index 6f92ee2e..f6530a56 100644 --- a/descrip.mms +++ b/descrip.mms @@ -268,7 +268,8 @@ HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\ $(HP2100_DIR)HP2100_CPU2.C,$(HP2100_DIR)HP2100_CPU3.C,\ $(HP2100_DIR)HP2100_CPU4.C,$(HP2100_DIR)HP2100_CPU5.C,\ $(HP2100_DIR)HP2100_CPU6.C,$(HP2100_DIR)HP2100_CPU7.C,\ - $(HP2100_DIR)HP2100_FP1.C,$(HP2100_DIR)HP2100_BACI.C + $(HP2100_DIR)HP2100_FP1.C,$(HP2100_DIR)HP2100_BACI.C,\ + $(HP2100_DIR)HP2100_MPX.C,$(HP2100_DIR)HP2100_PIF.C .IF ALPHA_OR_IA64 HP2100_OPTIONS = /INCL=($(SIMH_DIR),$(HP2100_DIR))\ /DEF=($(CC_DEFS),"HAVE_INT64=1") @@ -395,7 +396,7 @@ PDP11_SOURCE1 = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ $(PDP11_DIR)PDP11_RX.C,$(PDP11_DIR)PDP11_STDDEV.C,\ $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C, \ $(PDP11_DIR)PDP11_CPUMOD.C,$(PDP11_DIR)PDP11_CR.C,\ - $(PDP11_DIR)PDP11_TA.C + $(PDP11_DIR)PDP11_TA.C,$(PDP11_DIR)PDP11_IO_LIB.C PDP11_LIB2 = $(LIB_DIR)PDP11L2-$(ARCH).OLB PDP11_SOURCE2 = $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ @@ -458,7 +459,7 @@ VAX_SOURCE = $(VAX_DIR)VAX_CIS.C,$(VAX_DIR)VAX_CMODE.C,\ $(VAX_DIR)VAX_OCTA.C,$(VAX_DIR)VAX_SYS.C,\ $(VAX_DIR)VAX_SYSCM.C,$(VAX_DIR)VAX_SYSDEV.C,\ $(VAX_DIR)VAX_SYSLIST.C,$(VAX_DIR)VAX_IO.C,\ - $(VAX_DIR)VAX_STDDEV.C,\ + $(VAX_DIR)VAX_STDDEV.C,$(PDP11_DIR)PDP11_IO_LIB.C,\ $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ @@ -485,7 +486,8 @@ VAX780_SOURCE2 = $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ $(PDP11_DIR)PDP11_XU.C,$(PDP11_DIR)PDP11_RY.C,\ $(PDP11_DIR)PDP11_CR.C,$(PDP11_DIR)PDP11_RP.C,\ - $(PDP11_DIR)PDP11_TU.C,$(PDP11_DIR)PDP11_HK.C + $(PDP11_DIR)PDP11_TU.C,$(PDP11_DIR)PDP11_HK.C,\ + $(PDP11_DIR)PDP11_IO_LIB.C VAX780_OPTIONS = /INCL=($(SIMH_DIR),$(VAX780_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEF=($(CC_DEFS),"VM_VAX=1"$(PCAP_DEFS),"VAX_780=1") diff --git a/makefile b/makefile index fd2501c8..2b65533f 100644 --- a/makefile +++ b/makefile @@ -84,7 +84,7 @@ PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \ ${PDP11D}/pdp11_rh.c ${PDP11D}/pdp11_tu.c ${PDP11D}/pdp11_cpumod.c \ ${PDP11D}/pdp11_cr.c ${PDP11D}/pdp11_rf.c ${PDP11D}/pdp11_dl.c \ ${PDP11D}/pdp11_ta.c ${PDP11D}/pdp11_rc.c ${PDP11D}/pdp11_kg.c \ - ${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c + ${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c ${PDP11D}/pdp11_io_lib.c PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} @@ -95,8 +95,8 @@ VAX = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c ${VAXD}/vax_io.c \ ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c ${VAXD}/vax_syslist.c \ ${PDP11D}/pdp11_rl.c ${PDP11D}/pdp11_rq.c ${PDP11D}/pdp11_ts.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ - ${PDP11D}/pdp11_xq.c ${PDP11D}/pdp11_ry.c \ - ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_cr.c + ${PDP11D}/pdp11_xq.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_vh.c \ + ${PDP11D}/pdp11_cr.c ${PDP11D}/pdp11_io_lib.c VAX_OPT = -DVM_VAX -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} @@ -109,7 +109,8 @@ VAX780 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${PDP11D}/pdp11_rl.c ${PDP11D}/pdp11_rq.c ${PDP11D}/pdp11_ts.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ - ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_tu.c ${PDP11D}/pdp11_hk.c + ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_tu.c ${PDP11D}/pdp11_hk.c \ + ${PDP11D}/pdp11_io_lib.c VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} @@ -149,7 +150,8 @@ HP2100 = ${HP2100D}/hp2100_stddev.c ${HP2100D}/hp2100_dp.c ${HP2100D}/hp2100_dq. ${HP2100D}/hp2100_ipl.c ${HP2100D}/hp2100_ds.c ${HP2100D}/hp2100_cpu0.c \ ${HP2100D}/hp2100_cpu1.c ${HP2100D}/hp2100_cpu2.c ${HP2100D}/hp2100_cpu3.c \ ${HP2100D}/hp2100_cpu4.c ${HP2100D}/hp2100_cpu5.c ${HP2100D}/hp2100_cpu6.c \ - ${HP2100D}/hp2100_cpu7.c ${HP2100D}/hp2100_fp1.c ${HP2100D}/hp2100_baci.c + ${HP2100D}/hp2100_cpu7.c ${HP2100D}/hp2100_fp1.c ${HP2100D}/hp2100_baci.c \ + ${HP2100D}/hp2100_mpx.c ${HP2100D}/hp2100_pif.c HP2100_OPT = -DHAVE_INT64 -I ${HP2100D} @@ -223,12 +225,13 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \ ${ALTAIRZ80D}/i86_ops.c ${ALTAIRZ80D}/i86_prim_ops.c \ ${ALTAIRZ80D}/i8272.c ${ALTAIRZ80D}/insnsa.c ${ALTAIRZ80D}/insnsd.c \ ${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \ - ${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c \ + ${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c\ ${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \ ${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \ ${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \ ${ALTAIRZ80D}/s100_scp300f.c ${ALTAIRZ80D}/sim_imd.c \ - ${ALTAIRZ80D}/wd179x.c + ${ALTAIRZ80D}/wd179x.c ${ALTAIRZ80D}/s100_hdc1001.c \ + ${ALTAIRZ80D}/s100_if3.c ${ALTAIRZ80D}/s100_adcs6.c ALTAIRZ80_OPT = -I ${ALTAIRZ80D} diff --git a/scp.c b/scp.c index c28b7280..f64196a2 100644 --- a/scp.c +++ b/scp.c @@ -1,6 +1,6 @@ /* scp.c: simulator control program - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2009, Robert 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,6 +23,13 @@ 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-09 RMS Fixed warnings in help printouts + 29-Dec-08 RMS Fixed implementation of MTAB_NC + 24-Nov-08 RMS Revised RESTORE unit logic for consistency + 05-Sep-08 JDB "detach_all" ignores error status returns if shutting down + 17-Aug-08 RMS Revert RUN/BOOT to standard, rather than powerup, reset + 25-Jul-08 JDB DO cmd missing params now default to null string + 29-Jun-08 JDB DO cmd sub_args now allows "\\" to specify literal backslash 31-Mar-08 RMS Fixed bug in local/global register search (found by Mark Pizzolato) Fixed bug in restore of RO units (from Mark Pizzolato) 06-Feb-08 RMS Added SET/SHO/NO BR with default argument @@ -339,7 +346,7 @@ t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr); t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr, UNIT *uptr, int32 dfltinc); t_stat step_svc (UNIT *ptr); -void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]); +void sub_args (char *instr, char *tmpbuf, int32 maxstr, char *do_arg[]); /* Global data */ @@ -587,7 +594,8 @@ argc = ccommand (&argv); 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] == NULL) /* paranoia */ + continue; if ((*argv[i] == '-') && lookswitch) { /* switch? */ if ((sw = get_switches (argv[i])) < 0) { fprintf (stderr, "Invalid switch %s\n", argv[i]); @@ -600,14 +608,16 @@ for (i = 1; i < argc; i++) { /* loop thru args */ fprintf (stderr, "Argument string too long\n"); return 0; } - if (*cbuf) strcat (cbuf, " "); /* concat args */ + if (*cbuf) /* concat args */ + strcat (cbuf, " "); 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 */ +if (sim_vm_init != NULL) /* call once only */ + (*sim_vm_init)(); sim_finit (); /* init fio package */ stop_cpu = 0; sim_interval = 0; @@ -616,7 +626,8 @@ noqueue_time = 0; sim_clock_queue = NULL; sim_is_running = 0; sim_log = NULL; -if (sim_emax <= 0) sim_emax = 1; +if (sim_emax <= 0) + sim_emax = 1; sim_timer_init (); if ((stat = sim_ttinit ()) != SCPE_OK) { @@ -642,7 +653,8 @@ if (!sim_quiet) { printf ("\n"); show_version (stdout, NULL, NULL, 0, NULL); } -if (sim_dflt_dev == NULL) sim_dflt_dev = sim_devices[0]; /* if no default */ +if (sim_dflt_dev == NULL) /* if no default */ + sim_dflt_dev = sim_devices[0]; if (*cbuf) /* cmd file arg? */ stat = do_cmd (0, cbuf); /* proc cmd file */ @@ -650,7 +662,8 @@ 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 */ + if (np = match_ext (nbuf, "EXE")) /* remove .exe */ + *np = 0; strcat (nbuf, ".ini\""); /* add .ini" */ stat = do_cmd (-1, nbuf); /* proc cmd file */ } @@ -662,9 +675,12 @@ while (stat != SCPE_EXIT) { /* in case exit */ 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 */ + if (cptr == NULL) /* ignore EOF */ + continue; + if (*cptr == 0) /* ignore blank */ + continue; + if (sim_log) /* log cmd */ + fprintf (sim_log, "sim> %s\n", cptr); cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ sim_switches = 0; /* init switches */ if (cmdp = find_cmd (gbuf)) /* lookup command */ @@ -672,10 +688,11 @@ while (stat != SCPE_EXIT) { /* in case exit */ 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_log) + fprintf (sim_log, "%s\n", scp_error_messages[stat - SCPE_BASE]); } - if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); + if (sim_vm_post != NULL) + (*sim_vm_post) (TRUE); } /* end while */ detach_all (0, TRUE); /* close files */ @@ -692,8 +709,10 @@ 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) /* try ext commands */ + cmdp = find_ctab (sim_vm_cmd, gbuf); +if (cmdp == NULL) /* try regular cmds */ + cmdp = find_ctab (cmd_table, gbuf); return cmdp; } @@ -711,11 +730,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) + fputs (cmdp->help, st); } 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); + fputs (cmdp->help, st); } return; } @@ -728,16 +748,19 @@ CTAB *cmdp; GET_SWITCHES (cptr); if (*cptr) { cptr = get_glyph (cptr, gbuf, 0); - if (*cptr) return SCPE_2MARG; + if (*cptr) + return SCPE_2MARG; if (cmdp = find_cmd (gbuf)) { - printf (cmdp->help); - if (sim_log) fprintf (sim_log, cmdp->help); + fputs (cmdp->help, stdout); + if (sim_log) + fputs (cmdp->help, sim_log); } else return SCPE_ARG; } else { fprint_help (stdout); - if (sim_log) fprint_help (sim_log); + if (sim_log) + fprint_help (sim_log); } return SCPE_OK; } @@ -746,13 +769,17 @@ return SCPE_OK; t_stat spawn_cmd (int32 flag, char *cptr) { -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = getenv("SHELL"); -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = getenv("ComSpec"); +if ((cptr == NULL) || (strlen (cptr) == 0)) + cptr = getenv("SHELL"); +if ((cptr == NULL) || (strlen (cptr) == 0)) + cptr = getenv("ComSpec"); #if defined (VMS) -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = "SPAWN/INPUT=SYS$COMMAND:"; +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 */ +if (sim_log) /* flush log if enabled */ + fflush (sim_log); system (cptr); #if defined (VMS) printf ("\n"); @@ -766,7 +793,8 @@ return SCPE_OK; t_stat echo_cmd (int32 flag, char *cptr) { puts (cptr); -if (sim_log) fprintf (sim_log, "%s\n", cptr); +if (sim_log) + fprintf (sim_log, "%s\n", cptr); return SCPE_OK; } @@ -811,21 +839,32 @@ char *ocptr; stat = SCPE_OK; staying = TRUE; interactive = (flag > 0); /* issued interactively? */ -if (interactive) { GET_SWITCHES (fcptr); } /* get switches */ +if (interactive) { /* get switches */ + GET_SWITCHES (fcptr); + } echo = sim_switches & SWMASK ('V'); /* -v means echo */ errabort = sim_switches & SWMASK ('E'); /* -e means abort on error */ 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 */ + while (isspace (*c)) /* skip blanks */ + c++; + if (*c == 0) /* all done? */ + do_arg [nargs++] = NULL; /* null argument */ + else { + if (*c == '\'' || *c == '"') /* quoted string? */ + quote = *c++; + else quote = 0; + do_arg[nargs++] = c; /* save start */ + while (*c && (quote ? (*c != quote) : !isspace (*c))) + c++; + if (*c) /* term at quote/spc */ + *c++ = 0; + } } /* end for */ -if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */ + +if (nargs <= 0) /* need at least 1 */ + return SCPE_2FARG; if ((fpin = fopen (do_arg[0], "r")) == NULL) { /* file failed to open? */ if (flag == 0) /* cmd line file? */ fprintf (stderr, "Can't open file %s\n", do_arg[0]); @@ -834,27 +873,32 @@ if ((fpin = fopen (do_arg[0], "r")) == NULL) { /* file failed to open? else return SCPE_OPENERR; /* return failure */ } -if (flag < 1) flag = 1; /* start at level 1 */ +if (flag < 1) /* start at level 1 */ + flag = 1; do { ocptr = cptr = sim_brk_getact (cbuf, CBUFSIZE); /* get bkpt action */ if (!ocptr) /* no pending action? */ ocptr = cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */ - sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg); /* substitute args */ + sub_args (cbuf, gbuf, CBUFSIZE, do_arg); /* substitute args */ if (cptr == NULL) { /* EOF? */ stat = SCPE_OK; /* set good return */ break; } - 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); + if (*cptr == 0) /* ignore blank */ + continue; + if (echo) /* echo if -v */ + printf("do> %s\n", cptr); + 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 */ isdo = FALSE; if (cmdp = find_cmd (gbuf)) { /* lookup command */ isdo = (cmdp->action == &do_cmd); if (isdo) { /* DO command? */ - if (flag >= DO_NEST_LVL) stat = SCPE_NEST; /* nest too deep? */ + 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 */ @@ -876,10 +920,11 @@ do { if ((staying || !interactive) && /* report error if staying */ (stat >= SCPE_BASE)) { /* or in cmdline file */ 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_log) + fprintf (sim_log, "%s\n", scp_error_messages[stat - SCPE_BASE]); } - if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); + if (sim_vm_post != NULL) + (*sim_vm_post) (TRUE); } while (staying); fclose (fpin); /* close file */ @@ -892,24 +937,34 @@ return stat; instr = input string tmpbuf = temp buffer maxstr = min (len (instr), len (tmpbuf)) - nargs = number of arguments do_arg[10] = arguments + + Token "%0" represents the command file name. + + The input sequence "\%" represents a literal "%", and "\\" represents a + literal "\". All other character combinations are rendered literally. + + Omitted parameters result in null-string substitutions. */ -void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]) +void sub_args (char *instr, char *tmpbuf, int32 maxstr, char *do_arg[]) { char *ip, *op, *ap, *oend = tmpbuf + maxstr - 2; for (ip = instr, op = tmpbuf; *ip && (op < oend); ) { - if ((*ip == '\\') && (ip[1] == '%')) { /* \% = literal % */ - ip++; /* skip \ */ - if (*ip) *op++ = *ip++; /* copy next */ + if ((ip [0] == '\\') && /* literal escape? */ + ((ip [1] == '%') || (ip [1] == '\\'))) { /* and followed by '%' or '\'? */ + ip++; /* skip '\' */ + *op++ = *ip++; /* copy escaped char */ } else if ((*ip == '%') && /* %n = sub */ - ((ip[1] >= '1') && (ip[1] <= ('0'+ nargs - 1)))) { + ((ip[1] >= '0') && (ip[1] <= ('9')))) { ap = do_arg[ip[1] - '0']; ip = ip + 2; - while (*ap && (op < oend)) *op++ = *ap++; /* copy the argument */ + if (ap) { /* non-null arg? */ + while (*ap && (op < oend)) /* copy the argument */ + *op++ = *ap++; + } } else *op++ = *ip++; /* literal character */ } @@ -936,28 +991,37 @@ 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 */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; 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 (!rptr) /* not there */ + return SCPE_NXREG; if (*gptr == '[') { /* subscript? */ - if (rptr->depth <= 1) return SCPE_ARG; /* array register? */ + if (rptr->depth <= 1) /* array register? */ + return SCPE_ARG; idx = (uint32) strtotv (++gptr, &tptr, 10); /* convert index */ - if ((gptr == tptr) || (*tptr++ != ']')) return SCPE_ARG; + 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 */ +if (idx >= rptr->depth) /* validate subscript */ + return SCPE_SUB; +if (*gptr != 0) /* more? must be search */ + get_glyph (gptr, gbuf, 0); else { - if (*cptr == 0) return SCPE_2FARG; /* must be more */ + if (*cptr == 0) /* must be more */ + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get search cond */ } -if (*cptr != 0) return SCPE_2MARG; /* must be done */ +if (*cptr != 0) /* must be done */ + return SCPE_2MARG; 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 */ +if (test_search (val, &sim_stab)) /* test condition */ + return SCPE_OK; return SCPE_AFAIL; /* condition fails */ } @@ -1006,7 +1070,8 @@ static C1TAB set_unit_tab[] = { }; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get glob/dev/unit */ if (dptr = find_dev (gbuf)) { /* device match? */ @@ -1015,47 +1080,58 @@ if (dptr = find_dev (gbuf)) { /* device match? */ lvl = MTAB_VDV; /* device match */ } else if (dptr = find_unit (gbuf, &uptr)) { /* unit match? */ - if (uptr == NULL) return SCPE_NXUN; /* invalid unit */ + if (uptr == NULL) /* invalid unit */ + return SCPE_NXUN; 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 (*cptr == 0) /* must be more */ + return SCPE_2FARG; while (*cptr != 0) { /* do all mods */ cptr = get_glyph (svptr = cptr, gbuf, ','); /* get modifier */ - if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ + if (cvptr = strchr (gbuf, '=')) /* = value? */ + *cvptr++ = 0; 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 & 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)) + if (cvptr && (mptr->mask & MTAB_NC)) { get_glyph_nc (svptr, gbuf, ','); + if (cvptr = strchr (gbuf, '=')) + *cvptr++ = 0; + } r = mptr->valid (uptr, mptr->match, cvptr, mptr->desc); - if (r != SCPE_OK) return r; + 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 if (!mptr->desc) /* value desc? */ + break; +// 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) /* = value? */ + return SCPE_ARG; else *((int32 *) mptr->desc) = mptr->match; } /* end if xtd */ else { /* old style */ - if (cvptr) return SCPE_ARG; /* = value? */ + if (cvptr) /* = value? */ + return SCPE_ARG; 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? */ + if ((mptr->valid) && /* invalid? */ + ((r = mptr->valid (uptr, mptr->match, cvptr, mptr->desc)) != SCPE_OK)) + return r; uptr->flags = (uptr->flags & ~(mptr->mask)) | (mptr->match & mptr->mask); /* set new value */ } /* end else xtd */ @@ -1065,9 +1141,11 @@ while (*cptr != 0) { /* do all mods */ 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; + if (r != SCPE_OK) + return r; } - else if (!dptr->modifiers) return SCPE_NOPARAM; /* no modifiers? */ + else if (!dptr->modifiers) /* no modifiers? */ + return SCPE_NOPARAM; else return SCPE_NXPAR; } /* end if no mat */ } /* end while */ @@ -1079,7 +1157,8 @@ return SCPE_OK; /* done all */ 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; } @@ -1087,7 +1166,8 @@ 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; } @@ -1096,7 +1176,8 @@ return NULL; t_stat set_dev_radix (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { -if (cptr) return SCPE_ARG; +if (cptr) + return SCPE_ARG; dptr->dradix = flag & 037; return SCPE_OK; } @@ -1108,15 +1189,18 @@ t_stat set_dev_enbdis (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) UNIT *up; uint32 i; -if (cptr) return SCPE_ARG; -if ((dptr->flags & DEV_DISABLE) == 0) return SCPE_NOFNC;/* allowed? */ +if (cptr) + return SCPE_ARG; +if ((dptr->flags & DEV_DISABLE) == 0) /* allowed? */ + return SCPE_NOFNC; 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 */ + if (dptr->flags & DEV_DIS) /* already dsb? ok */ + return SCPE_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)) @@ -1124,7 +1208,8 @@ else { } dptr->flags = dptr->flags | DEV_DIS; /* disable */ } -if (dptr->reset) return dptr->reset (dptr); /* reset device */ +if (dptr->reset) /* reset device */ + return dptr->reset (dptr); else return SCPE_OK; } @@ -1132,12 +1217,16 @@ 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 */ +if (cptr) + return SCPE_ARG; +if (!(uptr->flags & UNIT_DISABLE)) /* allowed? */ + return SCPE_NOFNC; +if (flag) /* enb? enable */ + uptr->flags = uptr->flags & ~UNIT_DIS; else { if ((uptr->flags & UNIT_ATT) || /* dsb */ - sim_is_active (uptr)) return SCPE_NOFNC; /* more tests */ + sim_is_active (uptr)) /* more tests */ + return SCPE_NOFNC; uptr->flags = uptr->flags | UNIT_DIS; /* disable */ } return SCPE_OK; @@ -1150,7 +1239,8 @@ t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) char gbuf[CBUFSIZE]; DEBTAB *dep; -if ((dptr->flags & DEV_DEBUG) == 0) return SCPE_NOFNC; +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? */ @@ -1159,17 +1249,20 @@ if (cptr == NULL) { /* no arguments? */ } return SCPE_OK; } -if (dptr->debflags == NULL) return SCPE_ARG; /* must have table */ +if (dptr->debflags == NULL) /* must have table */ + return SCPE_ARG; 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; + 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? */ + if (dep->mask == 0) /* no match? */ + return SCPE_ARG; } /* end while */ return SCPE_OK; } @@ -1181,14 +1274,16 @@ 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 (!cptr) /* error? */ + return r; 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); + if (sim_log) + show_cmd_fi (sim_log, flag, cptr); } return r; } @@ -1232,7 +1327,8 @@ static SHTAB show_unit_tab[] = { }; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; 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); @@ -1243,8 +1339,10 @@ if (dptr = find_dev (gbuf)) { /* device match? */ 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? */ + if (uptr == NULL) /* invalid unit */ + return SCPE_NXUN; + if (uptr->flags & UNIT_DIS) /* disabled? */ + return SCPE_UDIS; shtb = show_unit_tab; /* global table */ lvl = MTAB_VUN; /* unit match */ } @@ -1255,20 +1353,25 @@ if (*cptr == 0) { /* now eol? */ show_device (ofile, dptr, 0): show_unit (ofile, dptr, uptr, -1); } -if (dptr->modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */ +if (dptr->modifiers == NULL) /* any modifiers? */ + return SCPE_NOPARAM; while (*cptr != 0) { /* do all mods */ cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ - if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ + if (cvptr = strchr (gbuf, '=')) /* = value? */ + *cvptr++ = 0; 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; + (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 */ @@ -1285,7 +1388,8 @@ 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; } @@ -1304,17 +1408,24 @@ if (qdisable (dptr)) { /* disabled? */ } 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++; + 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"); +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 (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? */ +if (flag) /* dev only? */ + return SCPE_OK; for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ uptr = dptr->units + j; if ((uptr->flags & UNIT_DIS) == 0) @@ -1327,15 +1438,18 @@ t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) { int32 u = uptr - dptr->units; -if (flag > 1) fprintf (st, " %s%d", sim_dname (dptr), u); -else if (flag < 0) fprintf (st, "%s%d", sim_dname (dptr), u); +if (flag > 1) + fprintf (st, " %s%d", sim_dname (dptr), u); +else if (flag < 0) + fprintf (st, "%s%d", sim_dname (dptr), u); if (uptr->flags & UNIT_FIX) { fprintf (st, ", "); fprint_capac (st, dptr, uptr); } if (uptr->flags & UNIT_ATT) { fprintf (st, ", attached to %s", uptr->filename); - if (uptr->flags & UNIT_RO) fprintf (st, ", read only"); + if (uptr->flags & UNIT_RO) + fprintf (st, ", read only"); } else if (uptr->flags & UNIT_ATTABLE) fprintf (st, ", not attached"); @@ -1351,9 +1465,11 @@ t_addr mval = kval * kval; t_addr psize = uptr->capac; char scale, width; -if ((dptr->dwidth / dptr->aincr) > 8) width = 'W'; +if ((dptr->dwidth / dptr->aincr) > 8) + width = 'W'; else width = 'B'; -if (uptr->capac < (kval * 10)) scale = 0; +if (uptr->capac < (kval * 10)) + scale = 0; else if (uptr->capac < (mval * 10)) { scale = 'K'; psize = psize / kval; @@ -1363,7 +1479,8 @@ else { psize = psize / mval; } fprint_val (st, (t_value) psize, 10, T_ADDR_W, PV_LEFT); -if (scale) fputc (scale, st); +if (scale) + fputc (scale, st); fputc (width, st); return; } @@ -1374,10 +1491,13 @@ t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { int32 vmaj = SIM_MAJOR, vmin = SIM_MINOR, vpat = SIM_PATCH, vdelt = SIM_DELTA; -if (cptr && (*cptr != 0)) return SCPE_2MARG; +if (cptr && (*cptr != 0)) + return SCPE_2MARG; fprintf (st, "%s simulator V%d.%d-%d", sim_name, vmaj, vmin, vpat); -if (vdelt) fprintf (st, "(%d)", vdelt); -if (flag) fprintf (st, " [%s, %s, %s]", sim_si64, sim_sa64, sim_snet); +if (vdelt) + fprintf (st, "(%d)", vdelt); +if (flag) + fprintf (st, " [%s, %s, %s]", sim_si64, sim_sa64, sim_snet); fprintf (st, "\n"); return SCPE_OK; } @@ -1387,7 +1507,8 @@ t_stat show_config (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, char int32 i; DEVICE *dptr; -if (cptr && (*cptr != 0)) return SCPE_2MARG; +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); @@ -1399,7 +1520,8 @@ t_stat show_log_names (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, c int32 i; DEVICE *dptr; -if (cptr && (*cptr != 0)) return SCPE_2MARG; +if (cptr && (*cptr != 0)) + return SCPE_2MARG; for (i = 0; (dptr = sim_devices[i]) != NULL; i++) show_dev_logicals (st, dptr, NULL, 1, cptr); return SCPE_OK; @@ -1407,8 +1529,10 @@ return SCPE_OK; t_stat show_dev_logicals (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { -if (dptr->lname) fprintf (st, "%s -> %s\n", dptr->lname, dptr->name); -else if (!flag) fputs ("no logical name assigned\n", st); +if (dptr->lname) + fprintf (st, "%s -> %s\n", dptr->lname, dptr->name); +else if (!flag) + fputs ("no logical name assigned\n", st); return SCPE_OK; } @@ -1418,7 +1542,8 @@ DEVICE *dptr; UNIT *uptr; int32 accum; -if (cptr && (*cptr != 0)) return SCPE_2MARG; +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); @@ -1428,7 +1553,8 @@ fprintf (st, "%s event queue status, time = %.0f\n", sim_name, sim_time); accum = 0; for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) { - if (uptr == &sim_step_unit) fprintf (st, " Step timer"); + 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", @@ -1443,7 +1569,8 @@ return SCPE_OK; t_stat show_time (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { -if (cptr && (*cptr != 0)) return SCPE_2MARG; +if (cptr && (*cptr != 0)) + return SCPE_2MARG; fprintf (st, "Time:\t%.0f\n", sim_time); return SCPE_OK; } @@ -1452,7 +1579,8 @@ 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; } @@ -1469,13 +1597,16 @@ 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); + 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); + if (any) + fputc (';', st); fputs (dep->name, st); any = 1; } @@ -1494,7 +1625,8 @@ 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)) /* now eol? */ + return SCPE_2MARG; for (i = 0; (dptr = sim_devices[i]) != NULL; i++) show_dev_modifiers (st, dptr, NULL, flag, cptr); return SCPE_OK; @@ -1510,18 +1642,22 @@ 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); + 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"); + 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"); + if (any++) + fprintf (st, ", ENABLED, DISABLED"); else fprintf (st, "%s\tENABLED, DISABLED", sim_dname (dptr)); } if (any) fprintf (st, "\n"); @@ -1538,7 +1674,8 @@ t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) { MTAB *mptr; -if (dptr->modifiers == NULL) return SCPE_OK; +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)): @@ -1553,19 +1690,20 @@ return SCPE_OK; t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, char *cptr, int32 flag) { -t_value val; +//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); - } +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); +// } else fputs (mptr->pstring, st); -if (flag && !((mptr->mask & MTAB_XTD) && - (mptr->mask & MTAB_NMO))) fputc ('\n', st); +if (flag && !((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_NMO))) + fputc ('\n', st); return SCPE_OK; } @@ -1586,10 +1724,13 @@ t_stat r; t_addr lo, hi, max = uptr->capac - 1; int32 cnt; -if (sim_brk_types == 0) return SCPE_NOFNC; -if ((dptr == NULL) || (uptr == NULL)) return SCPE_IERR; +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 */ + if (flg != SSH_ST) /* only on SET */ + return SCPE_ARG; *aptr++ = 0; /* separate strings */ } if (*cptr == 0) { /* no argument? */ @@ -1599,24 +1740,29 @@ if (*cptr == 0) { /* no argument? */ 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 == NULL) + return SCPE_ARG; if (*tptr == '[') { cnt = (int32) strtotv (tptr + 1, &t1ptr, 10); - if ((tptr == t1ptr) || (*t1ptr != ']') || - (flg != SSH_ST)) return SCPE_ARG; + if ((tptr == t1ptr) || (*t1ptr != ']') || (flg != SSH_ST)) + return SCPE_ARG; tptr = t1ptr + 1; } else cnt = 0; - if (*tptr != 0) return SCPE_ARG; + 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); + 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) { r = ssh_break_one (st, flg, lo, cnt, aptr); - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; } } } @@ -1657,13 +1803,18 @@ char gbuf[CBUFSIZE]; DEVICE *dptr; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return (reset_all (0)); /* reset(cr) */ +if (*cptr == 0) /* reset(cr) */ + return (reset_all (0)); 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)); +if (*cptr != 0) /* now eol? */ + return SCPE_2MARG; +if (strcmp (gbuf, "ALL") == 0) + return (reset_all (0)); dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found it? */ -if (dptr->reset != NULL) return dptr->reset (dptr); +if (dptr == NULL) /* found it? */ + return SCPE_NXDEV; +if (dptr->reset != NULL) + return dptr->reset (dptr); else return SCPE_OK; } @@ -1682,12 +1833,14 @@ 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 (reason != SCPE_OK) + return reason; } } return SCPE_OK; @@ -1725,10 +1878,12 @@ FILE *loadfile; t_stat reason; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; 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; +if (loadfile == NULL) + return SCPE_OPENERR; GET_SWITCHES (cptr); /* get switches */ reason = sim_load (loadfile, cptr, gbuf, flag); /* load or dump */ fclose (loadfile); @@ -1748,16 +1903,21 @@ UNIT *uptr; t_stat r; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* now eol? */ +if (*cptr == 0) /* now eol? */ + return SCPE_2FARG; 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 == NULL) /* found dev? */ + return SCPE_NXDEV; +if (uptr == NULL) /* valid unit? */ + return SCPE_NXUN; if (uptr->flags & UNIT_ATT) { /* already attached? */ r = scp_detach_unit (dptr, uptr); /* detach it */ - if (r != SCPE_OK) return r; /* error? */ + if (r != SCPE_OK) /* error? */ + return r; } sim_trim_endspc (cptr); /* trim trailing spc */ return scp_attach_unit (dptr, uptr, cptr); /* attach */ @@ -1778,12 +1938,17 @@ 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 ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; -if (dptr->flags & DEV_RAWONLY) return SCPE_NOFNC; /* raw mode only? */ +if (uptr->flags & UNIT_DIS) /* disabled? */ + return SCPE_UDIS; +if (!(uptr->flags & UNIT_ATTABLE)) /* not attachable? */ + return SCPE_NOATT; +if ((dptr = find_dev_from_unit (uptr)) == NULL) + return SCPE_NOATT; +if (dptr->flags & DEV_RAWONLY) /* raw mode only? */ + return SCPE_NOFNC; uptr->filename = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc name buf */ -if (uptr->filename == NULL) return SCPE_MEM; +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? */ @@ -1792,7 +1957,8 @@ if (sim_switches & SWMASK ('R')) { /* read 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)); + if (!sim_quiet) + printf ("%s: unit is read only\n", sim_dname (dptr)); } else { /* normal */ uptr->fileref = sim_fopen (cptr, "rb+"); /* open r/w */ @@ -1804,7 +1970,8 @@ else { /* normal */ 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)); + if (!sim_quiet) + printf ("%s: unit is read only\n", sim_dname (dptr)); } else { /* doesn't exist */ if (sim_switches & SWMASK ('E')) /* must exist? */ @@ -1852,13 +2019,18 @@ DEVICE *dptr; UNIT *uptr; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; 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)); +if (*cptr != 0) /* now eol? */ + return SCPE_2MARG; +if (strcmp (gbuf, "ALL") == 0) + return (detach_all (0, FALSE)); dptr = find_unit (gbuf, &uptr); /* locate unit */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ +if (dptr == NULL) /* found dev? */ + return SCPE_NXDEV; +if (uptr == NULL) /* valid unit? */ + return SCPE_NXUN; return scp_detach_unit (dptr, uptr); /* detach */ } @@ -1871,7 +2043,8 @@ return scp_detach_unit (dptr, uptr); /* detach */ status = error status Note that during shutdown, detach routines for non-attachable devices - will be called. These routines can implement simulator shutdown. + will be called. These routines can implement simulator shutdown. Error + returns during shutdown are ignored. */ t_stat detach_all (int32 start, t_bool shutdown) @@ -1881,7 +2054,8 @@ DEVICE *dptr; UNIT *uptr; t_stat r; -if ((start < 0) || (start > 1)) return SCPE_IERR; +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; @@ -1889,7 +2063,9 @@ for (i = start; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ (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; + + if ((r != SCPE_OK) && !shutdown) /* error and not shutting down? */ + return r; /* bail out now with error status */ } } } @@ -1900,7 +2076,8 @@ return SCPE_OK; t_stat scp_detach_unit (DEVICE *dptr, UNIT *uptr) { -if (dptr->detach != NULL) return dptr->detach (uptr); /* device routine? */ +if (dptr->detach != NULL) /* device routine? */ + return dptr->detach (uptr); return detach_unit (uptr); /* no, standard */ } @@ -1910,17 +2087,23 @@ 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 ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK; +if (uptr == NULL) + return SCPE_IERR; +if (!(uptr->flags & UNIT_ATTABLE)) /* attachable? */ + return SCPE_NOATT; +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; +if ((dptr = find_dev_from_unit (uptr)) == NULL) + return SCPE_OK; if (uptr->flags & UNIT_BUF) { uint32 cap = (uptr->hwmark + dptr->aincr - 1) / dptr->aincr; if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { - if (!sim_quiet) printf ("%s: writing buffer to file\n", sim_dname (dptr)); + 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 (ferror (uptr->fileref)) + perror ("I/O error"); } if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ free (uptr->filebuf); /* free buf */ @@ -1931,7 +2114,8 @@ if (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; +if (fclose (uptr->fileref) == EOF) + return SCPE_IOERR; return SCPE_OK; } @@ -1946,15 +2130,20 @@ char gbuf[CBUFSIZE]; DEVICE *dptr; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* now eol? */ +if (*cptr == 0) /* now eol? */ + return SCPE_2FARG; dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ +if (dptr == NULL) /* found dev? */ + return SCPE_NXDEV; 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 */ +if (*cptr != 0) /* must be eol */ + return SCPE_2MARG; +if (find_dev (gbuf)) /* name in use */ + return SCPE_ARG; deassign_device (dptr); /* release current */ return assign_device (dptr, gbuf); } @@ -1962,7 +2151,8 @@ return assign_device (dptr, gbuf); t_stat assign_device (DEVICE *dptr, char *cptr) { dptr->lname = (char *) calloc (CBUFSIZE, sizeof (char)); -if (dptr->lname == NULL) return SCPE_MEM; +if (dptr->lname == NULL) + return SCPE_MEM; strncpy (dptr->lname, cptr, CBUFSIZE); return SCPE_OK; } @@ -1978,17 +2168,21 @@ char gbuf[CBUFSIZE]; DEVICE *dptr; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ +if (*cptr != 0) /* now eol? */ + return SCPE_2MARG; dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ +if (dptr == NULL) /* found dev? */ + return SCPE_NXDEV; return deassign_device (dptr); } t_stat deassign_device (DEVICE *dptr) { -if (dptr->lname) free (dptr->lname); +if (dptr->lname) + free (dptr->lname); dptr->lname = NULL; return SCPE_OK; } @@ -2010,9 +2204,11 @@ t_stat save_cmd (int32 flag, char *cptr) FILE *sfile; t_stat r; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; sim_trim_endspc (cptr); -if ((sfile = sim_fopen (cptr, "wb")) == NULL) return SCPE_OPENERR; +if ((sfile = sim_fopen (cptr, "wb")) == NULL) + return SCPE_OPENERR; r = sim_save (sfile); fclose (sfile); return r; @@ -2044,7 +2240,8 @@ 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 */ + if (dptr->lname) /* [V3.0] logical name */ + fputs (dptr->lname, sfile); fputc ('\n', sfile); WRITE_I (dptr->flags); /* [V2.10] flags */ for (j = 0; j < dptr->numunits; j++) { @@ -2058,7 +2255,8 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ WRITE_I (uptr->u6); WRITE_I (uptr->flags); /* [V2.10] flags */ WRITE_I (uptr->capac); /* [V3.5] capacity */ - if (uptr->flags & UNIT_ATT) fputs (uptr->filename, sfile); + if (uptr->flags & UNIT_ATT) + fputs (uptr->filename, sfile); fputc ('\n', sfile); if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) == UNIT_FIX) && (dptr->examine != NULL) && @@ -2074,7 +2272,8 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ 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 (r != SCPE_OK) + return r; if (val) zeroflg = FALSE; SZ_STORE (sz, val, mbuf, l); } /* end for l */ @@ -2123,9 +2322,11 @@ FILE *rfile; t_stat r; GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; sim_trim_endspc (cptr); -if ((rfile = sim_fopen (cptr, "rb")) == NULL) return SCPE_OPENERR; +if ((rfile = sim_fopen (cptr, "rb")) == NULL) + return SCPE_OPENERR; r = sim_rest (rfile); fclose (rfile); return r; @@ -2153,8 +2354,10 @@ REG *rptr; READ_S (buf); /* [V2.5+] read version */ v35 = v32 = FALSE; -if (strcmp (buf, save_vercur) == 0) v35 = v32 = TRUE; /* version 3.5? */ -else if (strcmp (buf, save_ver32) == 0) v32 = TRUE; /* version 3.2? */ +if (strcmp (buf, save_vercur) == 0) /* version 3.5? */ + v35 = v32 = TRUE; +else if (strcmp (buf, save_ver32) == 0) /* version 3.2? */ + v32 = TRUE; else if (strcmp (buf, save_ver30) != 0) { /* version 3.0? */ printf ("Invalid file version: %s\n", buf); return SCPE_INCOMP; @@ -2186,7 +2389,8 @@ 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 (buf[0] == 0) /* last? */ + break; if ((dptr = find_dev (buf)) == NULL) { /* locate device */ printf ("Invalid device name: %s\n", buf); return SCPE_INCOMP; @@ -2194,16 +2398,19 @@ for ( ;; ) { /* device loop */ READ_S (buf); /* [V3.0+] logical name */ deassign_device (dptr); /* delete old name */ if ((buf[0] != 0) && - ((r = assign_device (dptr, buf)) != SCPE_OK)) return r; + ((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 */ + 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 */ sim_switches = SIM_SW_REST; /* flag rstr, clr RO */ READ_I (unitno); /* unit number */ - if (unitno < 0) break; /* end units? */ + if (unitno < 0) /* end units? */ + break; if ((uint32) unitno >= dptr->numunits) { /* too big? */ printf ("Invalid unit number: %s%d\n", sim_dname (dptr), unitno); return SCPE_INCOMP; @@ -2211,7 +2418,8 @@ for ( ;; ) { /* device loop */ READ_I (time); /* event time */ uptr = (dptr->units) + unitno; sim_cancel (uptr); - if (time > 0) sim_activate (uptr, time - 1); + if (time > 0) + sim_activate (uptr, time - 1); READ_I (uptr->u3); /* device specific */ READ_I (uptr->u4); READ_I (uptr->u5); /* [V3.0+] more dev spec */ @@ -2221,24 +2429,28 @@ for ( ;; ) { /* device loop */ if (v35) { /* [V3.5+] capacity */ READ_I (uptr->capac); } - if (!v32) flg = ((flg & UNIT_UFMASK_31) << (UNIT_V_UF - UNIT_V_UF_31)) | - (flg & ~UNIT_UFMASK_31); /* [V3.2+] flags moved */ + 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 */ - 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; - } + if ((uptr->flags & UNIT_ATT) && /* unit currently attached? */ + !(dptr->flags & DEV_NET)) { /* and not a net device? */ + r = scp_detach_unit (dptr, uptr); /* detach it */ + if (r != SCPE_OK) + return r; + } + if ((buf[0] != '\0') && /* unit to be reattached? */ + !(dptr->flags & DEV_NET) && /* and not a net device? */ + ((uptr->flags & UNIT_ATTABLE) || /* and unit is attachable */ + (dptr->attach != NULL))) { /* or VM attach routine provided? */ + uptr->flags = uptr->flags & ~UNIT_DIS; /* ensure device is enabled */ + if (flg & UNIT_RO) /* [V2.10+] saved flgs & RO? */ + sim_switches |= SWMASK ('R'); /* RO attach */ + r = scp_attach_unit (dptr, uptr, buf); /* reattach unit */ + if (r != SCPE_OK) + return r; } READ_I (high); /* memory capacity */ if (high > 0) { /* [V2.5+] any memory? */ @@ -2266,14 +2478,18 @@ for ( ;; ) { /* device loop */ return SCPE_MEM; for (k = 0; k < high; ) { /* loop thru mem */ READ_I (blkcnt); /* block count */ - if (blkcnt < 0) limit = -blkcnt; /* compressed? */ + if (blkcnt < 0) /* compressed? */ + limit = -blkcnt; else limit = sim_fread (mbuf, sz, blkcnt, rfile); - if (limit <= 0) return SCPE_IOERR; /* invalid or err? */ + if (limit <= 0) /* invalid or err? */ + return SCPE_IOERR; for (j = 0; j < limit; j++, k = k + (dptr->aincr)) { - if (blkcnt < 0) val = 0; /* compressed? */ + if (blkcnt < 0) /* compressed? */ + val = 0; else SZ_LOAD (sz, val, mbuf, j); /* saved value */ r = dptr->deposit (val, k, uptr, SIM_SW_REST); - if (r != SCPE_OK) return r; + if (r != SCPE_OK) + return r; } /* end for j */ } /* end for k */ free (mbuf); /* dealloc buffer */ @@ -2281,7 +2497,8 @@ for ( ;; ) { /* device loop */ } /* end unit loop */ for ( ;; ) { /* register loop */ READ_S (buf); /* read reg name */ - if (buf[0] == 0) break; /* last? */ + if (buf[0] == 0) /* last? */ + break; 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); @@ -2331,22 +2548,26 @@ sim_step = 0; if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */ if (*cptr != 0) { /* argument? */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (*cptr != 0) return SCPE_2MARG; /* should be end */ + if (*cptr != 0) /* should be end */ + return SCPE_2MARG; 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);/* parse PC */ if ((tptr == gbuf) || (*tptr != 0) || /* error? */ - (pcv > width_mask[sim_PC->width])) return SCPE_ARG; + (pcv > width_mask[sim_PC->width])) + return SCPE_ARG; put_rval (sim_PC, 0, pcv); } if ((flag == RU_RUN) && /* run? */ - ((r = run_boot_prep ()) != SCPE_OK)) return r; /* reset sim */ + ((r = run_boot_prep ()) != SCPE_OK)) /* reset sim */ + return r; } else if (flag == RU_STEP) { /* step */ if (*cptr != 0) { /* argument? */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (*cptr != 0) return SCPE_2MARG; /* should be end */ + if (*cptr != 0) /* should be end */ + return SCPE_2MARG; sim_step = (int32) get_uint (gbuf, 10, INT_MAX, &r); if ((r != SCPE_OK) || (sim_step <= 0)) /* error? */ return SCPE_ARG; @@ -2355,29 +2576,37 @@ else if (flag == RU_STEP) { /* step */ } else if (flag == RU_BOOT) { /* boot */ - if (*cptr == 0) return SCPE_2FARG; /* must be more */ + if (*cptr == 0) /* must be more */ + return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (*cptr != 0) return SCPE_2MARG; /* should be end */ + if (*cptr != 0) /* should be end */ + return SCPE_2MARG; 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 (dptr == NULL) /* found dev? */ + return SCPE_NXDEV; + if (uptr == NULL) /* valid unit? */ + return SCPE_NXUN; + if (dptr->boot == NULL) /* can it boot? */ + return SCPE_NOFNC; + if (uptr->flags & UNIT_DIS) /* disabled? */ + return SCPE_UDIS; if ((uptr->flags & UNIT_ATTABLE) && /* if attable, att? */ - !(uptr->flags & UNIT_ATT)) return SCPE_UNATT; + !(uptr->flags & UNIT_ATT)) + return SCPE_UNATT; unitno = (int32) (uptr - dptr->units); /* recover unit# */ - if ((r = run_boot_prep ()) != SCPE_OK) return r; /* reset sim */ + if ((r = run_boot_prep ()) != SCPE_OK) /* reset sim */ + return r; if ((r = dptr->boot (unitno, dptr)) != SCPE_OK) /* boot device */ return r; } -else if (flag != RU_CONT) return SCPE_IERR; /* must be cont */ +else if (flag != RU_CONT) /* must be cont */ + return SCPE_IERR; for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* reposition all */ for (j = 0; j < dptr->numunits; j++) { /* seq devices */ uptr = dptr->units + j; - if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == - (UNIT_ATT + UNIT_SEQ)) + if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == (UNIT_ATT + UNIT_SEQ)) sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); } } @@ -2393,7 +2622,8 @@ 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 */ +if (sim_step) /* set step timer */ + sim_activate (&sim_step_unit, sim_step); sim_throt_sched (); /* set throttle */ sim_is_running = 1; /* flag running */ sim_brk_clract (); /* defang actions */ @@ -2411,8 +2641,10 @@ if (sim_clock_queue != NULL) { /* update sim 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 */ +if (sim_log) /* flush console log */ + fflush (sim_log); +if (sim_deb) /* flush debug log */ + fflush (sim_deb); 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; @@ -2428,7 +2660,8 @@ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files printf ("\n"); #endif fprint_stopped (stdout, r); /* print msg */ -if (sim_log) fprint_stopped (sim_log, r); /* log if enabled */ +if (sim_log) /* log if enabled */ + fprint_stopped (sim_log, r); return SCPE_OK; } @@ -2440,7 +2673,7 @@ sim_interval = 0; /* reset queue */ sim_time = sim_rtime = 0; noqueue_time = 0; sim_clock_queue = NULL; -return reset_all_p (0); +return reset_all (0); } /* Print stopped message */ @@ -2456,14 +2689,16 @@ if (v >= SCPE_BASE) fprintf (st, "\n%s, %s: ", scp_error_messages[v - SCPE_BASE], pc->name); else fprintf (st, "\n%s, %s: ", sim_stop_messages[v], pc->name); pcval = get_rval (pc, 0); -if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, dptr, (t_addr) pcval); +if (sim_vm_fprint_addr) + sim_vm_fprint_addr (st, dptr, (t_addr) pcval); else fprint_val (st, pcval, pc->radix, pc->width, pc->flags & REG_FMT); if ((dptr != NULL) && (dptr->examine != NULL)) { - for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; + 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, " ("); @@ -2536,13 +2771,18 @@ 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 */ +if (flag == EX_E) /* extra for EX */ + opt = opt | CMD_OPT_OF; 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? */ +if (!cptr) /* error? */ + return reason; +if (*cptr == 0) /* must be more */ + return SCPE_2FARG; +if (sim_dfunit == NULL) /* got a unit? */ + return SCPE_NXUN; cptr = get_glyph (cptr, gbuf, 0); /* get list */ -if ((flag == EX_D) && (*cptr == 0)) return SCPE_2FARG; /* deposit needs more */ +if ((flag == EX_D) && (*cptr == 0)) /* deposit needs more */ + return SCPE_2FARG; ofile = sim_ofile? sim_ofile: stdout; /* no ofile? use stdout */ for (gptr = gbuf, reason = SCPE_OK; @@ -2550,8 +2790,10 @@ for (gptr = gbuf, reason = SCPE_OK; 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; + 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, @@ -2565,18 +2807,22 @@ for (gptr = gbuf, reason = SCPE_OK; low = high = 0; if ((*tptr == '-') || (*tptr == ':')) { highr = find_reg (tptr + 1, &tptr, tdptr); - if (highr == NULL) return SCPE_NXREG; + if (highr == NULL) + return SCPE_NXREG; } else { highr = lowr; if (*tptr == '[') { - if (lowr->depth <= 1) return SCPE_ARG; + 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 == NULL) + return SCPE_ARG; } } - if (*tptr && (*tptr++ != ',')) 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; @@ -2585,12 +2831,15 @@ for (gptr = gbuf, reason = SCPE_OK; 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; + 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 */ +if (sim_ofile) /* close output file */ + fclose (sim_ofile); return reason; } @@ -2608,24 +2857,31 @@ uint32 idx; t_value val; REG *rptr; -if ((lowr == NULL) || (highr == NULL)) return SCPE_IERR; -if (lowr > highr) return SCPE_ARG; +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; + (rptr->flags & REG_HIDDEN)) + continue; for (idx = lows; idx <= highs; idx++) { - if (idx >= rptr->depth) return SCPE_SUB; + if (idx >= rptr->depth) + return SCPE_SUB; val = get_rval (rptr, idx); - if (schptr && !test_search (val, schptr)) continue; + 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 (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 (reason != SCPE_OK) + return reason; } } } @@ -2638,25 +2894,30 @@ t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, t_addr i, mask; t_stat reason; -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ +if (uptr->flags & UNIT_DIS) /* disabled? */ + return SCPE_UDIS; mask = (t_addr) width_mask[dptr->awidth]; -if ((low > mask) || (high > mask) || (low > high)) return SCPE_ARG; +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 (reason != SCPE_OK) /* return if error */ + return reason; 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 (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; + if (reason > SCPE_OK) + return reason; } i = i + (1 - reason); /* incr */ } @@ -2680,17 +2941,21 @@ 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]:\t", rptr->name, idx); +if (rptr == NULL) + return SCPE_IERR; +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; +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_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, "\t"); +if (flag & EX_I) + fprintf (ofile, "\t"); else fprintf (ofile, "\n"); return SCPE_OK; } @@ -2718,7 +2983,8 @@ if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { uptr = ((UNIT *) rptr->loc) + idx; #if defined (USE_INT64) - if (sz <= sizeof (uint32)) val = *((uint32 *) uptr); + if (sz <= sizeof (uint32)) + val = *((uint32 *) uptr); else val = *((t_uint64 *) uptr); #else val = *((uint32 *) uptr); @@ -2759,27 +3025,34 @@ t_value val, mask; int32 rdx; char *tptr, gbuf[CBUFSIZE]; -if ((cptr == NULL) || (rptr == NULL)) return SCPE_IERR; -if (rptr->flags & REG_RO) return SCPE_RO; +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 */ + if (sim_log) + fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); + if (cptr == NULL) /* force exit */ + return 1; + if (*cptr == 0) /* success */ + return SCPE_OK; } 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_dflt_dev, cptr, &tptr); - if ((tptr == cptr) || (*tptr != 0) || - (val > mask)) return SCPE_ARG; + 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; + if (r != SCPE_OK) + return SCPE_ARG; } -if ((rptr->flags & REG_NZ) && (val == 0)) return SCPE_ARG; +if ((rptr->flags & REG_NZ) && (val == 0)) + return SCPE_ARG; put_rval (rptr, idx, val); return SCPE_OK; } @@ -2806,12 +3079,14 @@ UNIT *uptr; (*(((sz *) rp->loc) + id) & \ ~((m) << (rp)->offset)) | ((v) << (rp)->offset) -if (rptr == sim_PC) sim_brk_npc (0); +if (rptr == sim_PC) + sim_brk_npc (0); sz = SZ_R (rptr); mask = width_mask[rptr->width]; if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { idx = idx + rptr->qptr; - if (idx >= rptr->depth) idx = idx - rptr->depth; + if (idx >= rptr->depth) + idx = idx - rptr->depth; } if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { uptr = ((UNIT *) rptr->loc) + idx; @@ -2862,17 +3137,20 @@ t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr) t_stat reason; int32 rdx; -if (sim_vm_fprint_addr) sim_vm_fprint_addr (ofile, dptr, addr); +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, ":\t"); -if (!(flag & EX_E)) return (1 - dptr->aincr); +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, "\t"); +if (flag & EX_I) + fprintf (ofile, "\t"); else fprintf (ofile, "\n"); return reason; } @@ -2896,17 +3174,22 @@ t_addr j, loc; size_t sz; t_stat reason = SCPE_OK; -if ((dptr == NULL) || (uptr == NULL)) return SCPE_IERR; +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; 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; + 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_ATT)) + return SCPE_UNATT; + if (uptr->flags & UNIT_RAW) + return SCPE_NOFNC; if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) { reason = SCPE_NXM; break; @@ -2933,7 +3216,8 @@ for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr->aincr) { } sim_eval[i] = sim_eval[i] & mask; } -if ((reason != SCPE_OK) && (i == 0)) return reason; +if ((reason != SCPE_OK) && (i == 0)) + return reason; return SCPE_OK; } @@ -2961,20 +3245,26 @@ t_value mask; size_t sz; char gbuf[CBUFSIZE]; -if (dptr == NULL) return SCPE_IERR; +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 (sim_log) + fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); + if (cptr == NULL) /* force exit */ + return 1; + if (*cptr == 0) /* success */ + return dfltinc; } -if (uptr->flags & UNIT_RO) return SCPE_RO; /* read only? */ +if (uptr->flags & UNIT_RO) /* read only? */ + return SCPE_RO; 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; + if (reason != SCPE_OK) + return reason; } count = (1 - reason + (dptr->aincr - 1)) / dptr->aincr; @@ -2982,18 +3272,22 @@ 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; + 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_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; + if (loc >= uptr->hwmark) + uptr->hwmark = (uint32) loc + 1; } else { sim_fseek (uptr->fileref, sz * loc, SEEK_SET); @@ -3018,11 +3312,14 @@ t_stat r; GET_SWITCHES (cptr); GET_RADIX (rdx, dptr->dradix); -for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; -if (*cptr == 0) return SCPE_2FARG; +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; + if (r != SCPE_OK) + return r; } lim = 1 - r; for (i = a = 0; a < lim; ) { @@ -3036,7 +3333,8 @@ for (i = a = 0; a < lim; ) { r = fprint_val (sim_log, sim_eval[i], rdx, dptr->dwidth, PV_RZRO); fprintf (sim_log, "\n"); } - if (r < 0) a = a + 1 - r; + if (r < 0) + a = a + 1 - r; else a = a + dptr->aincr; i = a / dptr->aincr; } @@ -3072,7 +3370,8 @@ for (tptr = cptr; tptr < (cptr + size); tptr++) { /* remove cr or nl */ break; } } -while (isspace (*cptr)) cptr++; /* trim leading spc */ +while (isspace (*cptr)) /* trim leading spc */ + cptr++; if (*cptr == ';') *cptr = 0; /* ignore comment */ #if defined (HAVE_READLINE) @@ -3098,13 +3397,16 @@ return cptr; 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); + 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)) /* skip terminator */ + iptr++; +while (isspace (*iptr)) /* absorb spaces */ + iptr++; return iptr; } @@ -3131,7 +3433,8 @@ char *sim_trim_endspc (char *cptr) char *tptr; tptr = cptr + strlen (cptr); -while ((--tptr >= cptr) && isspace (*tptr)) *tptr = 0; +while ((--tptr >= cptr) && isspace (*tptr)) + *tptr = 0; return cptr; } @@ -3150,8 +3453,10 @@ char cbuf[CBUFSIZE], *cptr; printf ("%s ", ques); cptr = read_line (cbuf, CBUFSIZE, stdin); -if ((cptr == NULL) || (*cptr == 0)) return deflt; -if ((*cptr == 'Y') || (*cptr == 'y')) return TRUE; +if ((cptr == NULL) || (*cptr == 0)) + return deflt; +if ((*cptr == 'Y') || (*cptr == 'y')) + return TRUE; return FALSE; } @@ -3173,10 +3478,12 @@ char *tptr; *status = SCPE_OK; val = strtotv (cptr, &tptr, radix); -if ((cptr == tptr) || (val > max)) *status = SCPE_ARG; +if ((cptr == tptr) || (val > max)) + *status = SCPE_ARG; else { while (isspace (*tptr)) tptr++; - if (*tptr != 0) *status = SCPE_ARG; + if (*tptr != 0) + *status = SCPE_ARG; } return val; } @@ -3210,24 +3517,29 @@ 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 (cptr == tptr) /* error? */ + return NULL; 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; + 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; + if ((cptr == tptr) || (*hi == 0)) + return NULL; *hi = *lo + *hi - 1; } else *hi = *lo; } -if (term && (*tptr++ != term)) return NULL; +if (term && (*tptr++ != term)) + return NULL; return tptr; } @@ -3252,26 +3564,34 @@ if ((cptr == NULL) || (*cptr == 0)) return SCPE_ARG; strncpy (gbuf, cptr, CBUFSIZE); addrp = gbuf; /* default addr */ -if (portp = strchr (gbuf, ':')) *portp++ = 0; /* x:y? split */ -else if (strchr (gbuf, '.')) portp = NULL; /* x.y...? */ +if (portp = strchr (gbuf, ':')) /* x:y? split */ + *portp++ = 0; +else if (strchr (gbuf, '.')) /* x.y...? */ + portp = NULL; else { portp = gbuf; /* port only */ addrp = NULL; /* no addr */ } if (portp) { /* port string? */ - if (ipp == NULL) return SCPE_ARG; /* not wanted? */ + if (ipp == NULL) /* not wanted? */ + return SCPE_ARG; port = (int32) get_uint (portp, 10, 65535, &r); - if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG; + if ((r != SCPE_OK) || (port == 0)) + return SCPE_ARG; } else port = 0; if (addrp) { /* addr string? */ - if (ipa == NULL) return SCPE_ARG; /* not wanted? */ + if (ipa == NULL) /* not wanted? */ + return SCPE_ARG; for (i = addr = 0; i < 4; i++) { /* four octets */ octetp = strchr (addrp, '.'); /* find octet end */ - if (octetp != NULL) *octetp++ = 0; /* split string */ - else if (i < 3) return SCPE_ARG; /* except last */ + if (octetp != NULL) /* split string */ + *octetp++ = 0; + else if (i < 3) /* except last */ + return SCPE_ARG; octet = (int32) get_uint (addrp, 10, 255, &r); - if (r != SCPE_OK) return SCPE_ARG; + if (r != SCPE_OK) + return SCPE_ARG; addr = (addr << 8) | octet; addrp = octetp; } @@ -3279,8 +3599,10 @@ if (addrp) { /* addr string? */ return SCPE_ARG; } else addr = 0; -if (ipp) *ipp = port; /* return req values */ -if (ipa) *ipa = addr; +if (ipp) /* return req values */ + *ipp = port; +if (ipa) + *ipa = addr; return SCPE_OK; } @@ -3300,7 +3622,8 @@ 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; + (strcmp (cptr, dptr->lname) == 0))) + return dptr; } return NULL; } @@ -3322,9 +3645,11 @@ char *nptr, *tptr; t_stat r; DEVICE *dptr; -if (uptr == NULL) return NULL; /* arg error? */ +if (uptr == NULL) /* arg error? */ + return NULL; if (dptr = find_dev (cptr)) { /* exact match? */ - if (qdisable (dptr)) return NULL; /* disabled? */ + if (qdisable (dptr)) /* disabled? */ + return NULL; *uptr = dptr->units; /* unit 0 */ return dptr; } @@ -3337,9 +3662,11 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */ (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? */ + if (qdisable (dptr)) /* disabled? */ + return NULL; + u = (uint32) get_uint (tptr, 10, dptr->numunits - 1, &r); + if (r != SCPE_OK) /* error? */ + *uptr = NULL; else *uptr = dptr->units + u; return dptr; } @@ -3361,10 +3688,12 @@ DEVICE *find_dev_from_unit (UNIT *uptr) DEVICE *dptr; uint32 i, j; -if (uptr == NULL) return NULL; +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; + if (uptr == (dptr->units + j)) + return dptr; } } return NULL; @@ -3396,9 +3725,11 @@ 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 (dptr->flags & DEV_DIS) /* skip disabled */ + continue; if (rptr = find_reg (cptr, optr, dptr)) { /* found? */ - if (srptr) return NULL; /* ambig? err */ + if (srptr) /* ambig? err */ + return NULL; srptr = rptr; /* save reg */ *gdptr = dptr; /* save unit */ } @@ -3423,8 +3754,8 @@ char *tptr; REG *rptr; uint32 slnt; -if ((cptr == NULL) || (dptr == NULL) || - (dptr->registers == NULL)) return NULL; +if ((cptr == NULL) || (dptr == NULL) || (dptr->registers == NULL)) + return NULL; tptr = cptr; do { tptr++; @@ -3433,7 +3764,8 @@ 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; + if (optr != NULL) + *optr = tptr; return rptr; } } @@ -3453,10 +3785,12 @@ int32 get_switches (char *cptr) { int32 sw; -if (*cptr != '-') return 0; +if (*cptr != '-') + return 0; sw = 0; for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) { - if (isalpha (*cptr) == 0) return -1; + if (isalpha (*cptr) == 0) + return -1; sw = sw | SWMASK (toupper (*cptr)); } return sw; @@ -3479,7 +3813,8 @@ 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? */ + if (lsw <= 0) /* invalid? */ + return NULL; sim_switches = sim_switches | lsw; /* accumulate */ } return cptr; @@ -3583,7 +3918,8 @@ if (pptr) { /* any? */ if (toupper (*fptr) != toupper (*eptr)) return NULL; } - if (*eptr != 0) return NULL; /* ext exhausted? */ + if (*eptr != 0) /* ext exhausted? */ + return NULL; } return pptr; } @@ -3607,12 +3943,14 @@ char *sptr, *tptr; const char logstr[] = "|&^", cmpstr[] = "=!><"; logval = cmpval = 0; -if (*cptr == 0) return NULL; /* check for clause */ +if (*cptr == 0) /* check for clause */ + return NULL; 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; + if (cptr == tptr) + return NULL; cptr = tptr; } else if (sptr = strchr (cmpstr, c)) { /* check for boolop */ @@ -3622,7 +3960,8 @@ for (logop = cmpop = -1; c = *cptr++; ) { /* loop thru clauses */ cptr++; } cmpval = strtotv (cptr, &tptr, radix); - if (cptr == tptr) return NULL; + if (cptr == tptr) + return NULL; cptr = tptr; } else return NULL; @@ -3711,20 +4050,27 @@ t_value val; uint32 c, digit; *endptr = inptr; /* assume fails */ -if ((radix < 2) || (radix > 36)) return 0; -while (isspace (*inptr)) inptr++; /* bypass white space */ +if ((radix < 2) || (radix > 36)) + return 0; +while (isspace (*inptr)) /* bypass white space */ + inptr++; 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 if (radix <= 10) break; /* stop if not expected */ + if (islower (c)) + c = toupper (c); + if (isdigit (c)) /* digit? */ + digit = c - (uint32) '0'; + else if (radix <= 10) /* stop if not expected */ + break; else digit = c + 10 - (uint32) 'A'; /* convert letter */ - if (digit >= radix) return 0; /* valid in radix? */ + if (digit >= radix) /* valid in radix? */ + return 0; val = (val * radix) + digit; /* add to value */ nodigit = 0; } -if (nodigit) return 0; /* no digits? */ +if (nodigit) /* no digits? */ + return 0; *endptr = inptr; /* result pointer */ return val; } @@ -3749,7 +4095,8 @@ t_value owtest, wtest; int32 d, digit, ndigits; char dbuf[MAX_WIDTH + 1]; -for (d = 0; d < MAX_WIDTH; d++) dbuf[d] = (format == PV_RZRO)? '0': ' '; +for (d = 0; d < MAX_WIDTH; d++) + dbuf[d] = (format == PV_RZRO)? '0': ' '; dbuf[MAX_WIDTH] = 0; d = MAX_WIDTH; do { @@ -3767,9 +4114,11 @@ if (format != PV_LEFT) { wtest = wtest * radix; ndigits = ndigits + 1; } - if ((MAX_WIDTH - ndigits) < d) d = MAX_WIDTH - ndigits; + if ((MAX_WIDTH - ndigits) < d) + d = MAX_WIDTH - ndigits; } -if (fputs (&dbuf[d], stream) == EOF) return SCPE_IOERR; +if (fputs (&dbuf[d], stream) == EOF) + return SCPE_IOERR; return SCPE_OK; } @@ -3808,7 +4157,8 @@ t_stat sim_process_event (void) UNIT *uptr; t_stat reason; -if (stop_cpu) return SCPE_STOP; /* stop CPU? */ +if (stop_cpu) /* stop CPU? */ + return SCPE_STOP; if (sim_clock_queue == NULL) { /* queue empty? */ UPDATE_SIM_TIME (noqueue_time); /* update sim time */ sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */ @@ -3820,9 +4170,11 @@ do { 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; + 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); + if (uptr->action != NULL) + reason = uptr->action (uptr); else reason = SCPE_OK; } while ((reason == SCPE_OK) && (sim_interval == 0)); @@ -3845,15 +4197,22 @@ t_stat sim_activate (UNIT *uptr, int32 event_time) UNIT *cptr, *prvptr; int32 accum; -if (event_time < 0) return SCPE_IERR; -if (sim_is_active (uptr)) return SCPE_OK; /* already active? */ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } /* update sim time */ +if (event_time < 0) + return SCPE_IERR; +if (sim_is_active (uptr)) /* already active? */ + return SCPE_OK; +if (sim_clock_queue == NULL) { + UPDATE_SIM_TIME (noqueue_time); + } +else { /* update sim time */ + UPDATE_SIM_TIME (sim_clock_queue->time); + } prvptr = NULL; accum = 0; for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - if (event_time < (accum + cptr->time)) break; + if (event_time < (accum + cptr->time)) + break; accum = accum + cptr->time; prvptr = cptr; } @@ -3866,7 +4225,8 @@ else { prvptr->next = uptr; } uptr->time = event_time - accum; -if (cptr != NULL) cptr->time = cptr->time - uptr->time; +if (cptr != NULL) + cptr->time = cptr->time - uptr->time; sim_interval = sim_clock_queue->time; return SCPE_OK; } @@ -3899,10 +4259,12 @@ t_stat sim_cancel (UNIT *uptr) { UNIT *cptr, *nptr; -if (sim_clock_queue == NULL) return SCPE_OK; +if (sim_clock_queue == NULL) + return SCPE_OK; UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */ nptr = NULL; -if (sim_clock_queue == uptr) nptr = sim_clock_queue = uptr->next; +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) { @@ -3911,10 +4273,12 @@ else { } } } -if (nptr != NULL) nptr->time = nptr->time + uptr->time; +if (nptr != NULL) + nptr->time = nptr->time + uptr->time; uptr->next = NULL; /* hygiene */ uptr->time = 0; -if (sim_clock_queue != NULL) sim_interval = sim_clock_queue->time; +if (sim_clock_queue != NULL) + sim_interval = sim_clock_queue->time; else sim_interval = noqueue_time = NOQUEUE_WAIT; return SCPE_OK; } @@ -3935,10 +4299,12 @@ int32 accum; accum = 0; for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { if (cptr == sim_clock_queue) { - if (sim_interval > 0) accum = accum + sim_interval; + if (sim_interval > 0) + accum = accum + sim_interval; } else accum = accum + cptr->time; - if (cptr == uptr) return accum + 1; + if (cptr == uptr) + return accum + 1; } return 0; } @@ -3953,15 +4319,23 @@ return 0; 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; } @@ -3978,7 +4352,8 @@ int32 cnt; UNIT *uptr; cnt = 0; -for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) cnt++; +for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) + cnt++; return cnt; } @@ -4019,7 +4394,8 @@ t_stat sim_brk_init (void) { sim_brk_lnt = SIM_BRK_INILNT; sim_brk_tab = (BRKTAB *) calloc (sim_brk_lnt, sizeof (BRKTAB)); -if (sim_brk_tab == NULL) return SCPE_MEM; +if (sim_brk_tab == NULL) + return SCPE_MEM; sim_brk_ent = sim_brk_ins = 0; sim_brk_act = NULL; sim_brk_npc (0); @@ -4042,11 +4418,14 @@ 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 */ + if (loc == bp->addr) /* match? */ + return bp; + else if (loc < bp->addr) /* go down? p is upper */ + hi = p - 1; else lo = p + 1; /* go up? p is lower */ } while (lo <= hi); -if (loc < bp->addr) sim_brk_ins = p; /* insrt before or */ +if (loc < bp->addr) /* insrt before or */ + sim_brk_ins = p; else sim_brk_ins = p + 1; /* after last sch */ return NULL; } @@ -4058,11 +4437,13 @@ BRKTAB *sim_brk_new (t_addr loc) int32 i, t; BRKTAB *bp, *newp; -if (sim_brk_ins < 0) return NULL; +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 = (BRKTAB *) calloc (t, sizeof (BRKTAB)); /* new table */ - if (newp == NULL) return NULL; /* can't extend */ + if (newp == NULL) /* can't extend */ + return NULL; for (i = 0; i < sim_brk_lnt; i++) /* copy table */ *(newp + i) = *(sim_brk_tab + i); free (sim_brk_tab); /* free old table */ @@ -4090,10 +4471,13 @@ t_stat sim_brk_set (t_addr loc, int32 sw, int32 ncnt, char *act) BRKTAB *bp; if (sw == 0) sw = sim_brk_dflt; -if ((sim_brk_types & sw) == 0) return SCPE_NOFNC; +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 */ +if (!bp) /* no, allocate */ + bp = sim_brk_new (loc); +if (!bp) /* still no? mem err */ + return SCPE_MEM; bp->typ = sw; /* set type */ bp->cnt = ncnt; /* set count */ if ((bp->act != NULL) && (act != NULL)) { /* replace old action? */ @@ -4102,7 +4486,8 @@ if ((bp->act != NULL) && (act != NULL)) { /* replace old 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? */ + if (newp == NULL) /* mem err? */ + return SCPE_MEM; strncpy (newp, act, CBUFSIZE); /* copy action */ bp->act = newp; /* set pointer */ } @@ -4116,11 +4501,15 @@ t_stat sim_brk_clr (t_addr loc, int32 sw) { BRKTAB *bp = sim_brk_fnd (loc); -if (!bp) return SCPE_OK; /* not there? ok */ -if (sw == 0) sw = SIM_BRK_ALLTYP; +if (!bp) /* not there? ok */ + return SCPE_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 */ +if (bp->typ) /* clear all types? */ + return SCPE_OK; +if (bp->act != NULL) /* deallocate action */ + free (bp->act); for ( ; bp < (sim_brk_tab + sim_brk_ent - 1); bp++) /* erase entry */ *bp = *(bp + 1); sim_brk_ent = sim_brk_ent - 1; /* decrement count */ @@ -4138,7 +4527,8 @@ 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); + if (bp->typ & sw) + sim_brk_clr (bp->addr, sw); else bp++; } return SCPE_OK; @@ -4152,22 +4542,29 @@ BRKTAB *bp = sim_brk_fnd (loc); DEVICE *dptr; int32 i, any; -if (sw == 0) sw = SIM_BRK_ALLTYP; -if (!bp || (!(bp->typ & sw))) return SCPE_OK; +if (sw == 0) + sw = SIM_BRK_ALLTYP; +if (!bp || (!(bp->typ & sw))) + return SCPE_OK; dptr = sim_dflt_dev; -if (dptr == NULL) return SCPE_OK; -if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, dptr, loc); +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, ", "); + 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); +if (bp->cnt > 0) + fprintf (st, " [%d]", bp->cnt); +if (bp->act != NULL) + fprintf (st, "; %s", bp->act); fprintf (st, "\n"); return SCPE_OK; } @@ -4178,9 +4575,11 @@ t_stat sim_brk_showall (FILE *st, int32 sw) { BRKTAB *bp; -if (sw == 0) sw = SIM_BRK_ALLTYP; +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; } @@ -4194,7 +4593,8 @@ uint32 spc = (btyp >> SIM_BKPT_V_SPC) & (SIM_BKPT_N_SPC - 1); if ((bp = sim_brk_fnd (loc)) && (btyp & bp->typ)) { /* in table, type match? */ if ((sim_brk_pend[spc] && (loc == sim_brk_ploc[spc])) || /* previous location? */ - (--bp->cnt > 0)) return 0; /* count > 0? */ + (--bp->cnt > 0)) /* count > 0? */ + return 0; bp->cnt = 0; /* reset count */ sim_brk_ploc[spc] = loc; /* save location */ sim_brk_pend[spc] = TRUE; /* don't do twice */ @@ -4212,9 +4612,12 @@ 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 (sim_brk_act == NULL) /* any action? */ + return NULL; +while (isspace (*sim_brk_act)) /* skip spaces */ + sim_brk_act++; +if (*sim_brk_act == 0) /* now empty? */ + return (sim_brk_act = NULL); if (ep = strchr (sim_brk_act, ';')) { /* cmd delimiter? */ lnt = ep - sim_brk_act; /* cmd length */ memcpy (buf, sim_brk_act, lnt + 1); /* copy with ; */ @@ -4241,7 +4644,8 @@ void sim_brk_npc (uint32 cnt) { uint32 i; -if ((cnt == 0) || (cnt > SIM_BKPT_N_SPC)) cnt = SIM_BKPT_N_SPC; +if ((cnt == 0) || (cnt > SIM_BKPT_N_SPC)) + cnt = SIM_BKPT_N_SPC; for (i = 0; i < cnt; i++) { sim_brk_pend[i] = FALSE; sim_brk_ploc[i] = 0; @@ -4274,7 +4678,8 @@ static char* debtab_none = "DEBTAB_ISNULL"; static char* debtab_nomatch = "DEBTAB_NOMATCH"; int32 offset = 0; -if (dptr->debflags == 0) return debtab_none; +if (dptr->debflags == 0) + return debtab_none; /* Find matching words for bitmask */ @@ -4311,7 +4716,8 @@ if (sim_deb && (dptr->dctrl & dbits)) { 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"); + if (terminate) + fprintf(sim_deb, "\r\n"); debug_unterm = terminate ? 0 : 1; /* set unterm for next */ } } @@ -4375,10 +4781,12 @@ if (sim_deb && (dptr->dctrl & dbits)) { /* 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); + if (buf != stackbuf) + free (buf); bufsize = bufsize * 2; buf = (char *) malloc (bufsize); - if (buf == NULL) return; /* out of memory */ + if (buf == NULL) /* out of memory */ + return; buf[bufsize-1] = '\0'; continue; } @@ -4389,17 +4797,20 @@ if (sim_deb && (dptr->dctrl & dbits)) { for (i = j = 0; i < len; ++i) { if ('\n' == buf[i]) { - if (i > j) fwrite (&buf[j], 1, i-j, sim_deb); + 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); + 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); + if (buf != stackbuf) + free (buf); } return; } diff --git a/scp.h b/scp.h index 026e74bb..cdb2c33a 100644 --- a/scp.h +++ b/scp.h @@ -1,6 +1,6 @@ /* scp.h: simulator control program headers - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/sim_console.c b/sim_console.c index 9a0044d4..497c8e6d 100644 --- a/sim_console.c +++ b/sim_console.c @@ -1,6 +1,6 @@ /* sim_console.c: simulator console I/O library - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -157,14 +157,17 @@ char *cvptr, gbuf[CBUFSIZE]; CTAB *ctptr; t_stat r; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; +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? */ + if (cvptr = strchr (gbuf, '=')) /* = value? */ + *cvptr++ = 0; 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; + if (r != SCPE_OK) + return r; } else return SCPE_NOPARAM; } @@ -201,12 +204,14 @@ DEVICE *dptr = sim_devices[0]; int32 val, rdx; t_stat r; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; +if ((cptr == NULL) || (*cptr == 0)) + return SCPE_2FARG; 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; } @@ -229,12 +234,14 @@ DEVICE *dptr = sim_devices[0]; uint32 val, rdx; t_stat r; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; +if ((cptr == NULL) || (*cptr == 0)) + return SCPE_2FARG; if (dptr->dradix == 16) rdx = 16; else rdx = 8; val = (uint32) get_uint (cptr, rdx, 0xFFFFFFFF, &r); if ((r != SCPE_OK) || - ((val & 0x00002400) == 0)) return SCPE_ARG; + ((val & 0x00002400) == 0)) + return SCPE_ARG; sim_tt_pchar = val; return SCPE_OK; } @@ -255,13 +262,17 @@ t_stat sim_set_logon (int32 flag, char *cptr) { char gbuf[CBUFSIZE]; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; /* need arg */ +if ((cptr == NULL) || (*cptr == 0)) /* need arg */ + return SCPE_2FARG; cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ +if (*cptr != 0) /* now eol? */ + return SCPE_2MARG; 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); +if (sim_log == NULL) /* error? */ + return SCPE_OPENERR; +if (!sim_quiet) + printf ("Logging to file \"%s\"\n", gbuf); fprintf (sim_log, "Logging to file \"%s\"\n", gbuf); /* start of log */ return SCPE_OK; } @@ -270,9 +281,12 @@ 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 (!sim_quiet) printf ("Log file closed\n"); +if (cptr && (*cptr != 0)) /* now eol? */ + return SCPE_2MARG; +if (sim_log == NULL) /* no log? */ + return SCPE_OK; +if (!sim_quiet) + printf ("Log file closed\n"); fprintf (sim_log, "Log file closed\n"); /* close log */ fclose (sim_log); sim_log = NULL; @@ -283,8 +297,10 @@ return SCPE_OK; t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_log) fputs ("Logging enabled\n", st); +if (cptr && (*cptr != 0)) + return SCPE_2MARG; +if (sim_log) + fputs ("Logging enabled\n", st); else fputs ("Logging disabled\n", st); return SCPE_OK; } @@ -295,24 +311,32 @@ t_stat sim_set_debon (int32 flag, char *cptr) { char *tptr, gbuf[CBUFSIZE]; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; /* too few arguments? */ +if ((cptr == NULL) || (*cptr == 0)) /* too few arguments? */ + return SCPE_2FARG; tptr = get_glyph (cptr, gbuf, 0); /* get file name */ -if (*tptr != 0) return SCPE_2MARG; /* now eol? */ +if (*tptr != 0) /* now eol? */ + return SCPE_2MARG; 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? */ + if (sim_log == NULL) /* any log? */ + return SCPE_ARG; 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 if (strcmp (gbuf, "STDOUT") == 0) /* debug to stdout? */ + sim_deb = stdout; +else if (strcmp (gbuf, "STDERR") == 0) /* debug to stderr? */ + sim_deb = 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? */ + if (sim_deb == NULL) /* error? */ + return SCPE_OPENERR; 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); +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; } @@ -320,11 +344,16 @@ return SCPE_OK; 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 (!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 (cptr && (*cptr != 0)) /* now eol? */ + return SCPE_2MARG; +if (sim_deb == NULL) /* no log? */ + return SCPE_OK; +if (!sim_quiet) + printf ("Debug output disabled\n"); +if (sim_log) + fprintf (sim_log, "Debug output disabled\n"); +if (sim_deb_close) /* close if needed */ + fclose (sim_deb); sim_deb_close = 0; sim_deb = NULL; return SCPE_OK; @@ -334,8 +363,10 @@ return SCPE_OK; t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_deb) fputs ("Debug output enabled\n", st); +if (cptr && (*cptr != 0)) + return SCPE_2MARG; +if (sim_deb) + fputs ("Debug output enabled\n", st); else fputs ("Debug output disabled\n", st); return SCPE_OK; } @@ -344,8 +375,10 @@ 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? */ +if ((cptr == NULL) || (*cptr == 0)) /* too few arguments? */ + return SCPE_2FARG; +if (sim_con_tmxr.master) /* already open? */ + return SCPE_ALATT; return tmxr_open_master (&sim_con_tmxr, cptr); /* open master socket */ } @@ -353,8 +386,10 @@ return tmxr_open_master (&sim_con_tmxr, cptr); /* open master socket */ 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 */ +if (cptr && (*cptr != 0)) /* too many arguments? */ + return SCPE_2MARG; +if (sim_con_tmxr.master == 0) /* ignore if already closed */ + return SCPE_OK; return tmxr_close_master (&sim_con_tmxr); /* close master socket */ } @@ -362,7 +397,8 @@ return tmxr_close_master (&sim_con_tmxr); /* close master socket * t_stat sim_show_telnet (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, char *cptr) { -if (cptr && (*cptr != 0)) return SCPE_2MARG; +if (cptr && (*cptr != 0)) + return SCPE_2MARG; if (sim_con_tmxr.master == 0) fprintf (st, "Connected to console window\n"); else if (sim_con_ldsc.conn == 0) @@ -382,10 +418,12 @@ 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_tmxr.master == 0) /* not Telnet? done */ + return SCPE_OK; 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? */ + if (sim_con_ldsc.conn) /* still connected? */ + return SCPE_OK; } for (i = 0; i < sec; i++) { /* loop */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */ @@ -397,7 +435,8 @@ for (i = 0; i < sec; i++) { /* loop */ 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 ((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); @@ -416,7 +455,8 @@ 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? */ +if (sim_con_ldsc.conn == 0) /* no Telnet conn? */ + return SCPE_LOST; 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; @@ -427,10 +467,12 @@ return SCPE_OK; t_stat sim_putchar (int32 c) { -if (sim_log) fputc (c, sim_log); /* log file? */ +if (sim_log) /* log file? */ + fputc (c, sim_log); 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.conn == 0) /* no Telnet conn? */ + return SCPE_LOST; tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ return SCPE_OK; @@ -443,8 +485,10 @@ 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? */ +if (sim_con_ldsc.conn == 0) /* no Telnet conn? */ + return SCPE_LOST; +if (sim_con_ldsc.xmte == 0) /* xmt disabled? */ + r = SCPE_STALL; else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ return r; /* return status */ @@ -459,8 +503,10 @@ uint32 md = mode & TTUF_M_MODE; if (md != TTUF_MODE_8B) { c = c & 0177; if (md == TTUF_MODE_UC) { - if (islower (c)) c = toupper (c); - if (mode & TTUF_KSR) c = c | 0200; + if (islower (c)) + c = toupper (c); + if (mode & TTUF_KSR) + c = c | 0200; } } else c = c & 0377; @@ -476,7 +522,8 @@ uint32 md = mode & TTUF_M_MODE; if (md != TTUF_MODE_8B) { c = c & 0177; if (md == TTUF_MODE_UC) { - if (islower (c)) c = toupper (c); + if (islower (c)) + c = toupper (c); if ((mode & TTUF_KSR) && (c >= 0140)) return -1; } @@ -531,10 +578,12 @@ IOSB iosb; $DESCRIPTOR (terminal_device, "tt"); status = sys$assign (&terminal_device, &tty_chan, 0, 0); -if (status != SS$_NORMAL) return SCPE_TTIERR; +if (status != SS$_NORMAL) + return SCPE_TTIERR; status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE, &iosb, 0, 0, &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; +if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) + return SCPE_TTIERR; run_mode = cmd_mode; run_mode.stat = cmd_mode.stat | TT$M_NOECHO & ~(TT$M_HOSTSYNC | TT$M_TTSYNC); run_mode.stat2 = cmd_mode.stat2 | TT2$M_PASTHRU; @@ -548,7 +597,8 @@ IOSB iosb; status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, &run_mode, sizeof (run_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; +if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) + return SCPE_TTIERR; return SCPE_OK; } @@ -559,7 +609,8 @@ IOSB iosb; status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; +if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) + return SCPE_TTIERR; return SCPE_OK; } @@ -578,15 +629,18 @@ SENSE_BUF sense; term[0] = 0; term[1] = 0; status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb, 0, 0, &sense, 8, 0, term, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; +if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) + return SCPE_TTIERR; if (sense.sense_count == 0) return SCPE_OK; term[0] = 0; term[1] = 0; status = sys$qiow (EFN, tty_chan, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, &iosb, 0, 0, buf, 1, 0, term, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_OK; +if ((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; +if (sim_brk_char && (buf[0] == sim_brk_char)) + return SCPE_BREAK; return (buf[0] | SCPE_KFLAG); } @@ -599,7 +653,8 @@ IOSB iosb; c = out; status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT, &iosb, 0, 0, &c, 1, 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR; +if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) + return SCPE_TTOERR; return SCPE_OK; } @@ -619,14 +674,16 @@ 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); @@ -655,17 +712,22 @@ t_stat sim_os_poll_kbd (void) { int c; -if (!_kbhit ()) return SCPE_OK; +if (!_kbhit ()) + return SCPE_OK; c = _getch (); -if ((c & 0177) == sim_del_char) c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -if (sim_brk_char && ((c & 0177) == sim_brk_char)) return SCPE_BREAK; +if ((c & 0177) == sim_del_char) + c = 0177; +if ((c & 0177) == sim_int_char) + return SCPE_STOP; +if (sim_brk_char && ((c & 0177) == sim_brk_char)) + return SCPE_BREAK; return c | SCPE_KFLAG; } t_stat sim_os_putchar (int32 c) { -if (c != 0177) _putch (c); +if (c != 0177) + _putch (c); return SCPE_OK; } @@ -713,12 +775,16 @@ switch (c = _read_kbd(0,0,0)) { /* EMX has _read_kbd */ break; } #else -if (!kbhit ()) return SCPE_OK; +if (!kbhit ()) + return SCPE_OK; c = getch(); #endif -if ((c & 0177) == sim_del_char) c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -if (sim_brk_char && ((c & 0177) == sim_brk_char)) return SCPE_BREAK; +if ((c & 0177) == sim_del_char) + c = 0177; +if ((c & 0177) == sim_int_char) + return SCPE_STOP; +if (sim_brk_char && ((c & 0177) == sim_brk_char)) + return SCPE_BREAK; return c | SCPE_KFLAG; } @@ -891,11 +957,14 @@ t_stat sim_os_poll_kbd (void) { int c; -if (!ps_kbhit ()) return SCPE_OK; +if (!ps_kbhit ()) + return SCPE_OK; c = ps_getch(); -if ((c & 0177) == sim_del_char) c = 0177; +if ((c & 0177) == sim_del_char) + c = 0177; if ((c & 0177) == sim_int_char) return SCPE_STOP; -if (sim_brk_char && ((c & 0177) == sim_brk_char)) return SCPE_BREAK; +if (sim_brk_char && ((c & 0177) == sim_brk_char)) + return SCPE_BREAK; return c | SCPE_KFLAG; } @@ -925,9 +994,12 @@ t_stat sim_ttinit (void) { cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */ runfl = cmdfl | FNDELAY; -if (ioctl (0, TIOCGETP, &cmdtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCGETC, &cmdtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCGLTC, &cmdltchars) < 0) return SCPE_TTIERR; +if (ioctl (0, TIOCGETP, &cmdtty) < 0) + return SCPE_TTIERR; +if (ioctl (0, TIOCGETC, &cmdtchars) < 0) + return SCPE_TTIERR; +if (ioctl (0, TIOCGLTC, &cmdltchars) < 0) + return SCPE_TTIERR; runtty = cmdtty; /* initial run state */ runtty.sg_flags = cmdtty.sg_flags & ~(ECHO|CRMOD) | CBREAK; runtchars.t_intrc = sim_int_char; /* interrupt */ @@ -949,9 +1021,12 @@ t_stat sim_ttrun (void) { runtchars.t_intrc = sim_int_char; /* in case changed */ fcntl (0, F_SETFL, runfl); /* non-block mode */ -if (ioctl (0, TIOCSETP, &runtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSETC, &runtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSLTC, &runltchars) < 0) return SCPE_TTIERR; +if (ioctl (0, TIOCSETP, &runtty) < 0) + return SCPE_TTIERR; +if (ioctl (0, TIOCSETC, &runtchars) < 0) + return SCPE_TTIERR; +if (ioctl (0, TIOCSLTC, &runltchars) < 0) + return SCPE_TTIERR; nice (10); /* lower priority */ return SCPE_OK; } @@ -960,9 +1035,12 @@ t_stat sim_ttcmd (void) { nice (-10); /* restore priority */ fcntl (0, F_SETFL, cmdfl); /* block mode */ -if (ioctl (0, TIOCSETP, &cmdtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSETC, &cmdtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSLTC, &cmdltchars) < 0) return SCPE_TTIERR; +if (ioctl (0, TIOCSETP, &cmdtty) < 0) + return SCPE_TTIERR; +if (ioctl (0, TIOCSETC, &cmdtchars) < 0) + return SCPE_TTIERR; +if (ioctl (0, TIOCSLTC, &cmdltchars) < 0) + return SCPE_TTIERR; return SCPE_OK; } @@ -978,7 +1056,8 @@ unsigned char buf[1]; status = read (0, buf, 1); if (status != 1) return SCPE_OK; -if (sim_brk_char && (buf[0] == sim_brk_char)) return SCPE_BREAK; +if (sim_brk_char && (buf[0] == sim_brk_char)) + return SCPE_BREAK; else return (buf[0] | SCPE_KFLAG); } @@ -1003,8 +1082,10 @@ 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))) /* skip if !tty */ + return SCPE_OK; +if (tcgetattr (0, &cmdtty) < 0) /* get old flags */ + return SCPE_TTIERR; runtty = cmdtty; runtty.c_lflag = runtty.c_lflag & ~(ECHO | ICANON); /* no echo or edit */ runtty.c_oflag = runtty.c_oflag & ~OPOST; /* no output edit */ @@ -1043,9 +1124,11 @@ return SCPE_OK; t_stat sim_ttrun (void) { -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ +if (!isatty (fileno (stdin))) /* skip if !tty */ + return SCPE_OK; runtty.c_cc[VINTR] = sim_int_char; /* in case changed */ -if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) return SCPE_TTIERR; +if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) + return SCPE_TTIERR; if (prior_norm) { /* at normal pri? */ errno = 0; nice (10); /* try to lower pri */ @@ -1056,13 +1139,15 @@ return SCPE_OK; t_stat sim_ttcmd (void) { -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ +if (!isatty (fileno (stdin))) /* skip if !tty */ + return SCPE_OK; 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; +if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0) + return SCPE_TTIERR; return SCPE_OK; } @@ -1078,7 +1163,8 @@ unsigned char buf[1]; status = read (0, buf, 1); if (status != 1) return SCPE_OK; -if (sim_brk_char && (buf[0] == sim_brk_char)) return SCPE_BREAK; +if (sim_brk_char && (buf[0] == sim_brk_char)) + return SCPE_BREAK; else return (buf[0] | SCPE_KFLAG); } diff --git a/sim_console.h b/sim_console.h index 7a69d7e1..0b4818a7 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-2005, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/sim_defs.h b/sim_defs.h index c26c4ee8..66f67d44 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -23,6 +23,7 @@ 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-Jul-08 RMS Removed inlining support 28-May-08 RMS Added inlining support 28-Jun-07 RMS Added IA64 VMS support (from Norm Lastovica) 18-Jun-07 RMS Added UNIT_IDLE flag @@ -161,15 +162,9 @@ typedef uint32 t_addr; #define T_ADDR_W 32 #endif /* end 64b address */ -/* Inlining */ +/* Stubs for inlining */ -#if defined (__GNUC__) /* GCC */ -#define SIM_INLINE inline -#elif defined (_MSC_VER) /* Microsoft C Compilers */ -#define SIM_INLINE __inline -#else /* default */ #define SIM_INLINE -#endif /* System independent definitions */ diff --git a/sim_fio.c b/sim_fio.c index d7b4d629..70b2800a 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -1,6 +1,6 @@ /* sim_fio.c: simulator file I/O library - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -84,7 +84,8 @@ size_t c, j; int32 k; unsigned char by, *sptr, *dptr; -if ((size == 0) || (count == 0)) return 0; /* check arguments */ +if ((size == 0) || (count == 0)) /* check arguments */ + return 0; c = fread (bptr, size, count, fptr); /* read buffer */ if (sim_end || (size == sizeof (char)) || (c == 0)) /* le, byte, or err? */ return c; /* done */ @@ -105,7 +106,8 @@ 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 ((size == 0) || (count == 0)) /* check arguments */ + return 0; if (sim_end || (size == sizeof (char))) /* le or byte? */ return fwrite (bptr, size, count, fptr); /* done */ nelem = FLIP_SIZE / size; /* elements in buffer */ @@ -118,11 +120,13 @@ 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++; + 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; + if (c == 0) + return total; total = total + c; } return total; @@ -135,7 +139,8 @@ uint32 sim_fsize_name (char *fname) FILE *fp; uint32 sz; -if ((fp = sim_fopen (fname, "rb")) == NULL) return 0; +if ((fp = sim_fopen (fname, "rb")) == NULL) + return 0; sz = sim_fsize (fp); fclose (fp); return sz; @@ -145,7 +150,8 @@ uint32 sim_fsize (FILE *fp) { uint32 pos, sz; -if (fp == NULL) return 0; +if (fp == NULL) + return 0; pos = ftell (fp); fseek (fp, 0, SEEK_END); sz = ftell (fp); @@ -222,7 +228,8 @@ switch (whence) { break; case SEEK_CUR: - if (fgetpos (st, &filepos)) return (-1); + if (fgetpos (st, &filepos)) + return (-1); fileaddr = fpos_t_to_int64 (&filepos); fileaddr = fileaddr + offset; break; @@ -266,7 +273,8 @@ switch (whence) { break; case SEEK_CUR: - if (fgetpos (st, &fileaddr)) return (-1); + if (fgetpos (st, &fileaddr)) + return (-1); fileaddr = fileaddr + offset; break; diff --git a/sim_fio.h b/sim_fio.h index 70cd153b..264ea971 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-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/sim_rev.h b/sim_rev.h index 9cda3321..4ba41b2d 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -1,6 +1,6 @@ /* sim_rev.h: simulator revisions and current rev level - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -29,14 +29,192 @@ #define SIM_MAJOR 3 #define SIM_MINOR 8 -#define SIM_PATCH 0 +#define SIM_PATCH 1 #define SIM_DELTA 0 /* V3.8 revision history patch date module(s) and fix(es) - 0 tbd scp.c: + 1 08-Feb-09 scp.c: + - revised RESTORE unit logic for consistency + - "detach_all" ignores error status returns if shutting down (from Dave Bryan) + - DO cmd missing params now default to null string (from Dave Bryan) + - DO cmd sub_args now allows "\\" to specify literal backslash (from Dave Bryan) + - decommitted MTAB_VAL + - fixed implementation of MTAB_NC + - fixed warnings in help printouts + + sim_tape.c: + - fixed signed/unsigned warning in sim_tape_set_fmt (from Dave Bryan) + + sim_tmxr.c, sim_tmxr.h: + - added line connection order to tmxr_poll_conn, + added tmxr_set_lnorder and tmxr_show_lnorder (from Dave Bryan) + - print device and line to which connection was made (from Dave Bryan) + - added three new standardized SHOW routines + + all terminal multiplexers: + - revised for new common SHOW routines in TMXR library + - rewrote set size routines not to use MTAB_VAL + + hp2100_cpu.c (from Dave Bryan): + - VIS and IOP are now mutually exclusive on 1000-F + - Removed A/B shadow register variables + - Moved hp_setdev, hp_showdev to hp2100_sys.c + - Moved non-existent memory checks to WritePW + - Fixed mp_dms_jmp to accept lower bound, check write protection + - Corrected DMS violation register set conditions + - Refefined ABORT to pass address, moved def to hp2100_cpu.h + - Combined dms and dms_io routines + - JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort + - Unified I/O slot dispatch by adding DIBs for CPU, MP, and DMA + - Rewrote device I/O to model backplane signals + - EDT no longer passes DMA channel + - Added SET CPU IDLE/NOIDLE, idle detection for DOS/RTE + - Breakpoints on interrupt trap cells now work + + hp2100_cpu0.c (from Dave Bryan): + - .FLUN and self-tests for VIS and SIGNAL are NOP if not present + - Moved microcode function prototypes to hp2100_cpu1.h + - Removed option-present tests (now in UIG dispatchers) + - Added "user microcode" dispatcher for unclaimed instructions + + hp2100_cpu1.c (from Dave Bryan): + - Moved microcode function prototypes to hp2100_cpu1.h + - Moved option-present tests to UIG dispatchers + - Call "user microcode" dispatcher for unclaimed UIG instructions + + hp2100_cpu2.c (from Dave Bryan): + - Moved microcode function prototypes to hp2100_cpu1.h + - Removed option-present tests (now in UIG dispatchers) + - Updated mp_dms_jmp calling sequence + - Fixed DJP, SJP, and UJP jump target validation + - RVA/B conditionally updates dms_vr before returning value + + hp2100_cpu3.c (from Dave Bryan): + - Moved microcode function prototypes to hp2100_cpu1.h + - Removed option-present tests (now in UIG dispatchers) + - Updated mp_dms_jmp calling sequence + + hp2100_cpu4.c, hp2100_cpu7.c (from Dave Bryan): + - Moved microcode function prototypes to hp2100_cpu1.h + - Removed option-present tests (now in UIG dispatchers) + + hp2100_cpu5.c (from Dave Bryan): + - Moved microcode function prototypes to hp2100_cpu1.h + - Removed option-present tests (now in UIG dispatchers) + - Redefined ABORT to pass address, moved def to hp2100_cpu.h + - Rewrote device I/O to model backplane signals + + hp2100_cpu6.c (from Dave Bryan): + - Corrected .SIP debug formatting + - Moved microcode function prototypes to hp2100_cpu1.h + - Removed option-present tests (now in UIG dispatchers) + - Rewrote device I/O to model backplane signals + + hp2100 all peripherals (from Dave Bryan): + - Rewrote device I/O to model backplane signals + + hp2100_baci.c (from Dave Bryan): + - Fixed STC,C losing interrupt request on BREAK + - Changed Telnet poll to connect immediately after reset or attach + - Added REG_FIT to register variables < 32-bit size + - Moved fmt_char() function to hp2100_sys.c + + hp2100_dp.c, hp2100_dq.c (from Dave Bryan): + - Added REG_FIT to register variables < 32-bit size + + hp2100_dr.c (from Dave Bryan): + - Revised drc_boot to use ibl_copy + + hp2100_fp1.c (from Dave Bryan): + - Quieted bogus gcc warning in fp_exec + + hp2100_ipl.c (from Dave Bryan): + - Changed socket poll to connect immediately after reset or attach + - Revised EDT handler to refine completion delay conditions + - Revised ipl_boot to use ibl_copy + + hp2100_lpt.c (from Dave Bryan): + - Changed CTIME register width to match documentation + + hp2100_mpx.c (from Dave Bryan): + - Implemented 12792C eight-channel terminal multiplexer + + hp2100_ms.c (from Dave Bryan): + - Revised to use AR instead of saved_AR in boot + + hp2100_mt.c (from Dave Bryan): + - Fixed missing flag after CLR command + - Moved write enable and format commands from MTD to MTC + + hp2100_mux.c (from Dave Bryan): + - SHOW MUX CONN/STAT with SET MUX DIAG is no longer disallowed + - Changed Telnet poll to connect immediately after reset or attach + - Added LINEORDER support + - Added BREAK deferral to allow RTE break-mode to work + + hp2100_pif.c (from Dave Bryan): + - Implemented 12620A/12936A Privileged Interrupt Fences + + hp2100_sys.c (from Dave Bryan): + - Fixed IAK instruction dual-use mnemonic display + - Moved hp_setdev, hp_showdev from hp2100_cpu.c + - Changed sim_load to use WritePW instead of direct M[] access + - Added PIF device + - Moved fmt_char() function from hp2100_baci.c + - Added MPX device + + hp2100_cpu.h (from Dave Bryan): + - Rearranged declarations with hp2100_cpu.c and hp2100_defs.h + - Added mp_control to CPU state externals + + hp2100_cpu1.h (from Dave Bryan): + - Moved microcode function prototypes here + + hp2100_defs.h (from Dave Bryan): + - Added POLL_FIRST to indicate immediate connection attempt + - Rearranged declarations with hp2100_cpu.h + - Added PIF device + - Declared fmt_char() function + - Added MPX device + + i1401_cpu.c: + - fixed bug in ZA and ZS (from Bob Abeles) + - fixed tape indicator implementation (from Bob Abeles) + - added missing magtape modifier A (from Van Snyder) + + i1401_mt.c: + - added -n (no rewind) option to BOOT (from Van Snyder) + - fixed bug to mask input to 6b on read (from Bob Abeles) + + lgp_stddev.c: + - changed encode character from # to !, due to overlap + + pdp11_cpu.c: + - fixed failure to clear cpu_bme on RESET (found by Walter Mueller) + + pdp11_dz.c: + - added MTAB_NC modifier on SET LOG command (found by Walter Mueller) + + pdp11_io.c, vax_io.c, vax780_uba.c: + - revised to use PDP-11 I/O library + + pdp11_io_lib.c: + - created common library for Unibus/Qbus support routines + + pdp11_cis.c, vax_cis.c: + - fixed bug in ASHP left overflow calc (Word/NibbleLShift) + - fixed bug in DIVx (LntDstr calculation) + + sds_lp.c: + - fixed loss of carriage control position on space op + + vax_stddev.c, vax780_stddev.c + - modified to resync TODR on any clock reset + + 0 15-Jun-08 scp.c: - fixed bug in local/global register search (found by Mark Pizzolato) - fixed bug in restore of RO units (from Mark Pizzolato) - added SET/SHO/NO BR with default argument (from Dave Bryan) diff --git a/sim_sock.c b/sim_sock.c index 3bc95d9f..a5579a7c 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -1,6 +1,6 @@ /* sim_sock.c: OS-dependent socket routines - Copyright (c) 2001-2005, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -146,7 +146,8 @@ struct sockaddr_in name; int32 sta; newsock = sim_create_sock (); /* create socket */ -if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ +if (newsock == INVALID_SOCKET) /* socket error? */ + return newsock; name.sin_family = AF_INET; /* name socket */ name.sin_port = htons ((unsigned short) port); /* insert port */ @@ -171,7 +172,8 @@ struct sockaddr_in name; int32 sta; newsock = sim_create_sock (); /* create socket */ -if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ +if (newsock == INVALID_SOCKET) /* socket error? */ + return newsock; name.sin_family = AF_INET; /* name socket */ name.sin_port = htons ((unsigned short) port); /* insert port */ @@ -204,7 +206,8 @@ size_t size; SOCKET newsock; struct sockaddr_in clientname; -if (master == 0) return INVALID_SOCKET; /* not attached? */ +if (master == 0) /* not attached? */ + return INVALID_SOCKET; size = sizeof (clientname); newsock = accept (master, (struct sockaddr *) &clientname, &size); if (newsock == INVALID_SOCKET) { /* error? */ @@ -233,10 +236,13 @@ FD_ZERO (rw_p); FD_ZERO (er_p); FD_SET (sock, rw_p); FD_SET (sock, er_p); -if (rd) select ((int) sock + 1, rw_p, NULL, er_p, &tz); +if (rd) + select ((int) sock + 1, rw_p, NULL, er_p, &tz); else select ((int) sock + 1, NULL, rw_p, er_p, &tz); -if (FD_ISSET (sock, rw_p)) return 1; -if (FD_ISSET (sock, er_p)) return -1; +if (FD_ISSET (sock, rw_p)) + return 1; +if (FD_ISSET (sock, er_p)) + return -1; return 0; } @@ -245,10 +251,12 @@ 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) /* disconnect */ + return -1; if (rbytes == SOCKET_ERROR) { err = WSAGetLastError (); - if (err == WSAEWOULDBLOCK) return 0; /* no data */ + if (err == WSAEWOULDBLOCK) /* no data */ + return 0; printf ("Sockets: read error %d\n", err); return -1; } @@ -299,12 +307,15 @@ int32 sim_setnonblock (SOCKET sock) int32 fl, sta; fl = fcntl (sock, F_GETFL,0); /* get flags */ -if (fl == -1) return SOCKET_ERROR; +if (fl == -1) + return SOCKET_ERROR; sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK); /* set nonblock */ -if (sta == -1) return SOCKET_ERROR; +if (sta == -1) + return SOCKET_ERROR; #if !defined (macintosh) && !defined (__EMX__) /* Unix only */ sta = fcntl (sock, F_SETOWN, getpid()); /* set ownership */ -if (sta == -1) return SOCKET_ERROR; +if (sta == -1) + return SOCKET_ERROR; #endif return 0; } diff --git a/sim_sock.h b/sim_sock.h index 9ac90e34..5d469519 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -1,6 +1,6 @@ /* sim_sock.h: OS-dependent socket routines header file - Copyright (c) 2001-2009, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/sim_tape.c b/sim_tape.c index b53cc06d..c3a0c9b2 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -1,6 +1,6 @@ /* sim_tape.c: simulator tape support library - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ Ultimately, this will be a place to hide processing of various tape formats, as well as OS-specific direct hardware access. + 08-Jun-08 JDB Fixed signed/unsigned warning in sim_tape_set_fmt 23-Jan-07 JDB Fixed backspace over gap at BOT 22-Jan-07 RMS Fixed bug in P7B format read reclnt rev (found by Rich Cornwell) 15-Dec-06 RMS Added support for small capacity tapes @@ -99,12 +100,14 @@ 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 (*cptr == 0) /* must be more */ + return SCPE_2FARG; 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 (r != SCPE_OK) /* error? */ + return r; switch (MT_GET_FMT (uptr)) { /* case on format */ case MTUF_F_TPC: /* TPC */ @@ -138,11 +141,13 @@ uint32 f = MT_GET_FMT (uptr); t_stat r; r = detach_unit (uptr); /* detach unit */ -if (r != SCPE_OK) return r; +if (r != SCPE_OK) + return r; switch (f) { /* case on format */ case MTUF_F_TPC: /* TPC */ - if (uptr->filebuf) free (uptr->filebuf); /* free map */ + if (uptr->filebuf) /* free map */ + free (uptr->filebuf); uptr->filebuf = NULL; uptr->hwmark = 0; break; @@ -183,7 +188,8 @@ t_mtrlnt sbc; t_tpclnt tpcbc; MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return MTSE_UNATT; sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */ switch (f) { /* switch on fmt */ @@ -200,7 +206,8 @@ switch (f) { /* switch on fmt */ return MTSE_EOM; } uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over rec lnt */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ + if (*bc == MTR_TMK) /* tape mark? */ + return MTSE_TMK; if (*bc == MTR_FHGAP) { /* half gap? */ uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2; /* half space fwd */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* resync */ @@ -224,7 +231,8 @@ switch (f) { /* switch on fmt */ return MTSE_EOM; } uptr->pos = uptr->pos + sizeof (t_tpclnt); /* spc over reclnt */ - if (tpcbc == TPC_TMK) return MTSE_TMK; /* tape mark? */ + if (tpcbc == TPC_TMK) /* tape mark? */ + return MTSE_TMK; uptr->pos = uptr->pos + ((tpcbc + 1) & ~1); /* spc over record */ break; @@ -236,16 +244,20 @@ switch (f) { /* switch on fmt */ return sim_tape_ioerr (uptr); } if (feof (uptr->fileref)) { /* eof? */ - if (sbc == 0) return MTSE_EOM; /* no data? eom */ + if (sbc == 0) /* no data? eom */ + return MTSE_EOM; break; /* treat like eor */ } - if ((sbc != 0) && (c & P7B_SOR)) break; /* next record? */ - if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; + if ((sbc != 0) && (c & P7B_SOR)) /* next record? */ + break; + if ((c & P7B_DPAR) != 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? */ + if (all_eof) /* tape mark? */ + return MTSE_TMK; break; default: @@ -286,8 +298,10 @@ 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) /* not attached? */ + return MTSE_UNATT; +if (sim_tape_bot (uptr)) /* at BOT? */ + return MTSE_BOT; switch (f) { /* switch on fmt */ case MTUF_F_STD: case MTUF_F_E11: @@ -297,10 +311,13 @@ switch (f) { /* switch on fmt */ sbc = MTR_L (*bc); if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); - if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ + if (feof (uptr->fileref)) /* eof? */ + return MTSE_EOM; 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? */ + if (*bc == MTR_EOM) /* eom? */ + return MTSE_EOM; + if (*bc == MTR_TMK) /* tape mark? */ + return MTSE_TMK; if ((*bc & MTR_M_RHGAP) == MTR_RHGAP) { /* half gap? */ uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2; /* half space rev */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* resync */ @@ -323,9 +340,11 @@ switch (f) { /* switch on fmt */ *bc = tpcbc; /* save rec lnt */ if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); - if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ + if (feof (uptr->fileref)) /* eof? */ + return MTSE_EOM; uptr->pos = ppos; /* spc over record */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ + if (*bc == MTR_TMK) /* tape mark? */ + return MTSE_TMK; sim_fseek (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET); break; @@ -335,14 +354,18 @@ switch (f) { /* switch on fmt */ 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_DPAR) != P7B_EOF) all_eof = 0; - if (c & P7B_SOR) break; /* start of record? */ + if (feof (uptr->fileref)) /* eof? */ + return MTSE_EOM; + if ((c & P7B_DPAR) != P7B_EOF) + all_eof = 0; + if (c & P7B_SOR) /* start of record? */ + break; } uptr->pos = uptr->pos - sbc; /* update position */ *bc = sbc; /* save rec lnt */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ - if (all_eof) return MTSE_TMK; /* tape mark? */ + if (all_eof) /* tape mark? */ + return MTSE_TMK; break; default: @@ -381,21 +404,24 @@ t_addr opos; t_stat st; opos = uptr->pos; /* old position */ -if (st = sim_tape_rdlntf (uptr, &tbc)) return st; /* read rec lnt */ +if (st = sim_tape_rdlntf (uptr, &tbc)) /* read rec lnt */ + return st; *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 */ +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 */ +for ( ; i < rbc; i++) /* fill with 0's */ + buf[i] = 0; +if (f == MTUF_F_P7B) /* p7b? strip SOR */ + buf[0] = buf[0] & P7B_DPAR; return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); } @@ -427,14 +453,18 @@ 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 */ +if (st = sim_tape_rdlntr (uptr, &tbc)) /* read rec lnt */ + return st; *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 (rbc > max) /* rec out of range? */ + return MTSE_INVRL; +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 */ +for ( ; i < rbc; i++) /* fill with 0's */ + buf[i] = 0; +if (f == MTUF_F_P7B) /* p7b? strip SOR */ + buf[0] = buf[0] & P7B_DPAR; return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); } @@ -462,9 +492,12 @@ t_mtrlnt sbc; MT_CLR_PNU (uptr); sbc = MTR_L (bc); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (sim_tape_wrp (uptr)) return MTSE_WRP; /* write prot? */ -if (sbc == 0) return MTSE_OK; /* nothing to do? */ +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return MTSE_UNATT; +if (sim_tape_wrp (uptr)) /* write prot? */ + return MTSE_WRP; +if (sbc == 0) /* nothing to do? */ + return MTSE_OK; sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ switch (f) { /* case on format */ @@ -501,8 +534,10 @@ 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? */ +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return MTSE_UNATT; +if (sim_tape_wrp (uptr)) /* write prot? */ + return MTSE_WRP; sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ sim_fwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref); if (ferror (uptr->fileref)) { /* error? */ @@ -528,7 +563,8 @@ return sim_tape_wrdata (uptr, MTR_TMK); t_stat sim_tape_wreom (UNIT *uptr) { -if (MT_GET_FMT (uptr) == MTUF_F_P7B) return MTSE_FMT; /* cant do P7B */ +if (MT_GET_FMT (uptr) == MTUF_F_P7B) /* cant do P7B */ + return MTSE_FMT; return sim_tape_wrdata (uptr, MTR_EOM); } @@ -838,10 +874,12 @@ return MTSE_IOERR; t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, char *cptr, void *desc) { -int32 f; +uint32 f; -if (uptr == NULL) return SCPE_IERR; -if (cptr == NULL) return SCPE_ARG; +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) | @@ -858,7 +896,8 @@ t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, void *desc) { int32 f = MT_GET_FMT (uptr); -if (fmts[f].name) fprintf (st, "%s format", fmts[f].name); +if (fmts[f].name) + fprintf (st, "%s format", fmts[f].name); else fprintf (st, "invalid format"); return SCPE_OK; } @@ -871,12 +910,15 @@ t_addr tpos; t_tpclnt bc; uint32 i, objc; -if ((uptr == NULL) || (uptr->fileref == NULL)) return 0; +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; + if (i == 0) + break; + if (map) + map[objc] = tpos; objc++; tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt); } @@ -891,14 +933,16 @@ t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map) uint32 lo, hi, p; -if (map == NULL) return 0; +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 if (uptr->pos < map[p]) + hi = p - 1; else lo = p + 1; } while (lo <= hi); @@ -913,10 +957,13 @@ extern uint32 sim_taddr_64; t_addr cap; t_stat r; -if ((cptr == NULL) || (*cptr == 0)) return SCPE_ARG; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +if ((cptr == NULL) || (*cptr == 0)) + return SCPE_ARG; +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; cap = (t_addr) get_uint (cptr, 10, sim_taddr_64? 2000000: 2000, &r); -if (r != SCPE_OK) return SCPE_ARG; +if (r != SCPE_OK) + return SCPE_ARG; uptr->capac = cap * ((t_addr) 1000000); return SCPE_OK; } diff --git a/sim_tape.h b/sim_tape.h index dfaadce5..22eb4aac 100644 --- a/sim_tape.h +++ b/sim_tape.h @@ -1,6 +1,6 @@ /* sim_tape.h: simulator tape support library definitions - Copyright (c) 1993-2006, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/sim_timer.c b/sim_timer.c index d2dbfa7e..af84fd48 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -23,6 +23,7 @@ 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-Sep-08 RMS Added "stability threshold" for idle routine 27-May-08 RMS Fixed bug in Linux idle routines (from Walter Mueller) 18-Jun-07 RMS Modified idle to exclude counted delays 22-Mar-07 RMS Added sim_rtcn_init_all @@ -52,6 +53,7 @@ t_bool sim_idle_enab = FALSE; /* global flag */ static uint32 sim_idle_rate_ms = 0; +static uint32 sim_idle_stable = SIM_IDLE_STDFLT; static uint32 sim_throt_ms_start = 0; static uint32 sim_throt_ms_stop = 0; static uint32 sim_throt_type = 0; @@ -146,7 +148,8 @@ const t_bool rtc_avail = TRUE; uint32 sim_os_msec () { -if (sim_idle_rate_ms) return timeGetTime (); +if (sim_idle_rate_ms) + return timeGetTime (); else return GetTickCount (); } @@ -317,8 +320,10 @@ for (i = 0, tot = 0; i < sleep1Samples; i++) { tot += (t2 - t1); } tim = (tot + (sleep1Samples - 1)) / sleep1Samples; -if (tim == 0) tim = 1; -else if (tim > SIM_IDLE_MAX) tim = 0; +if (tim == 0) + tim = 1; +else if (tim > SIM_IDLE_MAX) + tim = 0; return tim; #endif @@ -347,6 +352,7 @@ 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 */ +static uint32 rtc_elapsed[SIM_NTIMERS] = { 0 }; /* sec since init */ void sim_rtcn_init_all (void) { @@ -360,8 +366,10 @@ return; int32 sim_rtcn_init (int32 time, int32 tmr) { -if (time == 0) time = 1; -if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return time; +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; @@ -370,6 +378,7 @@ rtc_hz[tmr] = 0; rtc_based[tmr] = time; rtc_currd[tmr] = time; rtc_initd[tmr] = time; +rtc_elapsed[tmr] = 0; return time; } @@ -378,12 +387,16 @@ int32 sim_rtcn_calb (int32 ticksper, int32 tmr) uint32 new_rtime, delta_rtime; int32 delta_vtime; -if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return 10000; +if ((tmr < 0) || (tmr >= SIM_NTIMERS)) + return 10000; rtc_hz[tmr] = ticksper; rtc_ticks[tmr] = rtc_ticks[tmr] + 1; /* count ticks */ -if (rtc_ticks[tmr] < ticksper) return rtc_currd[tmr]; /* 1 sec yet? */ +if (rtc_ticks[tmr] < ticksper) /* 1 sec yet? */ + return rtc_currd[tmr]; rtc_ticks[tmr] = 0; /* reset ticks */ -if (!rtc_avail) return rtc_currd[tmr]; /* no timer? */ +rtc_elapsed[tmr] = rtc_elapsed[tmr] + 1; /* count sec */ +if (!rtc_avail) /* no timer? */ + return rtc_currd[tmr]; new_rtime = sim_os_msec (); /* wall time */ if (new_rtime < rtc_rtime[tmr]) { /* time running backwards? */ rtc_rtime[tmr] = new_rtime; /* reset wall time */ @@ -399,13 +412,17 @@ if (delta_rtime == 0) /* gap too small? */ 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; +if (delta_vtime > SIM_TMAX) /* limit gap */ + delta_vtime = SIM_TMAX; +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! */ +if (rtc_based[tmr] <= 0) /* never negative or zero! */ + rtc_based[tmr] = 1; +if (rtc_currd[tmr] <= 0) /* never negative or zero! */ + rtc_currd[tmr] = 1; return rtc_currd[tmr]; } @@ -449,19 +466,23 @@ uint32 cyc_ms, w_ms, w_idle, act_ms; int32 act_cyc; if ((sim_clock_queue == NULL) || /* clock queue empty? */ - ((sim_clock_queue->flags & UNIT_IDLE) == 0)) { /* event not idle-able? */ - if (sin_cyc) sim_interval = sim_interval - 1; + ((sim_clock_queue->flags & UNIT_IDLE) == 0) || /* event not idle-able? */ + (rtc_elapsed[tmr] < sim_idle_stable)) { /* timer not stable? */ + if (sin_cyc) + sim_interval = sim_interval - 1; return FALSE; } cyc_ms = (rtc_currd[tmr] * rtc_hz[tmr]) / 1000; /* cycles per msec */ if ((sim_idle_rate_ms == 0) || (cyc_ms == 0)) { /* not possible? */ - if (sin_cyc) sim_interval = sim_interval - 1; + if (sin_cyc) + sim_interval = sim_interval - 1; return FALSE; } w_ms = (uint32) sim_interval / cyc_ms; /* ms to wait */ w_idle = w_ms / sim_idle_rate_ms; /* intervals to wait */ if (w_idle == 0) { /* none? */ - if (sin_cyc) sim_interval = sim_interval - 1; + if (sin_cyc) + sim_interval = sim_interval - 1; return FALSE; } act_ms = sim_os_ms_sleep (w_idle); /* wait */ @@ -476,14 +497,25 @@ return TRUE; t_stat sim_set_idle (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (sim_idle_rate_ms == 0) return SCPE_NOFNC; +t_stat r; +uint32 v; + +if (sim_idle_rate_ms == 0) + return SCPE_NOFNC; if ((val != 0) && (sim_idle_rate_ms > (uint32) val)) return SCPE_NOFNC; +if (cptr) { + v = (uint32) get_uint (cptr, 10, SIM_IDLE_STMAX, &r); + if ((r != SCPE_OK) || (v < SIM_IDLE_STMIN)) + return SCPE_ARG; + sim_idle_stable = v; + } sim_idle_enab = TRUE; if (sim_throt_type != SIM_THROT_NONE) { sim_set_throt (0, NULL); printf ("Throttling disabled\n"); - if (sim_log) fprintf (sim_log, "Throttling disabled\n"); + if (sim_log) + fprintf (sim_log, "Throttling disabled\n"); } return SCPE_OK; } @@ -500,7 +532,9 @@ return SCPE_OK; t_stat sim_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc) { -fprintf (st, sim_idle_enab? "idle enabled": "idle disabled"); +if (sim_idle_enab) + fprintf (st, "idle enabled, stability wait = %ds", sim_idle_stable); +else fputs ("idle disabled", st); return SCPE_OK; } @@ -512,24 +546,31 @@ char *tptr, c; t_value val; if (arg == 0) { - if ((cptr != 0) && (*cptr != 0)) return SCPE_ARG; + if ((cptr != 0) && (*cptr != 0)) + return SCPE_ARG; sim_throt_type = SIM_THROT_NONE; sim_throt_cancel (); } -else if (sim_idle_rate_ms == 0) return SCPE_NOFNC; +else if (sim_idle_rate_ms == 0) + return SCPE_NOFNC; else { val = strtotv (cptr, &tptr, 10); - if (cptr == tptr) return SCPE_ARG; + if (cptr == tptr) + return SCPE_ARG; c = toupper (*tptr++); - if (*tptr != 0) return SCPE_ARG; - if (c == 'M') sim_throt_type = SIM_THROT_MCYC; - else if (c == 'K') sim_throt_type = SIM_THROT_KCYC; + if (*tptr != 0) + return SCPE_ARG; + if (c == 'M') + sim_throt_type = SIM_THROT_MCYC; + else if (c == 'K') + sim_throt_type = SIM_THROT_KCYC; else if ((c == '%') && (val > 0) && (val < 100)) sim_throt_type = SIM_THROT_PCT; else return SCPE_ARG; if (sim_idle_enab) { printf ("Idling disabled\n"); - if (sim_log) fprintf (sim_log, "Idling disabled\n"); + if (sim_log) + fprintf (sim_log, "Idling disabled\n"); sim_clr_idle (NULL, 0, NULL, NULL); } sim_throt_val = (uint32) val; diff --git a/sim_timer.h b/sim_timer.h index c7660fd7..8447cbdd 100644 --- a/sim_timer.h +++ b/sim_timer.h @@ -1,6 +1,6 @@ /* sim_timer.h: simulator timer library headers - Copyright (c) 1993-2007, Robert M Supnik + Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -36,6 +36,9 @@ #define SIM_IDLE_CAL 10 /* ms to calibrate */ #define SIM_IDLE_MAX 10 /* max granularity idle */ +#define SIM_IDLE_STMIN 10 /* min sec for stability */ +#define SIM_IDLE_STDFLT 20 /* dft sec for stability */ +#define SIM_IDLE_STMAX 600 /* max sec for stability */ #define SIM_THROT_WINIT 1000 /* cycles to skip */ #define SIM_THROT_WST 10000 /* initial wait */ diff --git a/sim_tmxr.c b/sim_tmxr.c index 16b958a0..b7ff0fdd 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1,6 +1,6 @@ /* sim_tmxr.c: Telnet terminal multiplexor library - Copyright (c) 2001-2007, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,11 @@ Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. + 20-Nov-08 RMS Added three new standardized SHOW routines + 30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation + 27-May-08 JDB Added line connection order to tmxr_poll_conn, + added tmxr_set_lnorder and tmxr_show_lnorder + 14-May-08 JDB Print device and line to which connection was made 11-Apr-07 JDB Worked around Telnet negotiation problem with QCTerm 16-Aug-05 RMS Fixed C++ declaration and cast problems 29-Jun-05 RMS Extended tmxr_dscln to support unit array devices @@ -67,6 +72,8 @@ tmxr_dscln - disconnect line (SET routine) tmxr_rqln - number of available characters for line tmxr_tqln - number of buffered characters for line + tmxr_set_lnorder - set line connection order + tmxr_show_lnorder - show line connection order All routines are OS-independent. */ @@ -74,6 +81,7 @@ #include "sim_defs.h" #include "sim_sock.h" #include "sim_tmxr.h" +#include "scp.h" #include /* Telnet protocol constants - negatives are for init'ing signed char data */ @@ -118,13 +126,18 @@ extern uint32 sim_os_msec (void); *mp = pointer to terminal multiplexor descriptor Outputs: line number activated, -1 if none + + If a connection order is defined for the descriptor, and the first value is + not -1 (indicating default order), then the order array is used to find an + open line. Otherwise, a search is made of all lines in numerical sequence. */ int32 tmxr_poll_conn (TMXR *mp) { SOCKET newsock; TMLN *lp; -int32 i; +int32 *op; +int32 i, j; uint32 ipaddr; static char mantra[] = { TN_IAC, TN_WILL, TN_LINE, @@ -136,10 +149,20 @@ static char mantra[] = { 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? */ + op = mp->lnorder; /* get line connection order list pointer */ + i = mp->lines; /* play it safe in case lines == 0 */ + + for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */ + if (op && (*op >= 0) && (*op < mp->lines)) /* order list present and valid? */ + i = *op++; /* get next line in list to try */ + else /* no list or not used or range error */ + i = j; /* get next sequential line */ + + lp = mp->ldsc + i; /* get pointer to line descriptor */ + if (lp->conn == 0) /* is the line available? */ + break; /* yes, so stop search */ } + if (i >= mp->lines) { /* all busy? */ tmxr_msg (newsock, "All connections busy\r\n"); sim_close_sock (newsock, 0); @@ -158,7 +181,23 @@ if (newsock != INVALID_SOCKET) { /* got a live one? */ 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_linemsg (lp, " simulator "); + + if (mp->dptr) { /* device defined? */ + tmxr_linemsg (lp, sim_dname (mp->dptr)); /* report device name */ + tmxr_linemsg (lp, " device"); + + if (mp->lines > 1) { /* more than one line? */ + char line[20]; + + tmxr_linemsg (lp, ", line "); /* report the line number */ + sprintf (line, "%i", i); + tmxr_linemsg (lp, line); + } + } + + tmxr_linemsg (lp, "\r\n\n"); + tmxr_poll_tx (mp); /* flush output */ return i; } @@ -170,7 +209,8 @@ return -1; void tmxr_reset_ln (TMLN *lp) { -if (lp->txlog) fflush (lp->txlog); /* dump log */ +if (lp->txlog) /* dump log */ + fflush (lp->txlog); tmxr_send_buffered_data (lp); /* send buffered data */ sim_close_sock (lp->conn, 0); /* reset conn */ lp->conn = lp->tsta = 0; /* reset state */ @@ -199,7 +239,8 @@ if (lp->conn && lp->rcve) { /* conn & enb? */ 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? */ + if (lp->rbr[lp->rxbpr]) /* break? */ + val = val | SCPE_BREAK; lp->rxbpr = lp->rxbpr + 1; /* adv pointer */ } } /* end if conn */ @@ -222,7 +263,8 @@ 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 */ + if (!lp->conn || !lp->rcve) /* skip if !conn */ + continue; nbytes = 0; if (lp->rxbpi == 0) /* need input? */ @@ -233,7 +275,8 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ 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 */ + if (nbytes < 0) /* closed? reset ln */ + tmxr_reset_ln (lp); else if (nbytes > 0) { /* if data rcvd */ j = lp->rxbpi; /* start of data */ memset (&lp->rbr[j], 0, nbytes); /* clear status */ @@ -280,7 +323,8 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ case TNS_WILL: case TNS_WONT: /* IAC+WILL/WONT prev */ if (tmp == TN_BIN) { /* BIN? */ - if (lp->tsta == TNS_WILL) lp->dstb = 0; + if (lp->tsta == TNS_WILL) + lp->dstb = 0; else lp->dstb = 1; } @@ -297,7 +341,7 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ strip it only if it is LF or NUL. This should not affect conforming clients. */ - + case TNS_CRPAD: /* only LF or NUL should follow CR */ lp->tsta = TNS_NORM; /* next normal */ if ((tmp == TN_LF) || /* CR + LF ? */ @@ -351,16 +395,20 @@ return; 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 (lp->txlog) /* log if available */ + fputc (chr, lp->txlog); +if (lp->conn == 0) /* no conn? lost */ + return SCPE_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 (lp->txbpi >= TMXR_MAXBUF) /* wrap? */ + lp->txbpi = 0; 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? */ + lp->txbpi = lp->txbpi + 1; /* adv pointer */ + if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */ + lp->txbpi = 0; } if (tmxr_tqln (lp) > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */ lp->xmte = 0; /* disable line */ @@ -385,9 +433,11 @@ 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 */ + if (lp->conn == 0) /* skip if !conn */ + continue; nbytes = tmxr_send_buffered_data (lp); /* buffered bytes */ - if (nbytes == 0) lp->xmte = 1; /* buf empty? enab line */ + if (nbytes == 0) /* buf empty? enab line */ + lp->xmte = 1; } /* end for */ return; } @@ -413,7 +463,8 @@ if (nbytes) { /* >0? write */ &(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? */ + if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */ + lp->txbpr = 0; lp->txcnt = lp->txcnt + sbytes; /* update counts */ nbytes = nbytes - sbytes; } @@ -421,7 +472,8 @@ if (nbytes) { /* >0? write */ 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? */ + if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */ + lp->txbpr = 0; lp->txcnt = lp->txcnt + sbytes; /* update counts */ nbytes = nbytes - sbytes; } @@ -447,12 +499,14 @@ TMLN *lp; t_stat r; port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */ -if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG; +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 */ +if (sock == INVALID_SOCKET) /* open error */ + return SCPE_OPENERR; 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); +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 */ @@ -475,7 +529,8 @@ char* tptr; t_stat r; tptr = (char *) malloc (strlen (cptr) + 1); /* get string buf */ -if (tptr == NULL) return SCPE_MEM; /* no more mem? */ +if (tptr == NULL) /* no more mem? */ + return SCPE_MEM; r = tmxr_open_master (mp, cptr); /* open master socket */ if (r != SCPE_OK) { /* error? */ free (tptr); /* release buf */ @@ -484,6 +539,10 @@ if (r != SCPE_OK) { /* error? */ strcpy (tptr, cptr); /* copy port */ uptr->filename = tptr; /* save */ uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */ + +if (mp->dptr == NULL) /* has device been set? */ + mp->dptr = find_dev_from_unit (uptr); /* no, so set device now */ + return SCPE_OK; } @@ -512,7 +571,8 @@ return SCPE_OK; t_stat tmxr_detach (TMXR *mp, UNIT *uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; tmxr_close_master (mp); /* close master socket */ free (uptr->filename); /* free port string */ uptr->filename = NULL; @@ -536,7 +596,8 @@ return SCPE_NOFNC; void tmxr_msg (SOCKET sock, char *msg) { -if (sock) sim_write_sock (sock, msg, strlen (msg)); +if (sock) + sim_write_sock (sock, msg, strlen (msg)); return; } @@ -553,7 +614,8 @@ return; void tmxr_fconns (FILE *st, TMLN *lp, int32 ln) { -if (ln >= 0) fprintf (st, "line %d: ", ln); +if (ln >= 0) + fprintf (st, "line %d: ", ln); if (lp->conn) { int32 o1, o2, o3, o4, hr, mn, sc; uint32 ctime; @@ -567,10 +629,12 @@ if (lp->conn) { 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); + 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); +if (lp->txlog) + fprintf (st, "Logging to %s\n", lp->txlogname); return; } @@ -581,7 +645,8 @@ void tmxr_fstats (FILE *st, TMLN *lp, int32 ln) static const char *enab = "on"; static const char *dsab = "off"; -if (ln >= 0) fprintf (st, "line %d: ", ln); +if (ln >= 0) + fprintf (st, "line %d: ", ln); if (lp->conn) { fprintf (st, "input (%s) queued/total = %d/%d, ", (lp->rcve? enab: dsab), @@ -603,16 +668,20 @@ TMLN *lp; int32 ln; t_stat r; -if (mp == NULL) return SCPE_IERR; +if (mp == NULL) + return SCPE_IERR; if (val) { /* = n form */ - if (cptr == NULL) return SCPE_ARG; + if (cptr == NULL) + return SCPE_ARG; ln = (int32) get_uint (cptr, 10, mp->lines - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; + 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 == NULL) + return SCPE_IERR; } if (lp->conn) { tmxr_linemsg (lp, "\r\nOperator disconnected line\r\n\n"); @@ -628,12 +697,16 @@ 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? */ +if (cptr == NULL) /* no file name? */ + return SCPE_2FARG; 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 */ +if (lp == NULL) + return SCPE_IERR; +if (lp->txlog) /* close existing log */ + tmxr_set_nolog (NULL, val, NULL, desc); lp->txlogname = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */ -if (lp->txlogname == NULL) return SCPE_MEM; /* can't? */ +if (lp->txlogname == NULL) /* can't? */ + return SCPE_MEM; strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */ lp->txlog = fopen (cptr, "ab"); /* open log */ if (lp->txlog == NULL) { /* error? */ @@ -650,9 +723,11 @@ 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 */ +if (cptr) /* no arguments */ + return SCPE_2MARG; lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ -if (lp == NULL) return SCPE_IERR; +if (lp == NULL) + return SCPE_IERR; if (lp->txlog) { /* logging? */ fclose (lp->txlog); /* close log */ free (lp->txlogname); /* free namebuf */ @@ -670,21 +745,254 @@ TMXR *mp = (TMXR *) desc; TMLN *lp; 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); +if (lp == NULL) + return SCPE_IERR; +if (lp->txlog) + fprintf (st, "logging to %s", lp->txlogname); else fprintf (st, "no logging"); return SCPE_OK; } -/* Find line descriptor */ +/* Find line descriptor. + + Note: This routine may be called with a UNIT that does not belong to the + device indicated in the TMXR structure. That is, the multiplexer lines may + belong to a device other than the one attached to the socket (the HP 2100 MUX + device is one example). Therefore, we must look up the device from the unit + at each call, rather than depending on the DPTR stored in the TMXR. +*/ 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?? */ + if (dptr == NULL) /* what?? */ + return NULL; val = (int32) (uptr - dptr->units); /* implicit line # */ } -if ((val < 0) || (val >= mp->lines)) return NULL; /* invalid line? */ +if ((val < 0) || (val >= mp->lines)) /* invalid line? */ + return NULL; return mp->ldsc + val; /* line descriptor */ } + +/* Set the line connection order. + + Example command for eight-line multiplexer: + + SET LINEORDER=1;5;2-4;7 + + Resulting connection order: 1,5,2,3,4,7,0,6. + + Parameters: + - uptr = (not used) + - val = (not used) + - cptr = pointer to first character of range specification + - desc = pointer to multiplexer's TMXR structure + + On entry, cptr points to the value portion of the command string, which may + be either a semicolon-separated list of line ranges or the keyword ALL. + + If a line connection order array is not defined in the multiplexer + descriptor, the command is rejected. If the specified range encompasses all + of the lines, the first value of the connection order array is set to -1 to + indicate sequential connection order. Otherwise, the line values in the + array are set to the order specified by the command string. All values are + populated, first with those explicitly specified in the command string, and + then in ascending sequence with those not specified. + + If an error occurs, the original line order is not disturbed. +*/ + +t_stat tmxr_set_lnorder (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +TMXR *mp = (TMXR *) desc; +char *tptr; +t_addr low, high, max = (t_addr) mp->lines - 1; +int32 *list; +t_bool *set; +uint32 line, idx = 0; +t_stat result = SCPE_OK; + +if (mp->lnorder == NULL) /* line connection order undefined? */ + return SCPE_NXPAR; /* "Non-existent parameter" error */ + +else if ((cptr == NULL) || (*cptr == '\0')) /* line range not supplied? */ + return SCPE_MISVAL; /* "Missing value" error */ + +list = (int32 *) calloc (mp->lines, sizeof (int32)); /* allocate new line order array */ + +if (list == NULL) /* allocation failed? */ + return SCPE_MEM; /* report it */ + +set = (t_bool *) calloc (mp->lines, sizeof (t_bool)); /* allocate line set tracking array */ + +if (set == NULL) { /* allocation failed? */ + free (list); /* free successful list allocation */ + return SCPE_MEM; /* report it */ + } + +tptr = cptr + strlen (cptr); /* append a semicolon */ +*tptr++ = ';'; /* to the command string */ +*tptr = '\0'; /* to make parsing easier for get_range */ + +while (*cptr) { /* parse command string */ + cptr = get_range (NULL, cptr, &low, &high, 10, max, ';'); /* get a line range */ + + if (cptr == NULL) { /* parsing error? */ + result = SCPE_ARG; /* "Invalid argument" error */ + break; + } + + else if ((low > max) || (high > max)) { /* line out of range? */ + result = SCPE_SUB; /* "Subscript out of range" error */ + break; + } + + else if ((low == 0) && (high == max)) { /* entire line range specified? */ + list [0] = -1; /* set sequential order flag */ + idx = (uint32) max + 1; /* indicate no fill-in needed */ + break; + } + + else + for (line = (uint32) low; line <= (uint32) high; line++) /* see if previously specified */ + if (set [line] == FALSE) { /* not already specified? */ + set [line] = TRUE; /* now it is */ + list [idx] = line; /* add line to connection order */ + idx = idx + 1; /* bump "specified" count */ + } + } + +if (result == SCPE_OK) { /* assignment successful? */ + if (idx <= max) /* any lines not specified? */ + for (line = 0; line <= max; line++) /* fill them in sequentially */ + if (set [line] == FALSE) { /* specified? */ + list [idx] = line; /* no, so add it */ + idx = idx + 1; + } + + memcpy (mp->lnorder, list, mp->lines * sizeof (int32)); /* copy working array to connection array */ + } + +free (list); /* free list allocation */ +free (set); /* free set allocation */ + +return result; +} + +/* Show line connection order. + + Parameters: + - st = stream on which output is to be written + - uptr = (not used) + - val = (not used) + - desc = pointer to multiplexer's TMXR structure + + If a connection order array is not defined in the multiplexer descriptor, the + command is rejected. If the first value of the connection order array is set + to -1, then the connection order is sequential. Otherwise, the line values + in the array are printed as a semicolon-separated list. Ranges are printed + where possible to shorten the output. +*/ + +t_stat tmxr_show_lnorder (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i, j, low, last; +TMXR *mp = (TMXR *) desc; +int32 *iptr = mp->lnorder; +t_bool first = TRUE; + +if (iptr == NULL) /* connection order undefined? */ + return SCPE_NXPAR; /* "Non-existent parameter" error */ + +if (*iptr < 0) /* sequential order indicated? */ + fprintf (st, "Order=0-%d\n", mp->lines - 1); /* print full line range */ + +else { + low = last = *iptr++; /* set first line value */ + + for (j = 1; j <= mp->lines; j++) { /* print remaining lines in order list */ + if (j < mp->lines) /* more lines to process? */ + i = *iptr++; /* get next line in list */ + else /* final iteration */ + i = -1; /* get "tie-off" value */ + + if (i != last + 1) { /* end of a range? */ + if (first) { /* first line to print? */ + fputs ("Order=", st); /* print header */ + first = FALSE; + } + + else /* not first line printed */ + fputc (';', st); /* print separator */ + + if (low == last) /* range null? */ + fprintf (st, "%d", last); /* print single line value */ + + else /* range established */ + fprintf (st, "%d-%d", low, last); /* print start and end line */ + + low = i; /* start new range */ + } + + last = i; /* note value for range check */ + } + } + +if (first == FALSE) /* sanity check for lines == 0 */ + fputc ('\n', st); + +return SCPE_OK; +} + +/* Show summary processor */ + +t_stat tmxr_show_summ (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +TMXR *mp = (TMXR *) desc; +int32 i, t; + +if (mp == NULL) + return SCPE_IERR; +for (i = t = 0; i < mp->lines; i++) + t = t + (mp->ldsc[i].conn != 0); +if (t == 1) + fprintf (st, "1 connection"); +else fprintf (st, "%d connections", t); +return SCPE_OK; +} + +/* Show conn/stat processor */ + +t_stat tmxr_show_cstat (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +TMXR *mp = (TMXR *) desc; +int32 i, any; + +if (mp == NULL) + return SCPE_IERR; +for (i = any = 0; i < mp->lines; i++) { + if (mp->ldsc[i].conn) { + any++; + if (val) + tmxr_fconns (st, &mp->ldsc[i], i); + else tmxr_fstats (st, &mp->ldsc[i], i); + } + } +if (any == 0) + fprintf (st, (mp->lines == 1? "disconnected\n": "all disconnected\n")); +return SCPE_OK; +} + +/* Show number of lines */ + +t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +TMXR *mp = (TMXR *) desc; + +if (mp == NULL) + return SCPE_IERR; +fprintf (st, "lines=%d", mp->lines); +return SCPE_OK; +} + diff --git a/sim_tmxr.h b/sim_tmxr.h index c9a299e0..55399840 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -1,6 +1,6 @@ /* sim_tmxr.h: terminal multiplexor definitions - Copyright (c) 2001-2005, Robert M Supnik + Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,10 @@ Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. + 20-Nov-08 RMS Added three new standardized SHOW routines + 27-May-08 JDB Added lnorder to TMXR structure, + added tmxr_set_lnorder and tmxr_set_lnorder + 14-May-08 JDB Added dptr to TMXR structure 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 @@ -72,6 +76,8 @@ struct tmxr { int32 port; /* listening port */ SOCKET master; /* master socket */ TMLN *ldsc; /* line descriptors */ + int32 *lnorder; /* line connection order */ + DEVICE *dptr; /* multiplexer device */ }; typedef struct tmxr TMXR; @@ -98,6 +104,11 @@ t_stat tmxr_show_log (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat tmxr_dscln (UNIT *uptr, int32 val, char *cptr, void *desc); int32 tmxr_rqln (TMLN *lp); int32 tmxr_tqln (TMLN *lp); +t_stat tmxr_set_lnorder (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat tmxr_show_lnorder (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat tmxr_show_summ (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat tmxr_show_cstat (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc); #endif