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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [opcodes/] [d30v-dis.c] - Blame information for rev 1765

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

Line No. Rev Author Line
1 578 markom
/* Disassemble D30V instructions.
2
   Copyright 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 "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
    }
109
  return 8;
110
}
111
 
112
 
113
/* returns 0 if lookup fails */
114
/* 1 if found and only one form */
115
/* 2 if found and there are short and long forms */
116
static int
117
lookup_opcode (insn, num, is_long)
118
     struct d30v_insn *insn;
119
     long num;
120
     int is_long;
121
{
122
  int i=0, index;
123
  struct d30v_format *f;
124
  struct d30v_opcode *op = (struct d30v_opcode *)d30v_opcode_table;
125
  int op1 = (num >> 25) & 0x7;
126
  int op2 = (num >> 20) & 0x1f;
127
  int mod = (num >> 18) & 0x3;
128
 
129
  /* find the opcode */
130
  do {
131
    if ((op->op1 == op1) && (op->op2 == op2))
132
      break;
133
    op++;
134
  } while (op->name);
135
 
136
  if (!op || !op->name)
137
    return 0;
138
 
139
  while (op->op1 == op1 && op->op2 == op2)
140
    {
141
      /* scan through all the formats for the opcode  */
142
      index = op->format[i++];
143
      do
144
        {
145
          f = (struct d30v_format *)&d30v_format_table[index];
146
          while (f->form == index)
147
            {
148
              if ((!is_long || f->form >= LONG) && (f->modifier == mod))
149
                {
150
                  insn->form = f;
151
                  break;
152
                }
153
              f++;
154
            }
155
          if (insn->form)
156
            break;
157
        } while ((index = op->format[i++]) != 0);
158
      if (insn->form)
159
        break;
160
      op++;
161
      i=0;
162
    }
163
  if (insn->form == NULL)
164
    return 0;
165
 
166
  insn->op = op;
167
  insn->ecc = (num >> 28) & 0x7;
168
  if (op->format[1])
169
    return 2;
170
  else
171
    return 1;
172
}
173
 
174
 
175
static void
176
print_insn ( info, memaddr, num, insn, is_long, show_ext )
177
     struct disassemble_info *info;
178
     bfd_vma memaddr;
179
     long long num;
180
     struct d30v_insn *insn;
181
     int is_long;
182
     int show_ext;
183
{
184
  int val, opnum, need_comma=0;
185
  struct d30v_operand *oper;
186
  int i, match, opind=0, need_paren=0, found_control=0;
187
 
188
  (*info->fprintf_func) (info->stream, "%s",insn->op->name);
189
 
190
  /* check for CMP or CMPU */
191
  if (d30v_operand_table[insn->form->operands[0]].flags & OPERAND_NAME)
192
    {
193
      opind++;
194
      val = extract_value(num,(struct d30v_operand *)&d30v_operand_table[insn->form->operands[0]],is_long);
195
      (*info->fprintf_func) (info->stream, "%s",d30v_cc_names[val]);
196
    }
197
 
198
  /* add in ".s" or ".l" */
199
  if (show_ext == 2)
200
    {
201
      if (is_long)
202
        (*info->fprintf_func) (info->stream, ".l");
203
      else
204
        (*info->fprintf_func) (info->stream, ".s");
205
    }
206
 
207
  if (insn->ecc)
208
    (*info->fprintf_func) (info->stream, "/%s",d30v_ecc_names[insn->ecc]);
209
 
210
  (*info->fprintf_func) (info->stream, "\t");
211
 
212
  while ((opnum = insn->form->operands[opind++]) != 0)
213
    {
214
      int bits;
215
      oper = (struct d30v_operand *)&d30v_operand_table[opnum];
216
      bits = oper->bits;
217
      if (oper->flags & OPERAND_SHIFT)
218
        bits += 3;
219
 
220
      if (need_comma && oper->flags != OPERAND_PLUS && oper->flags != OPERAND_MINUS)
221
        {
222
          need_comma=0;
223
          (*info->fprintf_func) (info->stream, ", ");
224
        }
225
 
226
      if (oper->flags == OPERAND_ATMINUS)
227
        {
228
          (*info->fprintf_func) (info->stream, "@-");
229
          continue;
230
        }
231
      if (oper->flags == OPERAND_MINUS)
232
        {
233
          (*info->fprintf_func) (info->stream, "-");
234
          continue;
235
        }
236
      if (oper->flags == OPERAND_PLUS)
237
        {
238
          (*info->fprintf_func) (info->stream, "+");
239
          continue;
240
        }
241
      if (oper->flags == OPERAND_ATSIGN)
242
        {
243
          (*info->fprintf_func) (info->stream, "@");
244
          continue;
245
        }
246
      if (oper->flags == OPERAND_ATPAR)
247
        {
248
          (*info->fprintf_func) (info->stream, "@(");
249
          need_paren = 1;
250
          continue;
251
        }
252
 
253
      if (oper->flags == OPERAND_SPECIAL)
254
        continue;
255
 
256
      val = extract_value(num, oper, is_long);
257
 
258
      if (oper->flags & OPERAND_REG)
259
        {
260
          match = 0;
261
          if (oper->flags & OPERAND_CONTROL)
262
            {
263
              struct d30v_operand *oper3 =
264
                (struct d30v_operand *)&d30v_operand_table[insn->form->operands[2]];
265
              int id = extract_value (num, oper3, is_long );
266
              found_control = 1;
267
              switch ( id )
268
                {
269
                case 0:
270
                  val |= OPERAND_CONTROL;
271
                  break;
272
                case 1:
273
                case 2:
274
                  val = OPERAND_CONTROL + MAX_CONTROL_REG + id;
275
                  break;
276
                case 3:
277
                  val |= OPERAND_FLAG;
278
                  break;
279
                default:
280
                  fprintf(stderr,"illegal id (%d)\n",id);
281
                }
282
            }
283
          else if (oper->flags & OPERAND_ACC)
284
            val |= OPERAND_ACC;
285
          else if (oper->flags & OPERAND_FLAG)
286
            val |= OPERAND_FLAG;
287
          for (i=0;i<reg_name_cnt();i++)
288
            {
289
              if (val == pre_defined_registers[i].value)
290
                {
291
                  if (pre_defined_registers[i].pname)
292
                    (*info->fprintf_func)
293
                      (info->stream, "%s",pre_defined_registers[i].pname);
294
                  else
295
                    (*info->fprintf_func)
296
                      (info->stream, "%s",pre_defined_registers[i].name);
297
                  match=1;
298
                  break;
299
                }
300
            }
301
          if (match==0)
302
            {
303
              /* this would only get executed if a register was not in the
304
                 register table */
305
              (*info->fprintf_func)
306
                (info->stream, _("<unknown register %d>"), val & 0x3F);
307
            }
308
        }
309
      /* repeati has a relocation, but its first argument is a plain
310
         immediate.  OTOH instructions like djsri have a pc-relative
311
         delay target, but a absolute jump target.  Therefore, a test
312
         of insn->op->reloc_flag is not specific enough; we must test
313
         if the actual operand we are handling now is pc-relative.  */
314
      else if (oper->flags & OPERAND_PCREL)
315
        {
316
          int neg = 0;
317
 
318
          /* IMM6S3 is unsigned.  */
319
          if (oper->flags & OPERAND_SIGNED || bits == 32)
320
            {
321
              long max;
322
              max = (1 << (bits - 1));
323
              if (val & max)
324
                {
325
                  if (bits == 32)
326
                    val = -val;
327
                  else
328
                    val = -val & ((1 << bits)-1);
329
                  neg = 1;
330
                }
331
            }
332
          if (neg)
333
            {
334
              (*info->fprintf_func) (info->stream, "-%x\t(",val);
335
              (*info->print_address_func) ((memaddr - val) & PC_MASK, info);
336
              (*info->fprintf_func) (info->stream, ")");
337
            }
338
          else
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
        }
345
      else if (insn->op->reloc_flag == RELOC_ABS)
346
        {
347
          (*info->print_address_func) (val, info);
348
        }
349
      else
350
        {
351
          if (oper->flags & OPERAND_SIGNED)
352
            {
353
              int max = (1 << (bits - 1));
354
              if (val & max)
355
                {
356
                  val = -val;
357
                  if (bits < 32)
358
                    val &= ((1 << bits) - 1);
359
                  (*info->fprintf_func) (info->stream, "-");
360
                }
361
            }
362
          (*info->fprintf_func) (info->stream, "0x%x",val);
363
        }
364
      /* if there is another operand, then write a comma and space */
365
      if (insn->form->operands[opind] && !(found_control && opind == 2))
366
        need_comma = 1;
367
    }
368
  if (need_paren)
369
    (*info->fprintf_func) (info->stream, ")");
370
}
371
 
372
 
373
 
374
static int
375
extract_value (num, oper, is_long)
376
     long long num;
377
     struct d30v_operand *oper;
378
     int is_long;
379
{
380
  int val;
381
  int shift = 12 - oper->position;
382
  int mask = (0xFFFFFFFF >> (32 - oper->bits));
383
 
384
  if (is_long)
385
    {
386
      if (oper->bits == 32)
387
        {
388
          /* piece together 32-bit constant */
389
          val = ((num & 0x3FFFF)
390
                 | ((num & 0xFF00000) >> 2)
391
                 | ((num & 0x3F00000000LL) >> 6));
392
        }
393
      else
394
        val = (num >> (32 + shift)) & mask;
395
    }
396
  else
397
    val = (num >> shift) & mask;
398
 
399
  if (oper->flags & OPERAND_SHIFT)
400
    val <<= 3;
401
 
402
  return val;
403
}

powered by: WebSVN 2.1.0

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