OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [avr-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Disassemble AVR instructions.
2
   Copyright 1999, 2000 Free Software Foundation, Inc.
3
 
4
   Contributed by Denis Chertykov <denisc@overta.ru>
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
 
20
#include <assert.h>
21
#include "sysdep.h"
22
#include "dis-asm.h"
23
#include "opintl.h"
24
 
25
 
26
struct avr_opcodes_s
27
{
28
  char *name;
29
  char *constraints;
30
  char *opcode;
31
  int insn_size;                /* in words */
32
  int isa;
33
  unsigned int bin_opcode;
34
  unsigned int bin_mask;
35
};
36
 
37
#define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \
38
{#NAME, CONSTR, OPCODE, SIZE, ISA, BIN, 0},
39
 
40
struct avr_opcodes_s avr_opcodes[] =
41
{
42
  #include "opcode/avr.h"
43
  {NULL, NULL, NULL, 0, 0, 0, 0}
44
};
45
 
46
static int avr_operand PARAMS ((unsigned int, unsigned int,
47
                                unsigned int, int, char *, char *, int));
48
 
49
static int
50
avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
51
     unsigned int insn;
52
     unsigned int insn2;
53
     unsigned int pc;
54
     int constraint;
55
     char *buf;
56
     char *comment;
57
     int regs;
58
{
59
  int ok = 1;
60
 
61
  switch (constraint)
62
    {
63
      /* Any register operand.  */
64
    case 'r':
65
      if (regs)
66
        insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* source register */
67
      else
68
        insn = (insn & 0x01f0) >> 4; /* destination register */
69
 
70
      sprintf (buf, "r%d", insn);
71
      break;
72
 
73
    case 'd':
74
      if (regs)
75
        sprintf (buf, "r%d", 16 + (insn & 0xf));
76
      else
77
        sprintf (buf, "r%d", 16 + ((insn & 0xf0) >> 4));
78
      break;
79
 
80
    case 'w':
81
      sprintf (buf, "r%d", 24 + ((insn & 0x30) >> 3));
82
      break;
83
 
84
    case 'a':
85
      if (regs)
86
        sprintf (buf, "r%d", 16 + (insn & 7));
87
      else
88
        sprintf (buf, "r%d", 16 + ((insn >> 4) & 7));
89
      break;
90
 
91
    case 'v':
92
      if (regs)
93
        sprintf (buf, "r%d", (insn & 0xf) * 2);
94
      else
95
        sprintf (buf, "r%d", ((insn & 0xf0) >> 3));
96
      break;
97
 
98
    case 'e':
99
      {
100
        char *xyz;
101
 
102
        switch (insn & 0x100f)
103
          {
104
            case 0x0000: xyz = "Z";  break;
105
            case 0x1001: xyz = "Z+"; break;
106
            case 0x1002: xyz = "-Z"; break;
107
            case 0x0008: xyz = "Y";  break;
108
            case 0x1009: xyz = "Y+"; break;
109
            case 0x100a: xyz = "-Y"; break;
110
            case 0x100c: xyz = "X";  break;
111
            case 0x100d: xyz = "X+"; break;
112
            case 0x100e: xyz = "-X"; break;
113
            default: xyz = "??"; ok = 0;
114
          }
115
        sprintf (buf, xyz);
116
 
117
        if (AVR_UNDEF_P (insn))
118
          sprintf (comment, _("undefined"));
119
      }
120
      break;
121
 
122
    case 'z':
123
      *buf++ = 'Z';
124
      if (insn & 0x1)
125
        *buf++ = '+';
126
      *buf = '\0';
127
      if (AVR_UNDEF_P (insn))
128
        sprintf (comment, _("undefined"));
129
      break;
130
 
131
    case 'b':
132
      {
133
        unsigned int x;
134
 
135
        x = (insn & 7);
136
        x |= (insn >> 7) & (3 << 3);
137
        x |= (insn >> 8) & (1 << 5);
138
 
139
        if (insn & 0x8)
140
          *buf++ = 'Y';
141
        else
142
          *buf++ = 'Z';
143
        sprintf (buf, "+%d", x);
144
        sprintf (comment, "0x%02x", x);
145
      }
146
      break;
147
 
148
    case 'h':
149
      sprintf (buf, "0x%x",
150
               ((((insn & 1) | ((insn & 0x1f0) >> 3)) << 16) | insn2) * 2);
151
      break;
152
 
153
    case 'L':
154
      {
155
        int rel_addr = (((insn & 0xfff) ^ 0x800) - 0x800) * 2;
156
        sprintf (buf, ".%+-8d", rel_addr);
157
        sprintf (comment, "0x%x", pc + 2 + rel_addr);
158
      }
159
      break;
160
 
161
    case 'l':
162
      {
163
        int rel_addr = ((((insn >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
164
        sprintf (buf, ".%+-8d", rel_addr);
165
        sprintf (comment, "0x%x", pc + 2 + rel_addr);
166
      }
167
      break;
168
 
169
    case 'i':
170
      sprintf (buf, "0x%04X", insn2);
171
      break;
172
 
173
    case 'M':
174
      sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf));
175
      sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf));
176
      break;
177
 
178
    case 'n':
179
      sprintf (buf, "??");
180
      fprintf (stderr, _("Internal disassembler error"));
181
      ok = 0;
182
      break;
183
 
184
    case 'K':
185
      {
186
        unsigned int x;
187
 
188
        x = (insn & 0xf) | ((insn >> 2) & 0x30);
189
        sprintf (buf, "0x%02x", x);
190
        sprintf (comment, "%d", x);
191
      }
192
      break;
193
 
194
    case 's':
195
      sprintf (buf, "%d", insn & 7);
196
      break;
197
 
198
    case 'S':
199
      sprintf (buf, "%d", (insn >> 4) & 7);
200
      break;
201
 
202
    case 'P':
203
      {
204
        unsigned int x;
205
        x = (insn & 0xf);
206
        x |= (insn >> 5) & 0x30;
207
        sprintf (buf, "0x%02x", x);
208
        sprintf (comment, "%d", x);
209
      }
210
      break;
211
 
212
    case 'p':
213
      {
214
        unsigned int x;
215
 
216
        x = (insn >> 3) & 0x1f;
217
        sprintf (buf, "0x%02x", x);
218
        sprintf (comment, "%d", x);
219
      }
220
      break;
221
 
222
    case '?':
223
      *buf = '\0';
224
      break;
225
 
226
    default:
227
      sprintf (buf, "??");
228
      fprintf (stderr, _("unknown constraint `%c'"), constraint);
229
      ok = 0;
230
    }
231
 
232
    return ok;
233
}
234
 
235
static unsigned short avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
236
 
237
static unsigned short
238
avrdis_opcode (addr, info)
239
     bfd_vma addr;
240
     disassemble_info *info;
241
{
242
  bfd_byte buffer[2];
243
  int status;
244
  status = info->read_memory_func(addr, buffer, 2, info);
245
  if (status != 0)
246
    {
247
      info->memory_error_func(status, addr, info);
248
      return -1;
249
    }
250
  return bfd_getl16 (buffer);
251
}
252
 
253
 
254
int
255
print_insn_avr(addr, info)
256
     bfd_vma addr;
257
     disassemble_info *info;
258
{
259
  unsigned int insn, insn2;
260
  struct avr_opcodes_s *opcode;
261
  void *stream = info->stream;
262
  fprintf_ftype prin = info->fprintf_func;
263
  static int initialized;
264
  int cmd_len = 2;
265
  int ok = 0;
266
  char op1[20], op2[20], comment1[40], comment2[40];
267
 
268
  if (!initialized)
269
    {
270
      initialized = 1;
271
 
272
      for (opcode = avr_opcodes; opcode->name; opcode++)
273
        {
274
          char * s;
275
          unsigned int bin = 0;
276
          unsigned int mask = 0;
277
 
278
          for (s = opcode->opcode; *s; ++s)
279
            {
280
              bin <<= 1;
281
              mask <<= 1;
282
              bin |= (*s == '1');
283
              mask |= (*s == '1' || *s == '0');
284
            }
285
          assert (s - opcode->opcode == 16);
286
          assert (opcode->bin_opcode == bin);
287
          opcode->bin_mask = mask;
288
        }
289
    }
290
 
291
  insn = avrdis_opcode (addr, info);
292
 
293
  for (opcode = avr_opcodes; opcode->name; opcode++)
294
    {
295
      if ((insn & opcode->bin_mask) == opcode->bin_opcode)
296
        break;
297
    }
298
 
299
  /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
300
     `std b+0,r' as `st b,r' (next entry in the table).  */
301
 
302
  if (AVR_DISP0_P (insn))
303
    opcode++;
304
 
305
  op1[0] = 0;
306
  op2[0] = 0;
307
  comment1[0] = 0;
308
  comment2[0] = 0;
309
 
310
  if (opcode->name)
311
    {
312
      char *op = opcode->constraints;
313
 
314
      insn2 = 0;
315
      ok = 1;
316
 
317
      if (opcode->insn_size > 1)
318
        {
319
          insn2 = avrdis_opcode (addr + 2, info);
320
          cmd_len = 4;
321
        }
322
 
323
      if (*op && *op != '?')
324
        {
325
          int regs = REGISTER_P (*op);
326
 
327
          ok = avr_operand (insn, insn2, addr, *op, op1, comment1, 0);
328
 
329
          if (ok && *(++op) == ',')
330
            ok = avr_operand (insn, insn2, addr, *(++op), op2,
331
                              *comment1 ? comment2 : comment1, regs);
332
        }
333
    }
334
 
335
  if (!ok)
336
    {
337
      /* Unknown opcode, or invalid combination of operands.  */
338
      sprintf (op1, "0x%04x", insn);
339
      op2[0] = 0;
340
      sprintf (comment1, "????");
341
      comment2[0] = 0;
342
    }
343
 
344
  (*prin) (stream, "%s", ok ? opcode->name : ".word");
345
 
346
  if (*op1)
347
    (*prin) (stream, "\t%s", op1);
348
 
349
  if (*op2)
350
    (*prin) (stream, ", %s", op2);
351
 
352
  if (*comment1)
353
    (*prin) (stream, "\t; %s", comment1);
354
 
355
  if (*comment2)
356
    (*prin) (stream, " %s", comment2);
357
 
358
  return cmd_len;
359
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.