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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [opcodes/] [avr-dis.c] - Blame information for rev 1778

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* Disassemble AVR instructions.
2
   Copyright (C) 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
 
21
#include "dis-asm.h"
22
#include "opintl.h"
23
 
24
typedef unsigned char u8;
25
typedef unsigned short u16;
26
typedef unsigned long u32;
27
 
28
#define IFMASK(a,b)     ((opcode & (a)) == (b))
29
 
30
static char* SREG_flags = "CZNVSHTI";
31
static char* sect94[] = {"COM","NEG","SWAP","INC","NULL","ASR","LSR","ROR",
32
                         0,0,"DEC",0,0,0,0,0};
33
static char* sect98[] = {"CBI","SBIC","SBI","SBIS"};
34
static char* branchs[] = {
35
  "BRCS","BREQ","BRMI","BRVS",
36
  "BRLT","BRHS","BRTS","BRIE",
37
  "BRCC","BRNE","BRPL","BRVC",
38
  "BRGE","BRHC","BRTC","BRID"
39
};
40
 
41
static char* last4[] = {"BLD","BST","SBRC","SBRS"};
42
 
43
 
44
static void dispLDD PARAMS ((u16, char *));
45
 
46
static void
47
dispLDD (opcode, dest)
48
     u16 opcode;
49
     char *dest;
50
{
51
  opcode = (((opcode & 0x2000) >> 8) | ((opcode & 0x0c00) >> 7)
52
            | (opcode & 7));
53
  sprintf(dest, "%d", opcode);
54
}
55
 
56
 
57
static void regPP PARAMS ((u16, char *));
58
 
59
static void
60
regPP (opcode, dest)
61
     u16 opcode;
62
     char *dest;
63
{
64
  opcode = ((opcode & 0x0600) >> 5) | (opcode & 0xf);
65
  sprintf(dest, "0x%02X", opcode);
66
}
67
 
68
 
69
static void reg50 PARAMS ((u16, char *));
70
 
71
static void
72
reg50 (opcode, dest)
73
     u16 opcode;
74
     char *dest;
75
{
76
  opcode = (opcode & 0x01f0) >> 4;
77
  sprintf(dest, "R%d", opcode);
78
}
79
 
80
 
81
static void reg104 PARAMS ((u16, char *));
82
 
83
static void
84
reg104 (opcode, dest)
85
     u16 opcode;
86
     char *dest;
87
{
88
  opcode = (opcode & 0xf) | ((opcode & 0x0200) >> 5);
89
  sprintf(dest, "R%d", opcode);
90
}
91
 
92
 
93
static void reg40 PARAMS ((u16, char *));
94
 
95
static void
96
reg40 (opcode, dest)
97
     u16 opcode;
98
     char *dest;
99
{
100
  opcode = (opcode & 0xf0) >> 4;
101
  sprintf(dest, "R%d", opcode + 16);
102
}
103
 
104
 
105
static void reg20w PARAMS ((u16, char *));
106
 
107
static void
108
reg20w (opcode, dest)
109
     u16 opcode;
110
     char *dest;
111
{
112
  opcode = (opcode & 0x30) >> 4;
113
  sprintf(dest, "R%d", 24 + opcode * 2);
114
}
115
 
116
 
117
static void lit404 PARAMS ((u16, char *));
118
 
119
static void
120
lit404 (opcode, dest)
121
     u16 opcode;
122
     char *dest;
123
{
124
  opcode = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
125
  sprintf(dest, "0x%02X", opcode);
126
}
127
 
128
 
129
static void lit204 PARAMS ((u16, char *));
130
 
131
static void
132
lit204 (opcode, dest)
133
     u16 opcode;
134
     char *dest;
135
{
136
  opcode = ((opcode & 0xc0) >> 2) | (opcode & 0xf);
137
  sprintf(dest, "0x%02X", opcode);
138
}
139
 
140
 
141
static void add0fff PARAMS ((u16, char *, int));
142
 
143
static void
144
add0fff (op, dest, pc)
145
     u16 op;
146
     char *dest;
147
     int pc;
148
{
149
  int rel_addr = (((op & 0xfff) ^ 0x800) - 0x800) * 2;
150
  sprintf(dest, ".%+-8d ; 0x%06X", rel_addr, pc + 2 + rel_addr);
151
}
152
 
153
 
154
static void add03f8 PARAMS ((u16, char *, int));
155
 
156
static void
157
add03f8 (op, dest, pc)
158
     u16 op;
159
     char *dest;
160
     int pc;
161
{
162
  int rel_addr = ((((op >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
163
  sprintf(dest, ".%+-8d ; 0x%06X", rel_addr, pc + 2 + rel_addr);
164
}
165
 
166
 
167
static u16 avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
168
 
169
static u16
170
avrdis_opcode (addr, info)
171
     bfd_vma addr;
172
     disassemble_info *info;
173
{
174
  bfd_byte buffer[2];
175
  int status;
176
  status = info->read_memory_func(addr, buffer, 2, info);
177
  if (status != 0)
178
    {
179
      info->memory_error_func(status, addr, info);
180
      return -1;
181
    }
182
  return bfd_getl16 (buffer);
183
}
184
 
185
 
186
int
187
print_insn_avr(addr, info)
188
     bfd_vma addr;
189
     disassemble_info *info;
190
{
191
  char rr[200];
192
  char rd[200];
193
  u16 opcode;
194
  void *stream = info->stream;
195
  fprintf_ftype prin = info->fprintf_func;
196
  int cmd_len = 2;
197
 
198
  opcode = avrdis_opcode (addr, info);
199
 
200
  if (IFMASK(0xd000, 0x8000))
201
    {
202
      char letter;
203
      reg50(opcode, rd);
204
      dispLDD(opcode, rr);
205
      if (opcode & 8)
206
        letter = 'Y';
207
      else
208
        letter = 'Z';
209
      if (opcode & 0x0200)
210
        (*prin) (stream, "    STD     %c+%s,%s", letter, rr, rd);
211
      else
212
        (*prin) (stream, "    LDD     %s,%c+%s", rd, letter, rr);
213
    }
214
  else
215
    {
216
      switch (opcode & 0xf000)
217
        {
218
        case 0x0000:
219
          {
220
            reg50(opcode, rd);
221
            reg104(opcode, rr);
222
            switch (opcode & 0x0c00)
223
              {
224
              case 0x0000:
225
                (*prin) (stream, "    NOP");
226
                break;
227
              case 0x0400:
228
                (*prin) (stream, "    CPC     %s,%s", rd, rr);
229
                break;
230
              case 0x0800:
231
                (*prin) (stream, "    SBC     %s,%s", rd, rr);
232
                break;
233
              case 0x0c00:
234
                (*prin) (stream, "    ADD     %s,%s", rd, rr);
235
                break;
236
              }
237
          }
238
          break;
239
        case 0x1000:
240
          {
241
            reg50(opcode, rd);
242
            reg104(opcode, rr);
243
            switch (opcode & 0x0c00)
244
              {
245
              case 0x0000:
246
                (*prin) (stream, "    CPSE    %s,%s", rd, rr);
247
                break;
248
              case 0x0400:
249
                (*prin) (stream, "    CP      %s,%s", rd, rr);
250
                break;
251
              case 0x0800:
252
                (*prin) (stream, "    SUB     %s,%s", rd, rr);
253
                break;
254
              case 0x0c00:
255
                (*prin) (stream, "    ADC     %s,%s", rd, rr);
256
                break;
257
              }
258
          }
259
          break;
260
        case 0x2000:
261
          {
262
            reg50(opcode, rd);
263
            reg104(opcode, rr);
264
            switch (opcode & 0x0c00)
265
              {
266
              case 0x0000:
267
                (*prin) (stream, "    AND     %s,%s", rd, rr);
268
                break;
269
              case 0x0400:
270
                (*prin) (stream, "    EOR     %s,%s", rd, rr);
271
                break;
272
              case 0x0800:
273
                (*prin) (stream, "    OR      %s,%s", rd, rr);
274
                break;
275
              case 0x0c00:
276
                (*prin) (stream, "    MOV     %s,%s", rd, rr);
277
                break;
278
              }
279
          }
280
          break;
281
        case 0x3000:
282
          {
283
            reg40(opcode, rd);
284
            lit404(opcode, rr);
285
            (*prin) (stream, "    CPI     %s,%s", rd, rr);
286
          }
287
          break;
288
        case 0x4000:
289
          {
290
            reg40(opcode, rd);
291
            lit404(opcode, rr);
292
            (*prin) (stream, "    SBCI    %s,%s", rd, rr);
293
          }
294
          break;
295
        case 0x5000:
296
          {
297
            reg40(opcode, rd);
298
            lit404(opcode, rr);
299
            (*prin) (stream, "    SUBI    %s,%s", rd, rr);
300
          }
301
          break;
302
        case 0x6000:
303
          {
304
            reg40(opcode, rd);
305
            lit404(opcode, rr);
306
            (*prin) (stream, "    ORI     %s,%s", rd, rr);
307
          }
308
          break;
309
        case 0x7000:
310
          {
311
            reg40(opcode, rd);
312
            lit404(opcode, rr);
313
            (*prin) (stream, "    ANDI    %s,%s", rd, rr);
314
          }
315
          break;
316
        case 0x9000:
317
          {
318
            switch (opcode & 0x0e00)
319
              {
320
              case 0x0000:
321
                {
322
                  reg50(opcode, rd);
323
                  switch (opcode & 0xf)
324
                    {
325
                    case 0x0:
326
                      {
327
                        (*prin) (stream, "    LDS     %s,0x%04X", rd,
328
                                 avrdis_opcode(addr + 2, info));
329
                        cmd_len = 4;
330
                      }
331
                      break;
332
                    case 0x1:
333
                      (*prin) (stream, "    LD      %s,Z+", rd);
334
                      break;
335
                    case 0x2:
336
                      (*prin) (stream, "    LD      %s,-Z", rd);
337
                      break;
338
                    case 0x9:
339
                      (*prin) (stream, "    LD      %s,Y+", rd);
340
                      break;
341
                    case 0xa:
342
                      (*prin) (stream, "    LD      %s,-Y", rd);
343
                      break;
344
                    case 0xc:
345
                      (*prin) (stream, "    LD      %s,X", rd);
346
                      break;
347
                    case 0xd:
348
                      (*prin) (stream, "    LD      %s,X+", rd);
349
                      break;
350
                    case 0xe:
351
                      (*prin) (stream, "    LD      %s,-X", rd);
352
                      break;
353
                    case 0xf:
354
                      (*prin) (stream, "    POP     %s", rd);
355
                      break;
356
                    default:
357
                      (*prin) (stream, "    ????");
358
                      break;
359
                    }
360
                }
361
                break;
362
              case 0x0200:
363
                {
364
                  reg50(opcode, rd);
365
                  switch (opcode & 0xf)
366
                    {
367
                    case 0x0:
368
                      {
369
                        (*prin) (stream, "    STS     0x%04X,%s",
370
                                 avrdis_opcode(addr + 2, info), rd);
371
                        cmd_len = 4;
372
                      }
373
                      break;
374
                    case 0x1:
375
                      (*prin) (stream, "    ST      Z+,%s", rd);
376
                      break;
377
                    case 0x2:
378
                      (*prin) (stream, "    ST      -Z,%s", rd);
379
                      break;
380
                    case 0x9:
381
                      (*prin) (stream, "    ST      Y+,%s", rd);
382
                      break;
383
                    case 0xa:
384
                      (*prin) (stream, "    ST      -Y,%s", rd);
385
                      break;
386
                    case 0xc:
387
                      (*prin) (stream, "    ST      X,%s", rd);
388
                      break;
389
                    case 0xd:
390
                      (*prin) (stream, "    ST      X+,%s", rd);
391
                      break;
392
                    case 0xe:
393
                      (*prin) (stream, "    ST      -X,%s", rd);
394
                      break;
395
                    case 0xf:
396
                      (*prin) (stream, "    PUSH    %s", rd);
397
                      break;
398
                    default:
399
                      (*prin) (stream, "    ????");
400
                      break;
401
                    }
402
                }
403
                break;
404
              case 0x0400:
405
                {
406
                  if (IFMASK(0x020c, 0x000c))
407
                    {
408
                      u32 k = ((opcode & 0x01f0) >> 3) | (opcode & 1);
409
                      k = (k << 16) | avrdis_opcode(addr + 2, info);
410
                      if (opcode & 0x0002)
411
                        (*prin) (stream, "    CALL    0x%06X", k*2);
412
                      else
413
                        (*prin) (stream, "    JMP     0x%06X", k*2);
414
                      cmd_len = 4;
415
                    }
416
                  else if (IFMASK(0x010f, 0x0008))
417
                    {
418
                      int sf = (opcode & 0x70) >> 4;
419
                      if (opcode & 0x0080)
420
                        (*prin) (stream, "    CL%c", SREG_flags[sf]);
421
                      else
422
                        (*prin) (stream, "    SE%c", SREG_flags[sf]);
423
                    }
424
                  else if (IFMASK(0x000f, 0x0009))
425
                    {
426
                      if (opcode & 0x0100)
427
                        (*prin) (stream, "    ICALL");
428
                      else
429
                        (*prin) (stream, "    IJMP");
430
                    }
431
                  else if (IFMASK(0x010f, 0x0108))
432
                    {
433
                      if (IFMASK(0x0090, 0x0000))
434
                        (*prin) (stream, "    RET");
435
                      else if (IFMASK(0x0090, 0x0010))
436
                        (*prin) (stream, "    RETI");
437
                      else if (IFMASK(0x00e0, 0x0080))
438
                        (*prin) (stream, "    SLEEP");
439
                      else if (IFMASK(0x00e0, 0x00a0))
440
                        (*prin) (stream, "    WDR");
441
                      else if (IFMASK(0x00f0, 0x00c0))
442
                        (*prin) (stream, "    LPM");
443
                      else if (IFMASK(0x00f0, 0x00d0))
444
                        (*prin) (stream, "    ELPM");
445
                      else
446
                        (*prin) (stream, "    ????");
447
                    }
448
                  else
449
                    {
450
                      const char* p;
451
                      reg50(opcode, rd);
452
                      p = sect94[opcode & 0xf];
453
                      if (!p)
454
                        p = "????";
455
                      (*prin) (stream, "    %-8s%s", p, rd);
456
                    }
457
                }
458
                break;
459
              case 0x0600:
460
                {
461
                  if (opcode & 0x0200)
462
                    {
463
                      lit204(opcode, rd);
464
                      reg20w(opcode, rr);
465
                      if (opcode & 0x0100)
466
                        (*prin) (stream, "    SBIW    %s,%s", rr, rd);
467
                      else
468
                        (*prin) (stream, "    ADIW    %s,%s", rr, rd);
469
                    }
470
                }
471
                break;
472
              case 0x0800:
473
              case 0x0a00:
474
                {
475
                  (*prin) (stream, "    %-8s0x%02X,%d",
476
                           sect98[(opcode & 0x0300) >> 8],
477
                           (opcode & 0xf8) >> 3,
478
                           opcode & 7);
479
                }
480
                break;
481
              default:
482
                {
483
                  reg50(opcode, rd);
484
                  reg104(opcode, rr);
485
                  (*prin) (stream, "    MUL     %s,%s", rd, rr);
486
                }
487
              }
488
          }
489
          break;
490
        case 0xb000:
491
          {
492
            reg50(opcode, rd);
493
            regPP(opcode, rr);
494
            if (opcode & 0x0800)
495
              (*prin) (stream, "    OUT     %s,%s", rr, rd);
496
            else
497
              (*prin) (stream, "    IN      %s,%s", rd, rr);
498
          }
499
          break;
500
        case 0xc000:
501
          {
502
            add0fff(opcode, rd, addr);
503
            (*prin) (stream, "    RJMP    %s", rd);
504
          }
505
          break;
506
        case 0xd000:
507
          {
508
            add0fff(opcode, rd, addr);
509
            (*prin) (stream, "    RCALL   %s", rd);
510
          }
511
          break;
512
        case 0xe000:
513
          {
514
            reg40(opcode, rd);
515
            lit404(opcode, rr);
516
            (*prin) (stream, "    LDI     %s,%s", rd, rr);
517
          }
518
          break;
519
        case 0xf000:
520
          {
521
            if (opcode & 0x0800)
522
              {
523
                reg50(opcode, rd);
524
                (*prin) (stream, "    %-8s%s,%d",
525
                         last4[(opcode & 0x0600) >> 9],
526
                         rd, opcode & 7);
527
              }
528
            else
529
              {
530
                char* p;
531
                add03f8(opcode, rd, addr);
532
                p = branchs[((opcode & 0x0400) >> 7) | (opcode & 7)];
533
                (*prin) (stream, "    %-8s%s", p, rd);
534
              }
535
          }
536
          break;
537
        }
538
    }
539
  return cmd_len;
540
}

powered by: WebSVN 2.1.0

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