~ubuntu-branches/ubuntu/intrepid/dis51/intrepid

« back to all changes in this revision

Viewing changes to pass2.c

  • Committer: Bazaar Package Importer
  • Author(s): Uwe Hermann
  • Date: 2008-02-17 15:52:20 UTC
  • Revision ID: james.westby@ubuntu.com-20080217155220-mnsnjsovxvw46y0i
Tags: upstream-0.5
ImportĀ upstreamĀ versionĀ 0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pass2.c
 
2
 *
 
3
 * Functions for pass 2 of the disassembler.
 
4
 *
 
5
 * Copyright 2001 - 2003 by David Sullins
 
6
 *
 
7
 * This file is part of Dis51.
 
8
 * 
 
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.
 
12
 * 
 
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
 
16
 * details.
 
17
 * 
 
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
 
21
 * 
 
22
 * You may contact the author at davesullins@earthlink.net.
 
23
 */
 
24
 
 
25
 
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
#include <ctype.h>
 
29
#include <hexfile.h>
 
30
#include "distypes.h"
 
31
#include "global.h"
 
32
 
 
33
/* nextbyte: read a byte from memory
 
34
 *
 
35
 */
 
36
#define nextbyte() (hf->mem[addr++])
 
37
 
 
38
/* longaddr
 
39
 *
 
40
 */
 
41
static int longaddr(uchar op1, uchar op2, char *label)
 
42
{
 
43
        int addr;
 
44
        
 
45
        /* calculate address */
 
46
        addr = ((((int)op1)<<8) | op2);
 
47
        
 
48
        /* form label string */
 
49
        sprintf(label, "L%04d", lbl[addr]);
 
50
        
 
51
        return lbl[addr];
 
52
}
 
53
 
 
54
/* absaddr
 
55
 *
 
56
 */
 
57
static int absaddr(uchar opcode, uchar operand, int memPtr, char *label)
 
58
{
 
59
        int addr;
 
60
        
 
61
        /* calculate address */
 
62
        addr = ((memPtr & 0xf800) | (((int)opcode & 0xe0)<<3) | operand);
 
63
        
 
64
        /* form label string */
 
65
        sprintf(label, "L%04d", lbl[addr]);
 
66
        
 
67
        return lbl[addr];
 
68
}
 
69
 
 
70
/* reladdr
 
71
 *
 
72
 */
 
73
static int reladdr(uchar operand, int memPtr, char *label)
 
74
{
 
75
        int addr;
 
76
        
 
77
        /* calculate address */
 
78
        addr = memPtr + (signed char)operand;
 
79
        
 
80
        /* form label string */
 
81
        sprintf(label, "L%04d", lbl[addr]);
 
82
        
 
83
        return lbl[addr];
 
84
}
 
85
 
 
86
 
 
87
/* printhex
 
88
 *
 
89
 * Pretty format a hexadecimal number in a string.
 
90
 */
 
91
static void printhex(uchar num, char *name)
 
92
{
 
93
        if ((num >= 0xa0) || ((num <= 0xf) && (num >= 0xa)))
 
94
                snprintf(name, 5, "0%Xh", num);
 
95
        else
 
96
                snprintf(name, 5, "%Xh", num);
 
97
}
 
98
 
 
99
/* sfrdecode
 
100
 *
 
101
 * Convert a direct memory value to a SFR name if appropriate.
 
102
 * Otherwise output the formatted number.
 
103
 */
 
104
static void sfrdecode(uchar sfr, char *name)
 
105
{
 
106
        if (sfr & 0x80)
 
107
                strncpy(name, sfrname[sfr&0x7f], 5);
 
108
        else
 
109
                printhex(sfr, name);
 
110
}
 
111
 
 
112
/* sfbitdecode
 
113
 *
 
114
 * Convert a bit memory value to a SF bit name if appropriate.
 
115
 * Otherwise output the formatted number.
 
116
 */
 
117
static void sfbitdecode(uchar sfbit, char *name)
 
118
{
 
119
        if (sfbit & 0x80)
 
120
                strncpy(name, sfbitname[sfbit&0x7f], 6);
 
121
        else
 
122
                printhex(sfbit, name);
 
123
}
 
124
 
 
125
/* _listhex, listhex
 
126
 *
 
127
 * Output list-format address and data for the -l command line switch.
 
128
 *
 
129
 * Contributed by Peter Peres.
 
130
 */
 
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)
 
133
{
 
134
        fprintf( file, "  %04X %02X", addr-len, hf->mem[addr-len] );
 
135
        switch(len) {
 
136
          case 3:
 
137
            fprintf( file, "%02X", hf->mem[addr-2] );
 
138
          case 2:
 
139
                fprintf( file, "%02X", hf->mem[addr-1] );
 
140
                if(len == 2)
 
141
                        fprintf( file, "  ");
 
142
                break;
 
143
          default:
 
144
            fprintf( file, "    ");
 
145
        }
 
146
        fprintf( file, "\t\t" );
 
147
}
 
148
 
 
149
/* dis_inst2: Disassemble one instruction to ofile
 
150
 * 
 
151
 * Returns address immediately after instruction.
 
152
 */
 
153
static int dis_inst2(FILE *ofile, const struct hexfile *hf, int addr)
 
154
{
 
155
        uchar opcode;
 
156
        uchar op1, op2;
 
157
        char label[6];
 
158
        char name[6];
 
159
        char name2[5];
 
160
        int bytes = 1;
 
161
 
 
162
        /* Fetch opcode */
 
163
        opcode = nextbyte();
 
164
        
 
165
        /* Fetch second and third byte, if appropriate */
 
166
        if (op_format[opcode] > 1) {
 
167
                op1 = nextbyte();
 
168
                bytes = 2;
 
169
        }
 
170
        if (op_format[opcode] > 6) {
 
171
                op2 = nextbyte();
 
172
                bytes = 3;
 
173
        }
 
174
        
 
175
        /* Output decoded instruction */
 
176
        if(!Lst)
 
177
                fprintf(ofile, "\t");
 
178
        else
 
179
                listhex(bytes, addr, ofile);
 
180
        switch(op_format[opcode]) {
 
181
                case 0:
 
182
                                /* A5 is an illegal opcode */
 
183
                        fprintf(ofile, "DB 85h  ; illegal opcode");
 
184
                case 1:
 
185
                                /* no operands */
 
186
                        fprintf(ofile, mnemonic[opcode]);
 
187
                        break;
 
188
                case 2:
 
189
                                /* one immediate operand */
 
190
                        printhex(op1, name);
 
191
                        fprintf(ofile, mnemonic[opcode], name);
 
192
                        break;
 
193
                case 3:
 
194
                                /* one direct operand */
 
195
                        sfrdecode(op1, name);
 
196
                        fprintf(ofile, mnemonic[opcode], name);
 
197
                        break;
 
198
                case 4:
 
199
                                /* one bit-addressed operand */
 
200
                        sfbitdecode(op1, name);
 
201
                        fprintf(ofile, mnemonic[opcode], name);
 
202
                        break;
 
203
                case 5:
 
204
                                /* one operand, relative address */
 
205
                        /* relative addr calculation */
 
206
                        reladdr(op1, addr, label);
 
207
                        fprintf(ofile, mnemonic[opcode], label);
 
208
                        break;
 
209
                case 6:
 
210
                                /* one operand, absolute address */
 
211
                        /* absolute addr calculation */
 
212
                        absaddr(opcode, op1, addr, label);
 
213
                        fprintf(ofile, mnemonic[opcode], label);
 
214
                        break;
 
215
                case 7:
 
216
                                /* two-byte immediate operand */
 
217
                        /* MOV DPTR, #immediate16 */
 
218
                        fprintf(ofile, mnemonic[opcode], op1, op2);
 
219
                        break;
 
220
                case 8:
 
221
                                /* two operands: direct, immediate */
 
222
                        sfrdecode(op1, name);
 
223
                        printhex(op2, name2);
 
224
                        fprintf(ofile, mnemonic[opcode], name, name2);
 
225
                        break;
 
226
                case 9:
 
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);
 
232
                        break;
 
233
                case 10:
 
234
                                /* two operands: immediate, relative */
 
235
                        printhex(op1, name);
 
236
                        reladdr(op2, addr, label);
 
237
                        fprintf(ofile, mnemonic[opcode], name, label);
 
238
                        break;
 
239
                case 11:
 
240
                                /* two operands: direct, relative */
 
241
                        sfrdecode(op1, name);
 
242
                        reladdr(op2, addr, label);
 
243
                        fprintf(ofile, mnemonic[opcode], name, label);
 
244
                        break;
 
245
                case 12:
 
246
                                /* two operands: bit, relative */
 
247
                        sfbitdecode(op1, name);
 
248
                        reladdr(op2, addr, label);
 
249
                        fprintf(ofile, mnemonic[opcode], name, label);
 
250
                        break;
 
251
                case 13:
 
252
                                /* long address */
 
253
                        /* long addr calculation */
 
254
                        longaddr(op1, op2, label);
 
255
                        fprintf(ofile, mnemonic[opcode], label);
 
256
                        break;
 
257
                default:
 
258
                                /* error in op_format table */
 
259
                        fprintf(ofile, "DB 0%Xh  ; error in op_format table",
 
260
                                opcode);
 
261
        }
 
262
        fprintf(ofile, "\n");
 
263
        
 
264
        return addr;
 
265
}
 
266
 
 
267
/* pass2: Disassemble memory to given output file (pass 2)
 
268
 *
 
269
 */
 
270
void pass2(FILE *ofile, const struct hexfile *hf)
 
271
{
 
272
        int addr = 0;
 
273
        uchar empty = 1; /* 1 for no code/data, 0 for code or data */
 
274
        
 
275
        while (addr < 65536)
 
276
        {
 
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.
 
281
                         */
 
282
                        fprintf(ofile, "CSEG AT %04Xh\n", addr);
 
283
                else if (hf->flag[addr] == EMPTY) {
 
284
                        /* no code or data here */
 
285
                        ++addr;
 
286
                        empty = 1;
 
287
                        continue;
 
288
                }
 
289
                empty = 0;
 
290
                
 
291
                /* Step 2: Output a label if one exists */
 
292
                if (lbl[addr])
 
293
                        fprintf(ofile, "L%04d:\n", lbl[addr]);
 
294
                
 
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);
 
299
                else {
 
300
                        /* data here */
 
301
                        if(!Lst)
 
302
                                fprintf(ofile, "\tDB 0%Xh\n", hf->mem[addr]);
 
303
                        else {
 
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]);
 
307
                                else
 
308
                                        fprintf(ofile, "DB 0%02Xh \n", hf->mem[addr]);
 
309
                        }
 
310
                        ++addr;
 
311
                }
 
312
        }
 
313
        
 
314
        fprintf(ofile, "END\n");
 
315
}