1 /* 2 * Z80SIM - a Z80-CPU simulator 3 * 4 * Copyright (C) 1987-2021 by Udo Munk 5 * 6 * History: 7 * 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3 8 * 11-JAN-89 Release 1.1 9 * 08-FEB-89 Release 1.2 10 * 13-MAR-89 Release 1.3 11 * 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30 12 * 20-DEC-90 Release 1.5 Ported to COHERENT 3.0 13 * 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2 14 * and some optimisation 15 * 25-JUN-92 Release 1.7 comments in english and ported to COHERENT 4.0 16 * 02-OCT-06 Release 1.8 modified to compile on modern POSIX OS's 17 * 18-NOV-06 Release 1.9 modified to work with CP/M sources 18 * 08-DEC-06 Release 1.10 modified MMU for working with CP/NET 19 * 17-DEC-06 Release 1.11 TCP/IP sockets for CP/NET 20 * 25-DEC-06 Release 1.12 CPU speed option 21 * 19-FEB-07 Release 1.13 various improvements 22 * 06-OCT-07 Release 1.14 bug fixes and improvements 23 * 06-AUG-08 Release 1.15 many improvements and Windows support via Cygwin 24 * 25-AUG-08 Release 1.16 console status I/O loop detection and line discipline 25 * 20-OCT-08 Release 1.17 frontpanel integrated and Altair/IMSAI emulations 26 * 24-JAN-14 Release 1.18 bug fixes and improvements 27 * 02-MAR-14 Release 1.19 source cleanup and improvements 28 * 14-MAR-14 Release 1.20 added Tarbell SD FDC and printer port to Altair 29 * 29-MAR-14 Release 1.21 many improvements 30 * 29-MAY-14 Release 1.22 improved networking and bugfixes 31 * 04-JUN-14 Release 1.23 added 8080 emulation 32 * 06-SEP-14 Release 1.24 bugfixes and improvements 33 * 18-FEB-15 Release 1.25 bugfixes, improvements, added Cromemco Z-1 34 * 18-APR-15 Release 1.26 bugfixes and improvements 35 * 18-JAN-16 Release 1.27 bugfixes and improvements 36 * 05-MAY-16 Release 1.28 improved usability 37 * 20-NOV-16 Release 1.29 bugfixes and improvements 38 * 15-DEC-16 Release 1.30 improved memory management, machine cycle correct CPUs 39 * 28-DEC-16 Release 1.31 improved memory management, reimplemented MMUs 40 * 12-JAN-17 Release 1.32 improved configurations, front panel, added IMSAI VIO 41 * 07-FEB-17 Release 1.33 bugfixes, improvements, better front panels 42 * 16-MAR-17 Release 1.34 improvements, added ProcTec VDM-1 43 * 03-AUG-17 Release 1.35 added UNIX sockets, bugfixes, improvements 44 * 21-DEC-17 Release 1.36 bugfixes and improvements 45 * 06-JAN-21 Release 1.37 bugfixes and improvements 46 */ 47 48 /* 49 * This module contains the global variables other than memory management 50 */ 51 52 #include <stddef.h> 53 #include "sim.h" 54 55 #define MAXCHAN 5 /* max number of channels for I/O busy detect */ 56 57 /* 58 * Type of CPU, either Z80 or 8080 59 */ 60 int cpu = DEFAULT_CPU; 61 62 /* 63 * CPU Registers 64 */ 65 BYTE A,B,C,D,E,H,L; /* primary registers */ 66 int F; /* normally 8-Bit, but int is faster */ 67 WORD IX, IY; /* Z80 index registers */ 68 BYTE A_,B_,C_,D_,E_,H_,L_; /* Z80 alternate registers */ 69 int F_; 70 WORD PC; /* programm counter */ 71 WORD SP; /* stackpointer */ 72 BYTE I; /* Z80 interrupt register */ 73 BYTE IFF; /* interrupt flags */ 74 long R; /* Z80 refresh register */ 75 /* is normally a 8 bit register */ 76 /* the larger bits are used to measure the */ 77 /* clock frequency */ 78 79 #ifdef BUS_8080 80 BYTE cpu_bus; /* CPU bus status, for frontpanels */ 81 int m1_step; /* flag for waiting at M1 in single step */ 82 #endif 83 84 BYTE io_port; /* I/O port used */ 85 BYTE io_data; /* data on I/O port */ 86 int busy_loop_cnt[MAXCHAN]; /* counters for I/O busy loop detection */ 87 88 BYTE cpu_state; /* state of CPU emulation */ 89 int cpu_error; /* error status of CPU emulation */ 90 int int_mode; /* CPU interrupt mode (IM 0, IM 1, IM 2) */ 91 int int_nmi; /* non maskable interrupt request */ 92 int int_int; /* interrupt request */ 93 int int_data = -1; /* data from interrupting device on data bus */ 94 int int_protection; /* to delay interrupts after EI */ 95 BYTE bus_request; /* request address/data bus from CPU */ 96 int tmax; /* max t-states to execute in 10ms */ 97 int cpu_needed; /* don't adjust CPU freq if needed */ 98 99 /* 100 * Variables for history memory 101 */ 102 #ifdef HISIZE 103 struct history his[HISIZE]; /* memory to hold trace informations */ 104 int h_next; /* index into trace memory */ 105 int h_flag; /* flag for trace memory overrun */ 106 #endif 107 108 /* 109 * Variables for breakpoint memory 110 */ 111 #ifdef SBSIZE 112 struct softbreak soft[SBSIZE]; /* memory to hold breakpoint informations */ 113 int sb_next; /* index into breakpoint memory */ 114 #endif 115 116 /* 117 * Variables for runtime measurement 118 */ 119 long t_states; /* number of counted T states */ 120 int t_flag; /* flag, 1 = on, 0 = off */ 121 WORD t_start = 65535; /* start address for measurement */ 122 WORD t_end = 65535; /* end address for measurement */ 123 124 /* 125 * Variables for frontpanel emulation 126 */ 127 #ifdef FRONTPANEL 128 unsigned long long fp_clock; /* simulation clock */ 129 float fp_fps = 30.0; /* frame rate, default 30 usually works */ 130 WORD fp_led_address; /* lights for address bus */ 131 BYTE fp_led_data; /* lights for data bus */ 132 WORD address_switch; /* address and programmed input switches */ 133 BYTE fp_led_output = 0xff; /* IMSAI/Cromemco programmed output, inverted */ 134 #endif 135 136 /* 137 * Flags to control operation of simulation 138 */ 139 int s_flag; /* flag for -s option */ 140 int l_flag; /* flag for -l option */ 141 int m_flag = -1; /* flag for -m option */ 142 int x_flag; /* flag for -x option */ 143 int i_flag; /* flag for -i option */ 144 int f_flag; /* flag for -f option */ 145 int u_flag; /* flag for -u option */ 146 int r_flag; /* flag for -r option */ 147 148 /* 149 * Variables for configuration and disk images 150 */ 151 char xfn[MAX_LFN]; /* buffer for filename (option -x) */ 152 char *diskdir = NULL; /* path for disk images (option -d) */ 153 char diskd[MAX_LFN]; /* disk image directory in use */ 154 char confdir[MAX_LFN]; /* path for configuration files */ 155 156 /* 157 * Precompiled table to get parity as fast as possible 158 */ 159 int parity[256] = { 160 0 /* 00000000 */, 1 /* 00000001 */, 1 /* 00000010 */, 161 0 /* 00000011 */, 1 /* 00000100 */, 0 /* 00000101 */, 162 0 /* 00000110 */, 1 /* 00000111 */, 1 /* 00001000 */, 163 0 /* 00001001 */, 0 /* 00001010 */, 1 /* 00001011 */, 164 0 /* 00001100 */, 1 /* 00001101 */, 1 /* 00001110 */, 165 0 /* 00001111 */, 1 /* 00010000 */, 0 /* 00010001 */, 166 0 /* 00010010 */, 1 /* 00010011 */, 0 /* 00010100 */, 167 1 /* 00010101 */, 1 /* 00010110 */, 0 /* 00010111 */, 168 0 /* 00011000 */, 1 /* 00011001 */, 1 /* 00011010 */, 169 0 /* 00011011 */, 1 /* 00011100 */, 0 /* 00011101 */, 170 0 /* 00011110 */, 1 /* 00011111 */, 1 /* 00100000 */, 171 0 /* 00100001 */, 0 /* 00100010 */, 1 /* 00100011 */, 172 0 /* 00100100 */, 1 /* 00100101 */, 1 /* 00100110 */, 173 0 /* 00100111 */, 0 /* 00101000 */, 1 /* 00101001 */, 174 1 /* 00101010 */, 0 /* 00101011 */, 1 /* 00101100 */, 175 0 /* 00101101 */, 0 /* 00101110 */, 1 /* 00101111 */, 176 0 /* 00110000 */, 1 /* 00110001 */, 1 /* 00110010 */, 177 0 /* 00110011 */, 1 /* 00110100 */, 0 /* 00110101 */, 178 0 /* 00110110 */, 1 /* 00110111 */, 1 /* 00111000 */, 179 0 /* 00111001 */, 0 /* 00111010 */, 1 /* 00111011 */, 180 0 /* 00111100 */, 1 /* 00111101 */, 1 /* 00111110 */, 181 0 /* 00111111 */, 1 /* 01000000 */, 0 /* 01000001 */, 182 0 /* 01000010 */, 1 /* 01000011 */, 0 /* 01000100 */, 183 1 /* 01000101 */, 1 /* 01000110 */, 0 /* 01000111 */, 184 0 /* 01001000 */, 1 /* 01001001 */, 1 /* 01001010 */, 185 0 /* 01001011 */, 1 /* 01001100 */, 0 /* 01001101 */, 186 0 /* 01001110 */, 1 /* 01001111 */, 0 /* 01010000 */, 187 1 /* 01010001 */, 1 /* 01010010 */, 0 /* 01010011 */, 188 1 /* 01010100 */, 0 /* 01010101 */, 0 /* 01010110 */, 189 1 /* 01010111 */, 1 /* 01011000 */, 0 /* 01011001 */, 190 0 /* 01011010 */, 1 /* 01011011 */, 0 /* 01011100 */, 191 1 /* 01011101 */, 1 /* 01011110 */, 0 /* 01011111 */, 192 0 /* 01100000 */, 1 /* 01100001 */, 1 /* 01100010 */, 193 0 /* 01100011 */, 1 /* 01100100 */, 0 /* 01100101 */, 194 0 /* 01100110 */, 1 /* 01100111 */, 1 /* 01101000 */, 195 0 /* 01101001 */, 0 /* 01101010 */, 1 /* 01101011 */, 196 0 /* 01101100 */, 1 /* 01101101 */, 1 /* 01101110 */, 197 0 /* 01101111 */, 1 /* 01110000 */, 0 /* 01110001 */, 198 0 /* 01110010 */, 1 /* 01110011 */, 0 /* 01110100 */, 199 1 /* 01110101 */, 1 /* 01110110 */, 0 /* 01110111 */, 200 0 /* 01111000 */, 1 /* 01111001 */, 1 /* 01111010 */, 201 0 /* 01111011 */, 1 /* 01111100 */, 0 /* 01111101 */, 202 0 /* 01111110 */, 1 /* 01111111 */, 203 1 /* 10000000 */, 0 /* 10000001 */, 0 /* 10000010 */, 204 1 /* 10000011 */, 0 /* 10000100 */, 1 /* 10000101 */, 205 1 /* 10000110 */, 0 /* 10000111 */, 0 /* 10001000 */, 206 1 /* 10001001 */, 1 /* 10001010 */, 0 /* 10001011 */, 207 1 /* 10001100 */, 0 /* 10001101 */, 0 /* 10001110 */, 208 1 /* 10001111 */, 0 /* 10010000 */, 1 /* 10010001 */, 209 1 /* 10010010 */, 0 /* 10010011 */, 1 /* 10010100 */, 210 0 /* 10010101 */, 0 /* 10010110 */, 1 /* 10010111 */, 211 1 /* 10011000 */, 0 /* 10011001 */, 0 /* 10011010 */, 212 1 /* 10011011 */, 0 /* 10011100 */, 1 /* 10011101 */, 213 1 /* 10011110 */, 0 /* 10011111 */, 0 /* 10100000 */, 214 1 /* 10100001 */, 1 /* 10100010 */, 0 /* 10100011 */, 215 1 /* 10100100 */, 0 /* 10100101 */, 0 /* 10100110 */, 216 1 /* 10100111 */, 1 /* 10101000 */, 0 /* 10101001 */, 217 0 /* 10101010 */, 1 /* 10101011 */, 0 /* 10101100 */, 218 1 /* 10101101 */, 1 /* 10101110 */, 0 /* 10101111 */, 219 1 /* 10110000 */, 0 /* 10110001 */, 0 /* 10110010 */, 220 1 /* 10110011 */, 0 /* 10110100 */, 1 /* 10110101 */, 221 1 /* 10110110 */, 0 /* 10110111 */, 0 /* 10111000 */, 222 1 /* 10111001 */, 1 /* 10111010 */, 0 /* 10111011 */, 223 1 /* 10111100 */, 0 /* 10111101 */, 0 /* 10111110 */, 224 1 /* 10111111 */, 0 /* 11000000 */, 1 /* 11000001 */, 225 1 /* 11000010 */, 0 /* 11000011 */, 1 /* 11000100 */, 226 0 /* 11000101 */, 0 /* 11000110 */, 1 /* 11000111 */, 227 1 /* 11001000 */, 0 /* 11001001 */, 0 /* 11001010 */, 228 1 /* 11001011 */, 0 /* 11001100 */, 1 /* 11001101 */, 229 1 /* 11001110 */, 0 /* 11001111 */, 1 /* 11010000 */, 230 0 /* 11010001 */, 0 /* 11010010 */, 1 /* 11010011 */, 231 0 /* 11010100 */, 1 /* 11010101 */, 1 /* 11010110 */, 232 0 /* 11010111 */, 0 /* 11011000 */, 1 /* 11011001 */, 233 1 /* 11011010 */, 0 /* 11011011 */, 1 /* 11011100 */, 234 0 /* 11011101 */, 0 /* 11011110 */, 1 /* 11011111 */, 235 1 /* 11100000 */, 0 /* 11100001 */, 0 /* 11100010 */, 236 1 /* 11100011 */, 0 /* 11100100 */, 1 /* 11100101 */, 237 1 /* 11100110 */, 0 /* 11100111 */, 0 /* 11101000 */, 238 1 /* 11101001 */, 1 /* 11101010 */, 0 /* 11101011 */, 239 1 /* 11101100 */, 0 /* 11101101 */, 0 /* 11101110 */, 240 1 /* 11101111 */, 0 /* 11110000 */, 1 /* 11110001 */, 241 1 /* 11110010 */, 0 /* 11110011 */, 1 /* 11110100 */, 242 0 /* 11110101 */, 0 /* 11110110 */, 1 /* 11110111 */, 243 1 /* 11111000 */, 0 /* 11111001 */, 0 /* 11111010 */, 244 1 /* 11111011 */, 0 /* 11111100 */, 1 /* 11111101 */, 245 1 /* 11111110 */, 0 /* 11111111 */ 246 }; 247