3
* Functions for pass 2 of the disassembler.
5
* Copyright 2001 - 2003 by David Sullins
7
* This file is part of Dis51.
9
* Dis51 is free software; you can redistribute it and/or modify it under the
10
* terms of the GNU General Public License as published by the Free Software
11
* Foundation, version 2 of the License.
13
* Dis51 is distributed in the hope that it will be useful, but WITHOUT ANY
14
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18
* You should have received a copy of the GNU General Public License along with
19
* Dis51; if not, write to the Free Software Foundation, Inc., 59 Temple
20
* Place, Suite 330, Boston, MA 02111-1307 USA
22
* You may contact the author at davesullins@earthlink.net.
33
/* nextbyte: read a byte from memory
36
#define nextbyte() (hf->mem[addr++])
41
static int longaddr(uchar op1, uchar op2, char *label)
45
/* calculate address */
46
addr = ((((int)op1)<<8) | op2);
48
/* form label string */
49
sprintf(label, "L%04d", lbl[addr]);
57
static int absaddr(uchar opcode, uchar operand, int memPtr, char *label)
61
/* calculate address */
62
addr = ((memPtr & 0xf800) | (((int)opcode & 0xe0)<<3) | operand);
64
/* form label string */
65
sprintf(label, "L%04d", lbl[addr]);
73
static int reladdr(uchar operand, int memPtr, char *label)
77
/* calculate address */
78
addr = memPtr + (signed char)operand;
80
/* form label string */
81
sprintf(label, "L%04d", lbl[addr]);
89
* Pretty format a hexadecimal number in a string.
91
static void printhex(uchar num, char *name)
93
if ((num >= 0xa0) || ((num <= 0xf) && (num >= 0xa)))
94
snprintf(name, 5, "0%Xh", num);
96
snprintf(name, 5, "%Xh", num);
101
* Convert a direct memory value to a SFR name if appropriate.
102
* Otherwise output the formatted number.
104
static void sfrdecode(uchar sfr, char *name)
107
strncpy(name, sfrname[sfr&0x7f], 5);
114
* Convert a bit memory value to a SF bit name if appropriate.
115
* Otherwise output the formatted number.
117
static void sfbitdecode(uchar sfbit, char *name)
120
strncpy(name, sfbitname[sfbit&0x7f], 6);
122
printhex(sfbit, name);
127
* Output list-format address and data for the -l command line switch.
129
* Contributed by Peter Peres.
131
#define listhex(len,addr,ofile) { if(Lst) _listhex(ofile,hf,addr,len); }
132
static void _listhex(FILE *file, const struct hexfile *hf, int addr, int len)
134
fprintf( file, " %04X %02X", addr-len, hf->mem[addr-len] );
137
fprintf( file, "%02X", hf->mem[addr-2] );
139
fprintf( file, "%02X", hf->mem[addr-1] );
146
fprintf( file, "\t\t" );
149
/* dis_inst2: Disassemble one instruction to ofile
151
* Returns address immediately after instruction.
153
static int dis_inst2(FILE *ofile, const struct hexfile *hf, int addr)
165
/* Fetch second and third byte, if appropriate */
166
if (op_format[opcode] > 1) {
170
if (op_format[opcode] > 6) {
175
/* Output decoded instruction */
177
fprintf(ofile, "\t");
179
listhex(bytes, addr, ofile);
180
switch(op_format[opcode]) {
182
/* A5 is an illegal opcode */
183
fprintf(ofile, "DB 85h ; illegal opcode");
186
fprintf(ofile, mnemonic[opcode]);
189
/* one immediate operand */
191
fprintf(ofile, mnemonic[opcode], name);
194
/* one direct operand */
195
sfrdecode(op1, name);
196
fprintf(ofile, mnemonic[opcode], name);
199
/* one bit-addressed operand */
200
sfbitdecode(op1, name);
201
fprintf(ofile, mnemonic[opcode], name);
204
/* one operand, relative address */
205
/* relative addr calculation */
206
reladdr(op1, addr, label);
207
fprintf(ofile, mnemonic[opcode], label);
210
/* one operand, absolute address */
211
/* absolute addr calculation */
212
absaddr(opcode, op1, addr, label);
213
fprintf(ofile, mnemonic[opcode], label);
216
/* two-byte immediate operand */
217
/* MOV DPTR, #immediate16 */
218
fprintf(ofile, mnemonic[opcode], op1, op2);
221
/* two operands: direct, immediate */
222
sfrdecode(op1, name);
223
printhex(op2, name2);
224
fprintf(ofile, mnemonic[opcode], name, name2);
227
/* two operands: direct, direct */
228
/* (operands in reverse order) */
229
sfrdecode(op1, name);
230
sfrdecode(op2, name2);
231
fprintf(ofile, mnemonic[opcode], name2, name);
234
/* two operands: immediate, relative */
236
reladdr(op2, addr, label);
237
fprintf(ofile, mnemonic[opcode], name, label);
240
/* two operands: direct, relative */
241
sfrdecode(op1, name);
242
reladdr(op2, addr, label);
243
fprintf(ofile, mnemonic[opcode], name, label);
246
/* two operands: bit, relative */
247
sfbitdecode(op1, name);
248
reladdr(op2, addr, label);
249
fprintf(ofile, mnemonic[opcode], name, label);
253
/* long addr calculation */
254
longaddr(op1, op2, label);
255
fprintf(ofile, mnemonic[opcode], label);
258
/* error in op_format table */
259
fprintf(ofile, "DB 0%Xh ; error in op_format table",
262
fprintf(ofile, "\n");
267
/* pass2: Disassemble memory to given output file (pass 2)
270
void pass2(FILE *ofile, const struct hexfile *hf)
273
uchar empty = 1; /* 1 for no code/data, 0 for code or data */
277
/* Step 1: check if memory is empty */
278
if ((hf->flag[addr] != EMPTY) && (empty))
279
/* We've changed from empty to non-empty,
280
* so start a new segment.
282
fprintf(ofile, "CSEG AT %04Xh\n", addr);
283
else if (hf->flag[addr] == EMPTY) {
284
/* no code or data here */
291
/* Step 2: Output a label if one exists */
293
fprintf(ofile, "L%04d:\n", lbl[addr]);
295
/* Step 3: Output code or data as appropriate */
296
if (hf->flag[addr]&CODE)
297
/* code here, so disassemble next instruction */
298
addr = dis_inst2(ofile, hf, addr);
302
fprintf(ofile, "\tDB 0%Xh\n", hf->mem[addr]);
304
listhex(1, addr+1, ofile);
305
if(isprint(hf->mem[addr]))
306
fprintf(ofile, "DB 0%02Xh ; '%c'\n", hf->mem[addr], hf->mem[addr]);
308
fprintf(ofile, "DB 0%02Xh \n", hf->mem[addr]);
314
fprintf(ofile, "END\n");