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