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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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