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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [d30v-dis.c] - Blame information for rev 1777

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

Line No. Rev Author Line
1 1181 sfurman
/* Disassemble D30V instructions.
2
   Copyright 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
3
 
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
 
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
 
18
#include <stdio.h>
19
#include "sysdep.h"
20
#include "opcode/d30v.h"
21
#include "dis-asm.h"
22
#include "opintl.h"
23
 
24
#define PC_MASK 0xFFFFFFFF
25
 
26
static int lookup_opcode PARAMS ((struct d30v_insn *insn, long num, int is_long));
27
static void print_insn PARAMS ((struct disassemble_info *info, bfd_vma memaddr, long long num,
28
                                 struct d30v_insn *insn, int is_long, int show_ext));
29
static int extract_value PARAMS ((long long num, struct d30v_operand *oper, int is_long));
30
 
31
int
32
print_insn_d30v (memaddr, info)
33
     bfd_vma memaddr;
34
     struct disassemble_info *info;
35
{
36
  int status, result;
37
  bfd_byte buffer[12];
38
  unsigned long in1, in2;
39
  struct d30v_insn insn;
40
  long long num;
41
 
42
  insn.form = (struct d30v_format *) NULL;
43
 
44
  info->bytes_per_line = 8;
45
  info->bytes_per_chunk = 4;
46
  info->display_endian = BFD_ENDIAN_BIG;
47
 
48
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
49
  if (status != 0)
50
    {
51
      (*info->memory_error_func) (status, memaddr, info);
52
      return -1;
53
    }
54
  in1 = bfd_getb32 (buffer);
55
 
56
  status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
57
  if (status != 0)
58
    {
59
      info->bytes_per_line = 8;
60
      if (!(result = lookup_opcode (&insn, in1, 0)))
61
        (*info->fprintf_func) (info->stream, ".long\t0x%x", in1);
62
      else
63
        print_insn (info, memaddr, (long long) in1, &insn, 0, result);
64
      return 4;
65
    }
66
  in2 = bfd_getb32 (buffer);
67
 
68
  if (in1 & in2 & FM01)
69
    {
70
      /* LONG instruction.  */
71
      if (!(result = lookup_opcode (&insn, in1, 1)))
72
        {
73
          (*info->fprintf_func) (info->stream, ".long\t0x%x,0x%x", in1, in2);
74
          return 8;
75
        }
76
      num = (long long) in1 << 32 | in2;
77
      print_insn (info, memaddr, num, &insn, 1, result);
78
    }
79
  else
80
    {
81
      num = in1;
82
      if (!(result = lookup_opcode (&insn, in1, 0)))
83
        (*info->fprintf_func) (info->stream, ".long\t0x%x", in1);
84
      else
85
        print_insn (info, memaddr, num, &insn, 0, result);
86
 
87
      switch (((in1 >> 31) << 1) | (in2 >> 31))
88
        {
89
        case 0:
90
          (*info->fprintf_func) (info->stream, "\t||\t");
91
          break;
92
        case 1:
93
          (*info->fprintf_func) (info->stream, "\t->\t");
94
          break;
95
        case 2:
96
          (*info->fprintf_func) (info->stream, "\t<-\t");
97
        default:
98
          break;
99
        }
100
 
101
      insn.form = (struct d30v_format *) NULL;
102
      num = in2;
103
      if (!(result = lookup_opcode (&insn, in2, 0)))
104
        (*info->fprintf_func) (info->stream, ".long\t0x%x", in2);
105
      else
106
        print_insn (info, memaddr, num, &insn, 0, result);
107
    }
108
  return 8;
109
}
110
 
111
/* Return 0 if lookup fails,
112
   1 if found and only one form,
113
   2 if found and there are short and long forms.  */
114
 
115
static int
116
lookup_opcode (insn, num, is_long)
117
     struct d30v_insn *insn;
118
     long num;
119
     int is_long;
120
{
121
  int i = 0, index;
122
  struct d30v_format *f;
123
  struct d30v_opcode *op = (struct d30v_opcode *) d30v_opcode_table;
124
  int op1 = (num >> 25) & 0x7;
125
  int op2 = (num >> 20) & 0x1f;
126
  int mod = (num >> 18) & 0x3;
127
 
128
  /* Find the opcode.  */
129
  do
130
    {
131
      if ((op->op1 == op1) && (op->op2 == op2))
132
        break;
133
      op++;
134
    }
135
  while (op->name);
136
 
137
  if (!op || !op->name)
138
    return 0;
139
 
140
  while (op->op1 == op1 && op->op2 == op2)
141
    {
142
      /* Scan through all the formats for the opcode.  */
143
      index = op->format[i++];
144
      do
145
        {
146
          f = (struct d30v_format *) &d30v_format_table[index];
147
          while (f->form == index)
148
            {
149
              if ((!is_long || f->form >= LONG) && (f->modifier == mod))
150
                {
151
                  insn->form = f;
152
                  break;
153
                }
154
              f++;
155
            }
156
          if (insn->form)
157
            break;
158
        }
159
      while ((index = op->format[i++]) != 0);
160
      if (insn->form)
161
        break;
162
      op++;
163
      i = 0;
164
    }
165
  if (insn->form == NULL)
166
    return 0;
167
 
168
  insn->op = op;
169
  insn->ecc = (num >> 28) & 0x7;
170
  if (op->format[1])
171
    return 2;
172
  else
173
    return 1;
174
}
175
 
176
static void
177
print_insn (info, memaddr, num, insn, is_long, show_ext)
178
     struct disassemble_info *info;
179
     bfd_vma memaddr;
180
     long long num;
181
     struct d30v_insn *insn;
182
     int is_long;
183
     int show_ext;
184
{
185
  int val, opnum, need_comma = 0;
186
  struct d30v_operand *oper;
187
  int i, match, opind = 0, need_paren = 0, found_control = 0;
188
 
189
  (*info->fprintf_func) (info->stream, "%s", insn->op->name);
190
 
191
  /* Check for CMP or CMPU.  */
192
  if (d30v_operand_table[insn->form->operands[0]].flags & OPERAND_NAME)
193
    {
194
      opind++;
195
      val =
196
        extract_value (num,
197
                       (struct d30v_operand *) &d30v_operand_table[insn->form->operands[0]],
198
                       is_long);
199
      (*info->fprintf_func) (info->stream, "%s", d30v_cc_names[val]);
200
    }
201
 
202
  /* Add in ".s" or ".l".  */
203
  if (show_ext == 2)
204
    {
205
      if (is_long)
206
        (*info->fprintf_func) (info->stream, ".l");
207
      else
208
        (*info->fprintf_func) (info->stream, ".s");
209
    }
210
 
211
  if (insn->ecc)
212
    (*info->fprintf_func) (info->stream, "/%s", d30v_ecc_names[insn->ecc]);
213
 
214
  (*info->fprintf_func) (info->stream, "\t");
215
 
216
  while ((opnum = insn->form->operands[opind++]) != 0)
217
    {
218
      int bits;
219
      oper = (struct d30v_operand *) &d30v_operand_table[opnum];
220
      bits = oper->bits;
221
      if (oper->flags & OPERAND_SHIFT)
222
        bits += 3;
223
 
224
      if (need_comma
225
          && oper->flags != OPERAND_PLUS
226
          && oper->flags != OPERAND_MINUS)
227
        {
228
          need_comma = 0;
229
          (*info->fprintf_func) (info->stream, ", ");
230
        }
231
 
232
      if (oper->flags == OPERAND_ATMINUS)
233
        {
234
          (*info->fprintf_func) (info->stream, "@-");
235
          continue;
236
        }
237
      if (oper->flags == OPERAND_MINUS)
238
        {
239
          (*info->fprintf_func) (info->stream, "-");
240
          continue;
241
        }
242
      if (oper->flags == OPERAND_PLUS)
243
        {
244
          (*info->fprintf_func) (info->stream, "+");
245
          continue;
246
        }
247
      if (oper->flags == OPERAND_ATSIGN)
248
        {
249
          (*info->fprintf_func) (info->stream, "@");
250
          continue;
251
        }
252
      if (oper->flags == OPERAND_ATPAR)
253
        {
254
          (*info->fprintf_func) (info->stream, "@(");
255
          need_paren = 1;
256
          continue;
257
        }
258
 
259
      if (oper->flags == OPERAND_SPECIAL)
260
        continue;
261
 
262
      val = extract_value (num, oper, is_long);
263
 
264
      if (oper->flags & OPERAND_REG)
265
        {
266
          match = 0;
267
          if (oper->flags & OPERAND_CONTROL)
268
            {
269
              struct d30v_operand *oper3 =
270
                (struct d30v_operand *) &d30v_operand_table[insn->form->operands[2]];
271
              int id = extract_value (num, oper3, is_long);
272
              found_control = 1;
273
              switch (id)
274
                {
275
                case 0:
276
                  val |= OPERAND_CONTROL;
277
                  break;
278
                case 1:
279
                case 2:
280
                  val = OPERAND_CONTROL + MAX_CONTROL_REG + id;
281
                  break;
282
                case 3:
283
                  val |= OPERAND_FLAG;
284
                  break;
285
                default:
286
                  fprintf (stderr, "illegal id (%d)\n", id);
287
                }
288
            }
289
          else if (oper->flags & OPERAND_ACC)
290
            val |= OPERAND_ACC;
291
          else if (oper->flags & OPERAND_FLAG)
292
            val |= OPERAND_FLAG;
293
          for (i = 0; i < reg_name_cnt (); i++)
294
            {
295
              if (val == pre_defined_registers[i].value)
296
                {
297
                  if (pre_defined_registers[i].pname)
298
                    (*info->fprintf_func)
299
                      (info->stream, "%s", pre_defined_registers[i].pname);
300
                  else
301
                    (*info->fprintf_func)
302
                      (info->stream, "%s", pre_defined_registers[i].name);
303
                  match = 1;
304
                  break;
305
                }
306
            }
307
          if (match == 0)
308
            {
309
              /* This would only get executed if a register was not in
310
                 the register table.  */
311
              (*info->fprintf_func)
312
                (info->stream, _("<unknown register %d>"), val & 0x3F);
313
            }
314
        }
315
      /* repeati has a relocation, but its first argument is a plain
316
         immediate.  OTOH instructions like djsri have a pc-relative
317
         delay target, but an absolute jump target.  Therefore, a test
318
         of insn->op->reloc_flag is not specific enough; we must test
319
         if the actual operand we are handling now is pc-relative.  */
320
      else if (oper->flags & OPERAND_PCREL)
321
        {
322
          int neg = 0;
323
 
324
          /* IMM6S3 is unsigned.  */
325
          if (oper->flags & OPERAND_SIGNED || bits == 32)
326
            {
327
              long max;
328
              max = (1 << (bits - 1));
329
              if (val & max)
330
                {
331
                  if (bits == 32)
332
                    val = -val;
333
                  else
334
                    val = -val & ((1 << bits) - 1);
335
                  neg = 1;
336
                }
337
            }
338
          if (neg)
339
            {
340
              (*info->fprintf_func) (info->stream, "-%x\t(", val);
341
              (*info->print_address_func) ((memaddr - val) & PC_MASK, info);
342
              (*info->fprintf_func) (info->stream, ")");
343
            }
344
          else
345
            {
346
              (*info->fprintf_func) (info->stream, "%x\t(", val);
347
              (*info->print_address_func) ((memaddr + val) & PC_MASK, info);
348
              (*info->fprintf_func) (info->stream, ")");
349
            }
350
        }
351
      else if (insn->op->reloc_flag == RELOC_ABS)
352
        {
353
          (*info->print_address_func) (val, info);
354
        }
355
      else
356
        {
357
          if (oper->flags & OPERAND_SIGNED)
358
            {
359
              int max = (1 << (bits - 1));
360
              if (val & max)
361
                {
362
                  val = -val;
363
                  if (bits < 32)
364
                    val &= ((1 << bits) - 1);
365
                  (*info->fprintf_func) (info->stream, "-");
366
                }
367
            }
368
          (*info->fprintf_func) (info->stream, "0x%x", val);
369
        }
370
      /* If there is another operand, then write a comma and space.  */
371
      if (insn->form->operands[opind] && !(found_control && opind == 2))
372
        need_comma = 1;
373
    }
374
  if (need_paren)
375
    (*info->fprintf_func) (info->stream, ")");
376
}
377
 
378
static int
379
extract_value (num, oper, is_long)
380
     long long num;
381
     struct d30v_operand *oper;
382
     int is_long;
383
{
384
  int val;
385
  int shift = 12 - oper->position;
386
  int mask = (0xFFFFFFFF >> (32 - oper->bits));
387
 
388
  if (is_long)
389
    {
390
      if (oper->bits == 32)
391
        {
392
          /* Piece together 32-bit constant.  */
393
          val = ((num & 0x3FFFF)
394
                 | ((num & 0xFF00000) >> 2)
395
                 | ((num & 0x3F00000000LL) >> 6));
396
        }
397
      else
398
        val = (num >> (32 + shift)) & mask;
399
    }
400
  else
401
    val = (num >> shift) & mask;
402
 
403
  if (oper->flags & OPERAND_SHIFT)
404
    val <<= 3;
405
 
406
  return val;
407
}

powered by: WebSVN 2.1.0

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