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