1 |
cebix |
1.1 |
/* |
2 |
|
|
* mon_8080.cpp - 8080 disassembler |
3 |
|
|
* |
4 |
|
|
* (C) 1997-1999 Christian Bauer |
5 |
|
|
*/ |
6 |
|
|
|
7 |
|
|
#include <stdio.h> |
8 |
|
|
|
9 |
|
|
#include "mon.h" |
10 |
|
|
#include "mon_8080.h" |
11 |
|
|
|
12 |
|
|
|
13 |
|
|
// Addressing modes |
14 |
|
|
enum { |
15 |
|
|
A_IMPL, |
16 |
|
|
A_BC, // bc |
17 |
|
|
A_DE, // de |
18 |
|
|
A_HL, // hl |
19 |
|
|
A_SP, // sp |
20 |
|
|
A_PSW, // psw |
21 |
|
|
A_REG1, // register (bits 0..2 of opcode) |
22 |
|
|
A_REG2, // register (bits 3..5 of opcode) |
23 |
|
|
A_2REG, // register (bits 3..5 of opcode),register (bits 0..2 of opcode) |
24 |
|
|
A_RST, // restart |
25 |
|
|
A_BYTE, // xx |
26 |
|
|
A_R2_B, // register (bits 3..5 of opcode),xx |
27 |
|
|
A_WORD, // xxxx |
28 |
|
|
A_BC_W, // bc,xxxx |
29 |
|
|
A_DE_W, // de,xxxx |
30 |
|
|
A_HL_W, // hl,xxxx |
31 |
|
|
A_SP_W // sp,xxxx |
32 |
|
|
}; |
33 |
|
|
|
34 |
|
|
// Mnemonics |
35 |
|
|
enum { |
36 |
|
|
M_ACI, M_ADC, M_ADD, M_ADI, M_ANA, M_ANI, M_CALL, M_CC, M_CM, M_CMA, M_CMC, |
37 |
|
|
M_CMP, M_CNC, M_CNZ, M_CP, M_CPE, M_CPI, M_CPO, M_CZ, M_DAA, M_DAD, M_DCR, |
38 |
|
|
M_DCX, M_DI, M_EI, M_HLT, M_IN, M_INR, M_INX, M_JMP, M_JC, M_JM, M_JNC, M_JNZ, |
39 |
|
|
M_JP, M_JPE, M_JPO, M_JZ, M_LDA, M_LDAX, M_LHLD, M_LXI, M_MOV, M_MVI, M_NOP, |
40 |
|
|
M_ORA, M_ORI, M_OUT, M_PCHL, M_POP, M_PUSH, M_RAL, M_RAR, M_RET, M_RC, M_RM, |
41 |
|
|
M_RNC, M_RNZ, M_RP, M_RPE, M_RPO, M_RZ, M_RLC, M_RRC, M_RST, M_SBB, M_SBI, |
42 |
|
|
M_SHLD, M_SPHL, M_STA, M_STAX, M_STC, M_SUB, M_SUI, M_XCHG, M_XRA, M_XRI, M_XTHL, |
43 |
|
|
M_ILLEGAL, |
44 |
|
|
|
45 |
|
|
M_MAXIMUM // Highest element |
46 |
|
|
}; |
47 |
|
|
|
48 |
|
|
// Mnemonic for each opcode |
49 |
|
|
static const char mnemonic[256] = { |
50 |
|
|
M_NOP , M_LXI , M_STAX, M_INX , M_INR, M_DCR , M_MVI, M_RLC, // 00 |
51 |
|
|
M_ILLEGAL, M_DAD , M_LDAX, M_DCX , M_INR, M_DCR , M_MVI, M_RRC, |
52 |
|
|
M_ILLEGAL, M_LXI , M_STAX, M_INX , M_INR, M_DCR , M_MVI, M_RAL, // 10 |
53 |
|
|
M_ILLEGAL, M_DAD , M_LDAX, M_DCX , M_INR, M_DCR , M_MVI, M_RAR, |
54 |
|
|
M_ILLEGAL, M_LXI , M_SHLD, M_INX , M_INR, M_DCR , M_MVI, M_DAA, // 20 |
55 |
|
|
M_ILLEGAL, M_DAD , M_LHLD, M_DCX , M_INR, M_DCR , M_MVI, M_CMA, |
56 |
|
|
M_ILLEGAL, M_LXI , M_STA , M_INX , M_INR, M_DCR , M_MVI, M_STC, // 30 |
57 |
|
|
M_ILLEGAL, M_DAD , M_LDA , M_DCX , M_INR, M_DCR , M_MVI, M_CMC, |
58 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, // 40 |
59 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, |
60 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, // 50 |
61 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, |
62 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, // 60 |
63 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, |
64 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_HLT, M_MOV, // 70 |
65 |
|
|
M_MOV , M_MOV , M_MOV , M_MOV , M_MOV, M_MOV , M_MOV, M_MOV, |
66 |
|
|
M_ADD , M_ADD , M_ADD , M_ADD , M_ADD, M_ADD , M_ADD, M_ADD, // 80 |
67 |
|
|
M_ADC , M_ADC , M_ADC , M_ADC , M_ADC, M_ADC , M_ADC, M_ADC, |
68 |
|
|
M_SUB , M_SUB , M_SUB , M_SUB , M_SUB, M_SUB , M_SUB, M_SUB, // 90 |
69 |
|
|
M_SBB , M_SBB , M_SBB , M_SBB , M_SBB, M_SBB , M_SBB, M_SBB, |
70 |
|
|
M_ANA , M_ANA , M_ANA , M_ANA , M_ANA, M_ANA , M_ANA, M_ANA, // a0 |
71 |
|
|
M_XRA , M_XRA , M_XRA , M_XRA , M_XRA, M_XRA , M_XRA, M_XRA, |
72 |
|
|
M_ORA , M_ORA , M_ORA , M_ORA , M_ORA, M_ORA , M_ORA, M_ORA, // b0 |
73 |
|
|
M_CMP , M_CMP , M_CMP , M_CMP , M_CMP, M_CMP , M_CMP, M_CMP, |
74 |
|
|
M_RNZ , M_POP , M_JNZ , M_JMP , M_CNZ, M_PUSH , M_ADI, M_RST, // c0 |
75 |
|
|
M_RZ , M_RET , M_JZ , M_ILLEGAL, M_CZ , M_CALL , M_ACI, M_RST, |
76 |
|
|
M_RNC , M_POP , M_JNC , M_OUT , M_CNC, M_PUSH , M_SUI, M_RST, // d0 |
77 |
|
|
M_RC , M_ILLEGAL, M_JC , M_IN , M_CC , M_ILLEGAL, M_SBI, M_RST, |
78 |
|
|
M_RPO , M_POP , M_JPO , M_XTHL , M_CPO, M_PUSH , M_ANI, M_RST, // e0 |
79 |
|
|
M_RPE , M_PCHL , M_JPE , M_XCHG , M_CPE, M_ILLEGAL, M_XRI, M_RST, |
80 |
|
|
M_RP , M_POP , M_JP , M_DI , M_CP , M_PUSH , M_ORI, M_RST, // f0 |
81 |
|
|
M_RM , M_SPHL , M_JM , M_EI , M_CM , M_ILLEGAL, M_CPI, M_RST |
82 |
|
|
}; |
83 |
|
|
|
84 |
|
|
// Addressing mode for each opcode |
85 |
|
|
static const char adr_mode[256] = { |
86 |
|
|
A_IMPL, A_BC_W, A_BC , A_BC , A_REG2, A_REG2, A_R2_B, A_IMPL, // 00 |
87 |
|
|
A_IMPL, A_BC , A_BC , A_BC , A_REG2, A_REG2, A_R2_B, A_IMPL, |
88 |
|
|
A_IMPL, A_DE_W, A_DE , A_DE , A_REG2, A_REG2, A_R2_B, A_IMPL, // 10 |
89 |
|
|
A_IMPL, A_DE , A_DE , A_DE , A_REG2, A_REG2, A_R2_B, A_IMPL, |
90 |
|
|
A_IMPL, A_HL_W, A_WORD, A_HL , A_REG2, A_REG2, A_R2_B, A_IMPL, // 20 |
91 |
|
|
A_IMPL, A_HL , A_WORD, A_HL , A_REG2, A_REG2, A_R2_B, A_IMPL, |
92 |
|
|
A_IMPL, A_SP_W, A_WORD, A_SP , A_REG2, A_REG2, A_R2_B, A_IMPL, // 30 |
93 |
|
|
A_IMPL, A_SP , A_WORD, A_SP , A_REG2, A_REG2, A_R2_B, A_IMPL, |
94 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, // 40 |
95 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, |
96 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, // 50 |
97 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, |
98 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, // 60 |
99 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, |
100 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_IMPL, A_2REG, // 70 |
101 |
|
|
A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, A_2REG, |
102 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, // 80 |
103 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, |
104 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, // 90 |
105 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, |
106 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, // a0 |
107 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, |
108 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, // b0 |
109 |
|
|
A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, A_REG1, |
110 |
|
|
A_IMPL, A_BC , A_WORD, A_WORD, A_WORD, A_BC , A_BYTE, A_RST , // c0 |
111 |
|
|
A_IMPL, A_IMPL, A_WORD, A_IMPL, A_WORD, A_WORD, A_BYTE, A_RST , |
112 |
|
|
A_IMPL, A_DE , A_WORD, A_BYTE, A_WORD, A_DE , A_BYTE, A_RST , // d0 |
113 |
|
|
A_IMPL, A_IMPL, A_WORD, A_BYTE, A_WORD, A_IMPL, A_BYTE, A_RST , |
114 |
|
|
A_IMPL, A_HL , A_WORD, A_IMPL, A_WORD, A_HL , A_BYTE, A_RST , // e0 |
115 |
|
|
A_IMPL, A_IMPL, A_WORD, A_IMPL, A_WORD, A_IMPL, A_BYTE, A_RST , |
116 |
|
|
A_IMPL, A_PSW , A_WORD, A_IMPL, A_WORD, A_PSW , A_BYTE, A_RST , // f0 |
117 |
|
|
A_IMPL, A_IMPL, A_WORD, A_IMPL, A_WORD, A_IMPL, A_BYTE, A_RST |
118 |
|
|
}; |
119 |
|
|
|
120 |
|
|
// Chars for each mnemonic |
121 |
|
|
static const char mnem_1[] = "aaaaaacccccccccccccdddddehiiijjjjjjjjjllllmmnoooppprrrrrrrrrrrrrrsssssssssxxxx?"; |
122 |
|
|
static const char mnem_2[] = "cdddnnacmmmmnnppppzaacciilnnnmcmnnpppzddhxovorrucouaaecmnnpppzlrsbbhptttuucrrt "; |
123 |
|
|
static const char mnem_3[] = "icdiail acpcz eio adrx t rxp cz eo aalivipaithpslrt cz eo cctbilhaacbihaih "; |
124 |
|
|
static const char mnem_4[] = " l xd l h dl x g l "; |
125 |
|
|
|
126 |
|
|
// Register names |
127 |
|
|
static const char reg_name[] = {"bcdehlma"}; |
128 |
|
|
|
129 |
|
|
// Instruction length for each addressing mode |
130 |
|
|
static const char adr_length[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3}; |
131 |
|
|
|
132 |
|
|
|
133 |
|
|
/* |
134 |
|
|
* Disassemble one instruction, return number of bytes |
135 |
|
|
*/ |
136 |
|
|
|
137 |
|
|
int disass_8080(FILE *f, uint32 adr, uint8 op, uint8 lo, uint8 hi) |
138 |
|
|
{ |
139 |
|
|
char mode = adr_mode[op], mnem = mnemonic[op]; |
140 |
|
|
|
141 |
|
|
// Display instruction bytes in hex |
142 |
|
|
switch (adr_length[mode]) { |
143 |
|
|
case 1: |
144 |
|
|
fprintf(f, "%02x\t\t", op); |
145 |
|
|
break; |
146 |
|
|
|
147 |
|
|
case 2: |
148 |
|
|
fprintf(f, "%02x %02x\t\t", op, lo); |
149 |
|
|
break; |
150 |
|
|
|
151 |
|
|
case 3: |
152 |
|
|
fprintf(f, "%02x %02x %02x\t", op, lo, hi); |
153 |
|
|
break; |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
// Print mnemonic |
157 |
|
|
fprintf(f, "%c%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem], mnem_4[mnem]); |
158 |
|
|
|
159 |
|
|
// Print argument |
160 |
|
|
switch (mode) { |
161 |
|
|
case A_IMPL: |
162 |
|
|
break; |
163 |
|
|
|
164 |
|
|
case A_BC: |
165 |
|
|
fprintf(f, "bc"); |
166 |
|
|
break; |
167 |
|
|
|
168 |
|
|
case A_DE: |
169 |
|
|
fprintf(f, "de"); |
170 |
|
|
break; |
171 |
|
|
|
172 |
|
|
case A_HL: |
173 |
|
|
fprintf(f, "hl"); |
174 |
|
|
break; |
175 |
|
|
|
176 |
|
|
case A_SP: |
177 |
|
|
fprintf(f, "sp"); |
178 |
|
|
break; |
179 |
|
|
|
180 |
|
|
case A_PSW: |
181 |
|
|
fprintf(f, "psw"); |
182 |
|
|
break; |
183 |
|
|
|
184 |
|
|
case A_REG1: |
185 |
|
|
fprintf(f, "%c", reg_name[op & 7]); |
186 |
|
|
break; |
187 |
|
|
|
188 |
|
|
case A_REG2: |
189 |
|
|
fprintf(f, "%c", reg_name[(op >> 3) & 7]); |
190 |
|
|
break; |
191 |
|
|
|
192 |
|
|
case A_2REG: |
193 |
|
|
fprintf(f, "%c,%c", reg_name[(op >> 3) & 7], reg_name[op & 7]); |
194 |
|
|
break; |
195 |
|
|
|
196 |
|
|
case A_RST: |
197 |
|
|
fprintf(f, "$%02x", op & 0x38); |
198 |
|
|
break; |
199 |
|
|
|
200 |
|
|
case A_BYTE: |
201 |
|
|
fprintf(f, "$%02x", lo); |
202 |
|
|
break; |
203 |
|
|
|
204 |
|
|
case A_R2_B: |
205 |
|
|
fprintf(f, "%c,$%02x", reg_name[(op >> 3) & 7], lo); |
206 |
|
|
break; |
207 |
|
|
|
208 |
|
|
case A_WORD: |
209 |
|
|
fprintf(f, "$%04x", (hi << 8) | lo); |
210 |
|
|
break; |
211 |
|
|
|
212 |
|
|
case A_BC_W: |
213 |
|
|
fprintf(f, "bc,$%04x", (hi << 8) | lo); |
214 |
|
|
break; |
215 |
|
|
|
216 |
|
|
case A_DE_W: |
217 |
|
|
fprintf(f, "de,$%04x", (hi << 8) | lo); |
218 |
|
|
break; |
219 |
|
|
|
220 |
|
|
case A_HL_W: |
221 |
|
|
fprintf(f, "hl,$%04x", (hi << 8) | lo); |
222 |
|
|
break; |
223 |
|
|
|
224 |
|
|
case A_SP_W: |
225 |
|
|
fprintf(f, "sp,$%04x", (hi << 8) | lo); |
226 |
|
|
break; |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
fputc('\n', f); |
230 |
|
|
return adr_length[mode]; |
231 |
|
|
} |