1 /* altairz80_sys.c: MITS Altair system interface
2
3 Copyright (c) 2002-2011, Peter Schorn
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Peter Schorn shall not
23 be used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Peter Schorn.
25
26 Based on work by Charles E Owen (c) 1997
27 Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited)
28 */
29
30 #include <ctype.h>
31 #include "altairz80_defs.h"
32
33 #define SIM_EMAX 6
34
35 extern UNIT cpu_unit;
36 extern REG cpu_reg[];
37 extern DEVICE cpu_dev;
38 extern DEVICE sio_dev;
39 extern DEVICE simh_device;
40 extern DEVICE ptr_dev;
41 extern DEVICE ptp_dev;
42 extern DEVICE dsk_dev;
43 extern DEVICE hdsk_dev;
44 extern DEVICE net_dev;
45
46 extern DEVICE mfdc_dev;
47 extern DEVICE fw2_dev;
48 extern DEVICE fif_dev;
49 extern DEVICE vfdhd_dev;
50 extern DEVICE mdsad_dev;
51 extern DEVICE nsfpb_dev;
52 extern DEVICE disk1a_dev;
53 extern DEVICE disk2_dev;
54 extern DEVICE disk3_dev;
55 extern DEVICE selchan_dev;
56 extern DEVICE ss1_dev;
57 extern DEVICE if3_dev;
58 extern DEVICE i8272_dev;
59 extern DEVICE mdriveh_dev;
60 extern DEVICE switchcpu_dev;
61
62 extern DEVICE adcs6_dev;
63 extern DEVICE hdc1001_dev;
64
65 extern DEVICE cromfdc_dev;
66 extern DEVICE wd179x_dev;
67 extern DEVICE n8vem_dev;
68 extern DEVICE wdi2_dev;
69
70 extern DEVICE scp300f_dev;
71
72 #ifdef USE_FPC
73 extern DEVICE fpc_dev;
74 #endif /* USE_FPC */
75
76 extern int32 chiptype;
77 extern long disasm (unsigned char *data, char *output, int segsize, long offset);
78
79 void prepareMemoryAccessMessage(const t_addr loc);
80 void prepareInstructionMessage(const t_addr loc, const uint32 op);
81 t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
82 t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw);
83
84 t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc);
85 t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc);
86 t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
87 t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
88
89 /* SCP data structures
90 sim_name simulator name string
91 sim_PC pointer to saved PC register descriptor
92 sim_emax number of words needed for examine
93 sim_devices array of pointers to simulated devices
94 sim_stop_messages array of pointers to stop messages
95 */
96
97 char sim_name[] = "Altair 8800 (Z80)";
98 REG *sim_PC = &cpu_reg[6];
99 int32 sim_emax = SIM_EMAX;
100 DEVICE *sim_devices[] = {
101 /* AltairZ80 Devices */
102 &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev,
103 &hdsk_dev, &net_dev,
104 /* Advanced Digital (ADC) Devices */
105 &adcs6_dev,
106 &hdc1001_dev,
107 /* Compupro Devices */
108 &disk1a_dev, &disk2_dev, &disk3_dev, &ss1_dev, &mdriveh_dev, &selchan_dev, &if3_dev,
109 /* Cromemco Devices */
110 &cromfdc_dev,
111 /* IMSAI Devices */
112 &fif_dev,
113 /* Micropolis Devices */
114 &mfdc_dev,
115 /* North Star Devices */
116 &mdsad_dev,
117 /* Seattle Computer Products Devices */
118 &scp300f_dev,
119 /* Vector Graphic Devices */
120 &fw2_dev, &vfdhd_dev,
121 /* Single-Board Computers */
122 &n8vem_dev,
123 /* Floppy Controller Cores */
124 &i8272_dev, &wd179x_dev,
125 NULL
126 };
127
128 static char memoryAccessMessage[256];
129 static char instructionMessage[256];
130 const char *sim_stop_messages[] = {
131 "HALT instruction",
132 "Breakpoint",
133 memoryAccessMessage,
134 instructionMessage,
135 "Invalid Opcode"
136 };
137
138 static char *const Mnemonics8080[] = {
139 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
140 "NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */
141 "DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */
142 "DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */
143 "DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */
144 "DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */
145 "DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */
146 "DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */
147 "DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */
148 "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 */
149 "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 */
150 "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 */
151 "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 */
152 "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 */
153 "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 */
154 "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */
155 "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 */
156 "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */
157 "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */
158 "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */
159 "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */
160 "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */
161 "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */
162 "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */
163 "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */
164 "RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */
165 "RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */
166 "RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */
167 "RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */
168 "RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */
169 "RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */
170 "RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */
171 "RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */
172 };
173
174 static char *const MnemonicsZ80[256] = {
175 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
176 "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */
177 "EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */
178 "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */
179 "JR $h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */
180 "JR NZ,$h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA", /* 20-27 */
181 "JR Z,$h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL", /* 28-2f */
182 "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF", /* 30-37 */
183 "JR C,$h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */
184 "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 */
185 "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 */
186 "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 */
187 "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 */
188 "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 */
189 "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 */
190 "LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A", /* 70-77 */
191 "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 */
192 "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 */
193 "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 */
194 "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A", /* 90-97 */
195 "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 */
196 "AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A", /* a0-a7 */
197 "XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A", /* a8-af */
198 "OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A", /* b0-b7 */
199 "CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A", /* b8-bf */
200 "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c0-c7 */
201 "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */
202 "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */
203 "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */
204 "RET PO", "POP HL", "JP PO,#h", "EX (SP),HL", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h", /* e0-e7 */
205 "RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */
206 "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */
207 "RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */
208 };
209
210 static char *const MnemonicsCB[256] = {
211 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
212 "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */
213 "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */
214 "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", /* 10-17 */
215 "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", /* 18-1f */
216 "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", /* 20-27 */
217 "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", /* 28-2f */
218 "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A", /* 30-37 */
219 "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", /* 38-3f */
220 "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 */
221 "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 */
222 "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 */
223 "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 */
224 "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 */
225 "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 */
226 "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 */
227 "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 */
228 "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 */
229 "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 */
230 "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 */
231 "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 */
232 "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 */
233 "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 */
234 "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 */
235 "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 */
236 "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 */
237 "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 */
238 "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 */
239 "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 */
240 "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 */
241 "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 */
242 "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 */
243 "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 */
244 };
245
246 static char *const MnemonicsED[256] = {
247 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
248 "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 */
249 "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 */
250 "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 */
251 "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 */
252 "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 */
253 "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 */
254 "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 */
255 "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 */
256 "IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A", /* 40-47 */
257 "IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A", /* 48-4f */
258 "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 */
259 "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 */
260 "IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD", /* 60-67 */
261 "IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD", /* 68-6f */
262 "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 */
263 "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 */
264 "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 */
265 "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 */
266 "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 */
267 "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 */
268 "LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h", /* a0-a7 */
269 "LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh", /* a8-af */
270 "LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h", /* b0-b7 */
271 "LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh", /* b8-bf */
272 "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 */
273 "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 */
274 "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 */
275 "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 */
276 "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 */
277 "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 */
278 "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 */
279 "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 */
280 };
281
282 static char *const MnemonicsXX[256] = {
283 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
284 "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */
285 "EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */
286 "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */
287 "JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */
288 "JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */
289 "JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */
290 "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h","SCF", /* 30-37 */
291 "JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */
292 "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 */
293 "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 */
294 "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 */
295 "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 */
296 "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 */
297 "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 */
298 "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 */
299 "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 */
300 "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 */
301 "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 */
302 "SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */
303 "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 */
304 "AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */
305 "XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */
306 "OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */
307 "CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */
308 "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */
309 "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */
310 "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */
311 "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */
312 "RET PO", "POP I%", "JP PO,#h", "EX (SP),I%", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h", /* e0-e7 */
313 "RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */
314 "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */
315 "RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */
316 };
317
318 static char *const MnemonicsXCB[256] = {
319 /*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
320 "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */
321 "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */
322 "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A", /* 10-17 */
323 "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A", /* 18-1f */
324 "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A", /* 20-27 */
325 "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A", /* 28-2f */
326 "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A", /* 30-37 */
327 "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A", /* 38-3f */
328 "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 */
329 "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 */
330 "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 */
331 "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 */
332 "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 */
333 "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 */
334 "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 */
335 "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 */
336 "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 */
337 "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 */
338 "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 */
339 "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 */
340 "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 */
341 "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 */
342 "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 */
343 "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 */
344 "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 */
345 "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 */
346 "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 */
347 "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 */
348 "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 */
349 "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 */
350 "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 */
351 "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 */
352 };
353
prepareMemoryAccessMessage(const t_addr loc)354 void prepareMemoryAccessMessage(const t_addr loc) {
355 sprintf(memoryAccessMessage, "Memory access breakpoint [%05xh]", loc);
356 }
357
prepareInstructionMessage(const t_addr loc,const uint32 op)358 void prepareInstructionMessage(const t_addr loc, const uint32 op) {
359 sprintf(instructionMessage, "Instruction \"%s\" breakpoint [%05xh]", chiptype == CHIP_TYPE_8080 ? Mnemonics8080[op & 0xff] :
360 (chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80[op & 0xff] : "???"), loc);
361 }
362
363 /* Symbolic disassembler
364
365 Inputs:
366 *val = instructions to disassemble
367 useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used
368 addr = current PC
369 Outputs:
370 *S = output text
371
372 DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997
373 You are not allowed to distribute this software
374 commercially.
375
376 */
377
DAsm(char * S,const uint32 * val,const int32 useZ80Mnemonics,const int32 addr)378 static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) {
379 char R[128], H[10], C = '\0', *T, *P;
380 uint8 J = 0, Offset = 0;
381 uint16 B = 0;
382
383 if (useZ80Mnemonics)
384 switch(val[B]) {
385
386 case 0xcb:
387 B++;
388 T = MnemonicsCB[val[B++]];
389 break;
390
391 case 0xed:
392 B++;
393 T = MnemonicsED[val[B++]];
394 break;
395
396 case 0xdd:
397
398 case 0xfd:
399 C = (val[B++] == 0xdd) ? 'X' : 'Y';
400 if (val[B] == 0xcb) {
401 B++;
402 Offset = val[B++];
403 J = 1;
404 T = MnemonicsXCB[val[B++]];
405 }
406 else
407 T = MnemonicsXX[val[B++]];
408 break;
409
410 default:
411 T = MnemonicsZ80[val[B++]];
412 }
413 else
414 T = Mnemonics8080[val[B++]];
415
416 if ( (P = strchr(T, '^')) ) {
417 strncpy(R, T, P - T);
418 R[P - T] = '\0';
419 sprintf(H, "%02X", val[B++]);
420 strcat(R, H);
421 strcat(R, P + 1);
422 }
423 else
424 strcpy(R, T);
425 if ( (P = strchr(R, '%')) ) {
426 *P = C;
427 if ( (P = strchr(P + 1, '%')) )
428 *P = C;
429 }
430
431 if ( (P = strchr(R, '*')) ) {
432 strncpy(S, R, P - R);
433 S[P - R] = '\0';
434 sprintf(H, "%02X", val[B++]);
435 strcat(S, H);
436 strcat(S, P + 1);
437 }
438 else if ( (P = strchr(R, '@')) ) {
439 strncpy(S, R, P - R);
440 S[P - R] = '\0';
441 if (!J)
442 Offset = val[B++];
443 strcat(S, Offset & 0x80 ? "-" : "+");
444 J = Offset & 0x80 ? 256 - Offset : Offset;
445 sprintf(H, "%02X", J);
446 strcat(S, H);
447 strcat(S, P + 1);
448 }
449 else if ( (P = strchr(R, '$')) ) {
450 strncpy(S, R, P - R);
451 S[P - R] = '\0';
452 Offset = val[B++];
453 sprintf(H, "%04X", (addr + 2 + (Offset & 0x80 ? (Offset - 256) : Offset)) & 0xFFFF);
454 strcat(S, H);
455 strcat(S, P + 1);
456 }
457 else if ( (P = strchr(R, '#')) ) {
458 strncpy(S, R, P - R);
459 S[P - R] = '\0';
460 sprintf(H, "%04X", val[B] + 256 * val[B + 1]);
461 strcat(S, H);
462 strcat(S, P + 1);
463 B += 2;
464 }
465 else
466 strcpy(S, R);
467 return(B);
468 }
469
470 /* Symbolic output
471
472 Inputs:
473 *of = output stream
474 addr = current PC
475 *val = pointer to values
476 *uptr = pointer to unit
477 sw = switches
478 Outputs:
479 status = error code
480 */
481
fprint_sym(FILE * of,t_addr addr,t_value * val,UNIT * uptr,int32 sw)482 t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) {
483 char disasm_result[128];
484 int32 ch = val[0] & 0x7f;
485 long r;
486 unsigned char vals[SIM_EMAX];
487 int32 i;
488 if (sw & (SWMASK('A') | SWMASK('C'))) {
489 fprintf(of, ((0x20 <= ch) && (ch < 0x7f)) ? "'%c'" : "%02x", ch);
490 return SCPE_OK;
491 }
492 if (!(sw & SWMASK('M')))
493 return SCPE_ARG;
494 if (chiptype == CHIP_TYPE_8086) {
495 for (i = 0; i < SIM_EMAX; i++)
496 vals[i] = val[i] & 0xff;
497 r = disasm(vals, disasm_result, 16, addr);
498 }
499 else
500 r = DAsm(disasm_result, val, chiptype == CHIP_TYPE_Z80, addr);
501 fprintf(of, "%s", disasm_result);
502 return 1 - r;
503 }
504
505 /* checkbase determines the base of the number (ch, *numString)
506 and returns FALSE if the number is bad */
checkbase(char ch,const char * numString)507 static int32 checkbase(char ch, const char *numString) {
508 int32 decimal = (ch <= '9');
509 if (toupper(ch) == 'H')
510 return FALSE;
511 while (isxdigit(ch = *numString++))
512 if (ch > '9')
513 decimal = FALSE;
514 return toupper(ch) == 'H' ? 16 : (decimal ? 10 : FALSE);
515 }
516
numok(char ch,const char ** numString,const int32 minvalue,const int32 maxvalue,const int32 requireSign,int32 * result)517 static int32 numok(char ch, const char **numString, const int32 minvalue,
518 const int32 maxvalue, const int32 requireSign, int32 *result) {
519 int32 sign = 1, value = 0, base;
520 if (requireSign) {
521 if (ch == '+')
522 ch = *(*numString)++;
523 else if (ch == '-') {
524 sign = -1;
525 ch = *(*numString)++;
526 }
527 else
528 return FALSE;
529 }
530 if (!(base = checkbase(ch, *numString)))
531 return FALSE;
532 while (isxdigit(ch)) {
533 value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10));
534 ch = *(*numString)++;
535 }
536 if (toupper(ch) != 'H')
537 (*numString)--;
538 *result = value * sign;
539 return (minvalue <= value) && (value <= maxvalue);
540 }
541
match(const char * pattern,const char * input,char * xyFirst,char * xy,int32 * number,int32 * star,int32 * at,int32 * hat,int32 * dollar)542 static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star,
543 int32 *at, int32 *hat, int32 *dollar) {
544 char pat = *pattern++;
545 char inp = *input++;
546 while ((pat) && (inp)) {
547 switch(pat) {
548
549 case '_': /* patterns containing '_' should never match */
550 return FALSE;
551
552 case ',':
553 if (inp == ' ') {
554 inp = *input++;
555 continue;
556 } /* otherwise fall through */
557
558 case ' ':
559 if (inp != pat)
560 return FALSE;
561 pat = *pattern++;
562 inp = *input++;
563 while (inp == ' ')
564 inp = *input++;
565 continue;
566
567 case '%':
568 inp = toupper(inp);
569 if ((inp == 'X') || (inp == 'Y'))
570 if (*xyFirst) /* make sure that second '%' corresponds to first */
571 if (*xyFirst == inp)
572 *xy = inp;
573 else
574 return FALSE;
575 else { /* take note of first '%' for later */
576 *xyFirst = inp;
577 *xy = inp;
578 }
579 else
580 return FALSE;
581 break;
582
583 case '#':
584 if (numok(inp, &input, 0, 65535, FALSE, number))
585 pattern++; /* skip h */
586 else
587 return FALSE;
588 break;
589
590 case '*':
591 if (numok(inp, &input, 0, 255, FALSE, star))
592 pattern++; /* skip h */
593 else
594 return FALSE;
595 break;
596
597 case '@':
598 if (numok(inp, &input, -128, 65535, TRUE, at))
599 pattern++; /* skip h */
600 else
601 return FALSE;
602 break;
603
604 case '$':
605 if (numok(inp, &input, 0, 65535, FALSE, dollar))
606 pattern++; /* skip h */
607 else
608 return FALSE;
609 break;
610
611 case '^':
612 if (numok(inp, &input, 0, 255, FALSE, hat))
613 pattern++; /* skip h */
614 else
615 return FALSE;
616 break;
617
618 default:
619 if (toupper(pat) != toupper(inp))
620 return FALSE;
621 }
622 pat = *pattern++;
623 inp = *input++;
624 }
625 while (inp == ' ')
626 inp = *input++;
627 return (pat == 0) && (inp == 0);
628 }
629
checkXY(const char xy)630 static int32 checkXY(const char xy) {
631 return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */
632 }
633
parse_X80(const char * cptr,const int32 addr,uint32 * val,char * const Mnemonics[])634 static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) {
635 char xyFirst = 0, xy;
636 int32 op, number, star, at, hat, dollar;
637 for (op = 0; op < 256; op++) {
638 number = star = at = dollar = -129;
639 if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
640 val[0] = op;
641 if (number >= 0) {
642 val[1] = (0xff) & number;
643 val[2] = (0xff) & (number >> 8);
644 return -2; /* two additional bytes returned */
645 }
646 else if (star >= 0) {
647 val[1] = (0xff) & star;
648 return -1; /* one additional byte returned */
649 }
650 else if (at > -129)
651 if ((-128 <= at) && (at <= 127)) {
652 val[1] = (int8)(at);
653 return -1; /* one additional byte returned */
654 }
655 else
656 return SCPE_ARG;
657 else if (dollar >= 0) {
658 dollar -= addr + 2; /* relative translation */
659 if ((-128 <= dollar) && (dollar <= 127)) {
660 val[1] = (int8)(dollar);
661 return -1; /* one additional byte returned */
662 }
663 else
664 return SCPE_ARG;
665 }
666 else
667 return SCPE_OK;
668 }
669 }
670 if (Mnemonics == Mnemonics8080)
671 return SCPE_ARG;
672
673 for (op = 0; op < 256; op++)
674 if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
675 val[0] = 0xcb;
676 val[1] = op;
677 return -1; /* one additional byte returned */
678 }
679
680 for (op = 0; op < 256; op++) {
681 number = -1;
682 if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
683 val[0] = 0xed;
684 val[1] = op;
685 if (number >= 0) {
686 val[2] = (0xff) & number;
687 val[3] = (0xff) & (number >> 8);
688 return -3; /* three additional bytes returned */
689 }
690 else
691 return -1; /* one additional byte returned */
692 }
693 }
694
695 for (op = 0; op < 256; op++) {
696 number = star = hat = -1;
697 xy = 0;
698 if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
699 /* all matches must have contained a '%' character */
700 if (!(val[0] = checkXY(xy)))
701 return SCPE_ARG;
702 val[1] = op;
703 if (number >= 0) {
704 val[2] = (0xff) & number;
705 val[3] = (0xff) & (number >> 8);
706 return -3; /* three additional bytes returned */
707 }
708 else if ((star >= 0) && (hat >= 0)) {
709 val[2] = (0xff) & hat;
710 val[3] = (0xff) & star;
711 return -3; /* three additional bytes returned */
712 }
713 else if (star >= 0) {
714 val[2] = (0xff) & star;
715 return -2; /* two additional bytes returned */
716 }
717 else if (hat >= 0) {
718 val[2] = (0xff) & hat;
719 return -2; /* two additional bytes returned */
720 }
721 else
722 return -1; /* one additional byte returned */
723 }
724 }
725
726 for (op = 0; op < 256; op++) {
727 at = -129;
728 xy = 0;
729 if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
730 /* all matches must have contained a '%' character */
731 if (!(val[0] = checkXY(xy)))
732 return SCPE_ARG;
733 val[1] = 0xcb;
734 if (at > -129)
735 val[2] = (int8) (at);
736 else {
737 printf("Offset expected.\n");
738 return SCPE_ARG;
739 }
740 val[3] = op;
741 return -3; /* three additional bytes returned */
742 }
743 }
744 return SCPE_ARG;
745 }
746
747
748 /* Symbolic input
749
750 Inputs:
751 *cptr = pointer to input string
752 addr = current PC
753 *uptr = pointer to unit
754 *val = pointer to output values
755 sw = switches
756 Outputs:
757 status = error status
758 */
parse_sym(char * cptr,t_addr addr,UNIT * uptr,t_value * val,int32 sw)759 t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) {
760 while (isspace(*cptr))
761 cptr++; /* absorb spaces */
762 if ((sw & (SWMASK('A') | SWMASK('C'))) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
763 if (cptr[0] == 0)
764 return SCPE_ARG; /* must have one char */
765 val[0] = (uint32) cptr[0];
766 return SCPE_OK;
767 }
768 return parse_X80(cptr, addr, val, chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80 : Mnemonics8080);
769 }
770
771 /* Set Memory Base Address routine */
set_membase(UNIT * uptr,int32 val,char * cptr,void * desc)772 t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc)
773 {
774 DEVICE *dptr;
775 PNP_INFO *pnp;
776 uint32 newba;
777 t_stat r;
778
779 if (cptr == NULL)
780 return SCPE_ARG;
781 if (uptr == NULL)
782 return SCPE_IERR;
783 dptr = find_dev_from_unit (uptr);
784 if (dptr == NULL)
785 return SCPE_IERR;
786 pnp = (PNP_INFO *) dptr->ctxt;
787 if (pnp == NULL)
788 return SCPE_IERR;
789
790 newba = get_uint (cptr, 16, 0xFFFF, &r);
791 if (r != SCPE_OK)
792 return r;
793
794 if ((newba > 0xFFFF) || (newba % pnp->mem_size))
795 return SCPE_ARG;
796
797 if (dptr->flags & DEV_DIS) {
798 printf("device not enabled yet.\n");
799 pnp->mem_base = newba & ~(pnp->mem_size-1);
800 } else {
801 dptr->flags |= DEV_DIS;
802 dptr->reset(dptr);
803 pnp->mem_base = newba & ~(pnp->mem_size-1);
804 dptr->flags &= ~DEV_DIS;
805 dptr->reset(dptr);
806 }
807
808 return SCPE_OK;
809 }
810
811 /* Show Base Address routine */
show_membase(FILE * st,UNIT * uptr,int32 val,void * desc)812 t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc)
813 {
814 DEVICE *dptr;
815 PNP_INFO *pnp;
816
817 if (uptr == NULL)
818 return SCPE_IERR;
819 dptr = find_dev_from_unit (uptr);
820 if (dptr == NULL)
821 return SCPE_IERR;
822 pnp = (PNP_INFO *) dptr->ctxt;
823 if (pnp == NULL)
824 return SCPE_IERR;
825
826 fprintf(st, "MEM=0x%04X-0x%04X", pnp->mem_base, pnp->mem_base+pnp->mem_size-1);
827 return SCPE_OK;
828 }
829
830 /* Set Memory Base Address routine */
set_iobase(UNIT * uptr,int32 val,char * cptr,void * desc)831 t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc)
832 {
833 DEVICE *dptr;
834 PNP_INFO *pnp;
835 uint32 newba;
836 t_stat r;
837
838 if (cptr == NULL)
839 return SCPE_ARG;
840 if (uptr == NULL)
841 return SCPE_IERR;
842 dptr = find_dev_from_unit (uptr);
843 if (dptr == NULL)
844 return SCPE_IERR;
845 pnp = (PNP_INFO *) dptr->ctxt;
846 if (pnp == NULL)
847 return SCPE_IERR;
848
849 newba = get_uint (cptr, 16, 0xFF, &r);
850 if (r != SCPE_OK)
851 return r;
852
853 if ((newba > 0xFF) ||
854 (newba % pnp->io_size))
855 return SCPE_ARG;
856
857 if (dptr->flags & DEV_DIS) {
858 printf("device not enabled yet.\n");
859 pnp->io_base = newba & ~(pnp->io_size-1);
860 } else {
861 dptr->flags |= DEV_DIS;
862 dptr->reset(dptr);
863 pnp->io_base = newba & ~(pnp->io_size-1);
864 dptr->flags &= ~DEV_DIS;
865 dptr->reset(dptr);
866 }
867
868 return SCPE_OK;
869 }
870
871 /* Show I/O Base Address routine */
show_iobase(FILE * st,UNIT * uptr,int32 val,void * desc)872 t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc)
873 {
874 DEVICE *dptr;
875 PNP_INFO *pnp;
876
877 if (uptr == NULL)
878 return SCPE_IERR;
879 dptr = find_dev_from_unit (uptr);
880 if (dptr == NULL)
881 return SCPE_IERR;
882 pnp = (PNP_INFO *) dptr->ctxt;
883 if (pnp == NULL)
884 return SCPE_IERR;
885
886 fprintf(st, "I/O=0x%02X-0x%02X", pnp->io_base, pnp->io_base+pnp->io_size-1);
887 return SCPE_OK;
888 }
889
890