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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [opcodes/] [tic30-dis.c] - Blame information for rev 297

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

Line No. Rev Author Line
1 24 jeremybenn
/* Disassembly routines for TMS320C30 architecture
2 225 jeremybenn
   Copyright 1998, 1999, 2000, 2002, 2005, 2007, 2009
3
   Free Software Foundation, Inc.
4 24 jeremybenn
   Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
5
 
6
   This file is part of the GNU opcodes library.
7
 
8
   This library is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   It is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this file; see the file COPYING.  If not, write to the
20
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include <errno.h>
24
#include <math.h>
25
#include "sysdep.h"
26
#include "dis-asm.h"
27
#include "opcode/tic30.h"
28
 
29
#define NORMAL_INSN   1
30
#define PARALLEL_INSN 2
31
 
32
/* Gets the type of instruction based on the top 2 or 3 bits of the
33
   instruction word.  */
34
#define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
35
 
36
/* Instruction types.  */
37
#define TWO_OPERAND_1 0x00000000
38
#define TWO_OPERAND_2 0x40000000
39
#define THREE_OPERAND 0x20000000
40
#define PAR_STORE     0xC0000000
41
#define MUL_ADDS      0x80000000
42
#define BRANCHES      0x60000000
43
 
44
/* Specific instruction id bits.  */
45
#define NORMAL_IDEN    0x1F800000
46
#define PAR_STORE_IDEN 0x3E000000
47
#define MUL_ADD_IDEN   0x2C000000
48
#define BR_IMM_IDEN    0x1F000000
49
#define BR_COND_IDEN   0x1C3F0000
50
 
51
/* Addressing modes.  */
52
#define AM_REGISTER 0x00000000
53
#define AM_DIRECT   0x00200000
54
#define AM_INDIRECT 0x00400000
55
#define AM_IMM      0x00600000
56
 
57
#define P_FIELD 0x03000000
58
 
59
#define REG_AR0 0x08
60
#define LDP_INSN 0x08700000
61
 
62
/* TMS320C30 program counter for current instruction.  */
63
static unsigned int _pc;
64
 
65
struct instruction
66
{
67
  int type;
68 225 jeremybenn
  insn_template *tm;
69 24 jeremybenn
  partemplate *ptm;
70
};
71
 
72
static int
73
get_tic30_instruction (unsigned long insn_word, struct instruction *insn)
74
{
75
  switch (GET_TYPE (insn_word))
76
    {
77
    case TWO_OPERAND_1:
78
    case TWO_OPERAND_2:
79
    case THREE_OPERAND:
80
      insn->type = NORMAL_INSN;
81
      {
82 225 jeremybenn
        insn_template *current_optab = (insn_template *) tic30_optab;
83 24 jeremybenn
 
84
        for (; current_optab < tic30_optab_end; current_optab++)
85
          {
86
            if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
87
              {
88
                if (current_optab->operands == 0)
89
                  {
90
                    if (current_optab->base_opcode == insn_word)
91
                      {
92
                        insn->tm = current_optab;
93
                        break;
94
                      }
95
                  }
96
                else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
97
                  {
98
                    insn->tm = current_optab;
99
                    break;
100
                  }
101
              }
102
          }
103
      }
104
      break;
105
 
106
    case PAR_STORE:
107
      insn->type = PARALLEL_INSN;
108
      {
109
        partemplate *current_optab = (partemplate *) tic30_paroptab;
110
 
111
        for (; current_optab < tic30_paroptab_end; current_optab++)
112
          {
113
            if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
114
              {
115
                if ((current_optab->base_opcode & PAR_STORE_IDEN)
116
                    == (insn_word & PAR_STORE_IDEN))
117
                  {
118
                    insn->ptm = current_optab;
119
                    break;
120
                  }
121
              }
122
          }
123
      }
124
      break;
125
 
126
    case MUL_ADDS:
127
      insn->type = PARALLEL_INSN;
128
      {
129
        partemplate *current_optab = (partemplate *) tic30_paroptab;
130
 
131
        for (; current_optab < tic30_paroptab_end; current_optab++)
132
          {
133
            if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
134
              {
135
                if ((current_optab->base_opcode & MUL_ADD_IDEN)
136
                    == (insn_word & MUL_ADD_IDEN))
137
                  {
138
                    insn->ptm = current_optab;
139
                    break;
140
                  }
141
              }
142
          }
143
      }
144
      break;
145
 
146
    case BRANCHES:
147
      insn->type = NORMAL_INSN;
148
      {
149 225 jeremybenn
        insn_template *current_optab = (insn_template *) tic30_optab;
150 24 jeremybenn
 
151
        for (; current_optab < tic30_optab_end; current_optab++)
152
          {
153
            if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
154
              {
155
                if (current_optab->operand_types[0] & Imm24)
156
                  {
157
                    if ((current_optab->base_opcode & BR_IMM_IDEN)
158
                        == (insn_word & BR_IMM_IDEN))
159
                      {
160
                        insn->tm = current_optab;
161
                        break;
162
                      }
163
                  }
164
                else if (current_optab->operands > 0)
165
                  {
166
                    if ((current_optab->base_opcode & BR_COND_IDEN)
167
                        == (insn_word & BR_COND_IDEN))
168
                      {
169
                        insn->tm = current_optab;
170
                        break;
171
                      }
172
                  }
173
                else
174
                  {
175
                    if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000))
176
                        == (insn_word & (BR_COND_IDEN | 0x00800000)))
177
                      {
178
                        insn->tm = current_optab;
179
                        break;
180
                      }
181
                  }
182
              }
183
          }
184
      }
185
      break;
186
    default:
187
      return 0;
188
    }
189
  return 1;
190
}
191
 
192
static int
193
get_register_operand (unsigned char fragment, char *buffer)
194
{
195
  const reg *current_reg = tic30_regtab;
196
 
197
  if (buffer == NULL)
198
    return 0;
199
  for (; current_reg < tic30_regtab_end; current_reg++)
200
    {
201
      if ((fragment & 0x1F) == current_reg->opcode)
202
        {
203
          strcpy (buffer, current_reg->name);
204
          return 1;
205
        }
206
    }
207
  return 0;
208
}
209
 
210
static int
211
get_indirect_operand (unsigned short fragment,
212
                      int size,
213
                      char *buffer)
214
{
215
  unsigned char mod;
216
  unsigned arnum;
217
  unsigned char disp;
218
 
219
  if (buffer == NULL)
220
    return 0;
221
  /* Determine which bits identify the sections of the indirect
222
     operand based on the size in bytes.  */
223
  switch (size)
224
    {
225
    case 1:
226
      mod = (fragment & 0x00F8) >> 3;
227
      arnum = (fragment & 0x0007);
228
      disp = 0;
229
      break;
230
    case 2:
231
      mod = (fragment & 0xF800) >> 11;
232
      arnum = (fragment & 0x0700) >> 8;
233
      disp = (fragment & 0x00FF);
234
      break;
235
    default:
236
      return 0;
237
    }
238
  {
239
    const ind_addr_type *current_ind = tic30_indaddr_tab;
240
 
241
    for (; current_ind < tic30_indaddrtab_end; current_ind++)
242
      {
243
        if (current_ind->modfield == mod)
244
          {
245
            if (current_ind->displacement == IMPLIED_DISP && size == 2)
246
              continue;
247
 
248
            else
249
              {
250
                size_t i, len;
251
                int bufcnt;
252
 
253
                len = strlen (current_ind->syntax);
254
                for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
255
                  {
256
                    buffer[bufcnt] = current_ind->syntax[i];
257
                    if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r')
258
                      buffer[++bufcnt] = arnum + '0';
259
                    if (buffer[bufcnt] == '('
260
                        && current_ind->displacement == DISP_REQUIRED)
261
                      {
262
                        sprintf (&buffer[bufcnt + 1], "%u", disp);
263
                        bufcnt += strlen (&buffer[bufcnt + 1]);
264
                      }
265
                  }
266
                buffer[bufcnt + 1] = '\0';
267
                break;
268
              }
269
          }
270
      }
271
  }
272
  return 1;
273
}
274
 
275
static int
276
cnvt_tmsfloat_ieee (unsigned long tmsfloat, int size, float *ieeefloat)
277
{
278
  unsigned long exp, sign, mant;
279
  union
280
  {
281
    unsigned long l;
282
    float f;
283
  } val;
284
 
285
  if (size == 2)
286
    {
287
      if ((tmsfloat & 0x0000F000) == 0x00008000)
288
        tmsfloat = 0x80000000;
289
      else
290
        {
291
          tmsfloat <<= 16;
292
          tmsfloat = (long) tmsfloat >> 4;
293
        }
294
    }
295
  exp = tmsfloat & 0xFF000000;
296
  if (exp == 0x80000000)
297
    {
298
      *ieeefloat = 0.0;
299
      return 1;
300
    }
301
  exp += 0x7F000000;
302
  sign = (tmsfloat & 0x00800000) << 8;
303
  mant = tmsfloat & 0x007FFFFF;
304
  if (exp == 0xFF000000)
305
    {
306
      if (mant == 0)
307
        *ieeefloat = ERANGE;
308
#ifdef HUGE_VALF
309
      if (sign == 0)
310
        *ieeefloat = HUGE_VALF;
311
      else
312
        *ieeefloat = -HUGE_VALF;
313
#else
314
      if (sign == 0)
315
        *ieeefloat = 1.0 / 0.0;
316
      else
317
        *ieeefloat = -1.0 / 0.0;
318
#endif
319
      return 1;
320
    }
321
  exp >>= 1;
322
  if (sign)
323
    {
324
      mant = (~mant) & 0x007FFFFF;
325
      mant += 1;
326
      exp += mant & 0x00800000;
327
      exp &= 0x7F800000;
328
      mant &= 0x007FFFFF;
329
    }
330
  if (tmsfloat == 0x80000000)
331
    sign = mant = exp = 0;
332
  tmsfloat = sign | exp | mant;
333
  val.l = tmsfloat;
334
  *ieeefloat = val.f;
335
  return 1;
336
}
337
 
338
static int
339
print_two_operand (disassemble_info *info,
340
                   unsigned long insn_word,
341
                   struct instruction *insn)
342
{
343
  char name[12];
344
  char operand[2][13] =
345
  {
346
    {0},
347
    {0}
348
  };
349
  float f_number;
350
 
351
  if (insn->tm == NULL)
352
    return 0;
353
  strcpy (name, insn->tm->name);
354
  if (insn->tm->opcode_modifier == AddressMode)
355
    {
356
      int src_op, dest_op;
357
      /* Determine whether instruction is a store or a normal instruction.  */
358
      if ((insn->tm->operand_types[1] & (Direct | Indirect))
359
          == (Direct | Indirect))
360
        {
361
          src_op = 1;
362
          dest_op = 0;
363
        }
364
      else
365
        {
366
          src_op = 0;
367
          dest_op = 1;
368
        }
369
      /* Get the destination register.  */
370
      if (insn->tm->operands == 2)
371
        get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
372
      /* Get the source operand based on addressing mode.  */
373
      switch (insn_word & AddressMode)
374
        {
375
        case AM_REGISTER:
376
          /* Check for the NOP instruction before getting the operand.  */
377
          if ((insn->tm->operand_types[0] & NotReq) == 0)
378
            get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
379
          break;
380
        case AM_DIRECT:
381
          sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
382
          break;
383
        case AM_INDIRECT:
384
          get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
385
          break;
386
        case AM_IMM:
387
          /* Get the value of the immediate operand based on variable type.  */
388
          switch (insn->tm->imm_arg_type)
389
            {
390
            case Imm_Float:
391
              cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
392
              sprintf (operand[src_op], "%2.2f", f_number);
393
              break;
394
            case Imm_SInt:
395
              sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
396
              break;
397
            case Imm_UInt:
398
              sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
399
              break;
400
            default:
401
              return 0;
402
            }
403
          /* Handle special case for LDP instruction.  */
404
          if ((insn_word & 0xFFFFFF00) == LDP_INSN)
405
            {
406
              strcpy (name, "ldp");
407
              sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
408
              operand[1][0] = '\0';
409
            }
410
        }
411
    }
412
  /* Handle case for stack and rotate instructions.  */
413
  else if (insn->tm->operands == 1)
414
    {
415
      if (insn->tm->opcode_modifier == StackOp)
416
        get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
417
    }
418
  /* Output instruction to stream.  */
419
  info->fprintf_func (info->stream, "   %s %s%c%s", name,
420
                      operand[0][0] ? operand[0] : "",
421
                      operand[1][0] ? ',' : ' ',
422
                      operand[1][0] ? operand[1] : "");
423
  return 1;
424
}
425
 
426
static int
427
print_three_operand (disassemble_info *info,
428
                     unsigned long insn_word,
429
                     struct instruction *insn)
430
{
431
  char operand[3][13] =
432
  {
433
    {0},
434
    {0},
435
    {0}
436
  };
437
 
438
  if (insn->tm == NULL)
439
    return 0;
440
  switch (insn_word & AddressMode)
441
    {
442
    case AM_REGISTER:
443
      get_register_operand ((insn_word & 0x000000FF), operand[0]);
444
      get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
445
      break;
446
    case AM_DIRECT:
447
      get_register_operand ((insn_word & 0x000000FF), operand[0]);
448
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
449
      break;
450
    case AM_INDIRECT:
451
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
452
      get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
453
      break;
454
    case AM_IMM:
455
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
456
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
457
      break;
458
    default:
459
      return 0;
460
    }
461
  if (insn->tm->operands == 3)
462
    get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
463
  info->fprintf_func (info->stream, "   %s %s,%s%c%s", insn->tm->name,
464
                      operand[0], operand[1],
465
                      operand[2][0] ? ',' : ' ',
466
                      operand[2][0] ? operand[2] : "");
467
  return 1;
468
}
469
 
470
static int
471
print_par_insn (disassemble_info *info,
472
                unsigned long insn_word,
473
                struct instruction *insn)
474
{
475
  size_t i, len;
476
  char *name1, *name2;
477
  char operand[2][3][13] =
478
  {
479
    {
480
      {0},
481
      {0},
482
      {0}
483
    },
484
    {
485
      {0},
486
      {0},
487
      {0}
488
    }
489
  };
490
 
491
  if (insn->ptm == NULL)
492
    return 0;
493
  /* Parse out the names of each of the parallel instructions from the
494
     q_insn1_insn2 format.  */
495
  name1 = (char *) strdup (insn->ptm->name + 2);
496
  name2 = "";
497
  len = strlen (name1);
498
  for (i = 0; i < len; i++)
499
    {
500
      if (name1[i] == '_')
501
        {
502
          name2 = &name1[i + 1];
503
          name1[i] = '\0';
504
          break;
505
        }
506
    }
507
  /* Get the operands of the instruction based on the operand order.  */
508
  switch (insn->ptm->oporder)
509
    {
510
    case OO_4op1:
511
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
512
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
513
      get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
514
      get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
515
      break;
516
    case OO_4op2:
517
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
518
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
519
      get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
520
      get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
521
      break;
522
    case OO_4op3:
523
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
524
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
525
      get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
526
      get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
527
      break;
528
    case OO_5op1:
529
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
530
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
531
      get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
532
      get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
533
      get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
534
      break;
535
    case OO_5op2:
536
      get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
537
      get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
538
      get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
539
      get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
540
      get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
541
      break;
542
    case OO_PField:
543
      if (insn_word & 0x00800000)
544
        get_register_operand (0x01, operand[0][2]);
545
      else
546
        get_register_operand (0x00, operand[0][2]);
547
      if (insn_word & 0x00400000)
548
        get_register_operand (0x03, operand[1][2]);
549
      else
550
        get_register_operand (0x02, operand[1][2]);
551
      switch (insn_word & P_FIELD)
552
        {
553
        case 0x00000000:
554
          get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
555
          get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
556
          get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
557
          get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
558
          break;
559
        case 0x01000000:
560
          get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
561
          get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
562
          get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
563
          get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
564
          break;
565
        case 0x02000000:
566
          get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
567
          get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
568
          get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
569
          get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
570
          break;
571
        case 0x03000000:
572
          get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
573
          get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
574
          get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
575
          get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
576
          break;
577
        }
578
      break;
579
    default:
580
      return 0;
581
    }
582
  info->fprintf_func (info->stream, "   %s %s,%s%c%s", name1,
583
                      operand[0][0], operand[0][1],
584
                      operand[0][2][0] ? ',' : ' ',
585
                      operand[0][2][0] ? operand[0][2] : "");
586
  info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
587
                      operand[1][0], operand[1][1],
588
                      operand[1][2][0] ? ',' : ' ',
589
                      operand[1][2][0] ? operand[1][2] : "");
590
  free (name1);
591
  return 1;
592
}
593
 
594
static int
595
print_branch (disassemble_info *info,
596
              unsigned long insn_word,
597
              struct instruction *insn)
598
{
599
  char operand[2][13] =
600
  {
601
    {0},
602
    {0}
603
  };
604
  unsigned long address;
605
  int print_label = 0;
606
 
607
  if (insn->tm == NULL)
608
    return 0;
609
  /* Get the operands for 24-bit immediate jumps.  */
610
  if (insn->tm->operand_types[0] & Imm24)
611
    {
612
      address = insn_word & 0x00FFFFFF;
613
      sprintf (operand[0], "0x%lX", address);
614
      print_label = 1;
615
    }
616
  /* Get the operand for the trap instruction.  */
617
  else if (insn->tm->operand_types[0] & IVector)
618
    {
619
      address = insn_word & 0x0000001F;
620
      sprintf (operand[0], "0x%lX", address);
621
    }
622
  else
623
    {
624
      address = insn_word & 0x0000FFFF;
625
      /* Get the operands for the DB instructions.  */
626
      if (insn->tm->operands == 2)
627
        {
628
          get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
629
          if (insn_word & PCRel)
630
            {
631
              sprintf (operand[1], "%d", (short) address);
632
              print_label = 1;
633
            }
634
          else
635
            get_register_operand (insn_word & 0x0000001F, operand[1]);
636
        }
637
      /* Get the operands for the standard branches.  */
638
      else if (insn->tm->operands == 1)
639
        {
640
          if (insn_word & PCRel)
641
            {
642
              address = (short) address;
643
              sprintf (operand[0], "%ld", address);
644
              print_label = 1;
645
            }
646
          else
647
            get_register_operand (insn_word & 0x0000001F, operand[0]);
648
        }
649
    }
650
  info->fprintf_func (info->stream, "   %s %s%c%s", insn->tm->name,
651
                      operand[0][0] ? operand[0] : "",
652
                      operand[1][0] ? ',' : ' ',
653
                      operand[1][0] ? operand[1] : "");
654
  /* Print destination of branch in relation to current symbol.  */
655
  if (print_label && info->symbols)
656
    {
657
      asymbol *sym = *info->symbols;
658
 
659
      if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
660
        {
661
          address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
662
          /* Check for delayed instruction, if so adjust destination.  */
663
          if (insn_word & 0x00200000)
664
            address += 2;
665
        }
666
      else
667
        {
668
          address -= ((sym->section->vma + sym->value) / 4);
669
        }
670
      if (address == 0)
671
        info->fprintf_func (info->stream, " <%s>", sym->name);
672
      else
673
        info->fprintf_func (info->stream, " <%s %c %d>", sym->name,
674
                            ((short) address < 0) ? '-' : '+',
675
                            abs (address));
676
    }
677
  return 1;
678
}
679
 
680
int
681
print_insn_tic30 (bfd_vma pc, disassemble_info *info)
682
{
683
  unsigned long insn_word;
684
  struct instruction insn = { 0, NULL, NULL };
685
  bfd_vma bufaddr = pc - info->buffer_vma;
686
 
687
  /* Obtain the current instruction word from the buffer.  */
688
  insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
689
    (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
690
  _pc = pc / 4;
691
  /* Get the instruction refered to by the current instruction word
692
     and print it out based on its type.  */
693
  if (!get_tic30_instruction (insn_word, &insn))
694
    return -1;
695
  switch (GET_TYPE (insn_word))
696
    {
697
    case TWO_OPERAND_1:
698
    case TWO_OPERAND_2:
699
      if (!print_two_operand (info, insn_word, &insn))
700
        return -1;
701
      break;
702
    case THREE_OPERAND:
703
      if (!print_three_operand (info, insn_word, &insn))
704
        return -1;
705
      break;
706
    case PAR_STORE:
707
    case MUL_ADDS:
708
      if (!print_par_insn (info, insn_word, &insn))
709
        return -1;
710
      break;
711
    case BRANCHES:
712
      if (!print_branch (info, insn_word, &insn))
713
        return -1;
714
      break;
715
    }
716
  return 4;
717
}

powered by: WebSVN 2.1.0

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