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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 24 jeremybenn
/* Instruction printing code for the OpenRISC 1000
2
 
3
   Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributed by Damjan Lampret <lampret@opencores.org>.
7
   Modified from a29k port.
8
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
9
 
10
   This file is part of the GNU opcodes library.
11
 
12
   This program is free software; you can redistribute it and/or modify it
13
   under the terms of the GNU General Public License as published by the Free
14
   Software Foundation; either version 3 of the License, or (at your option)
15
   any later version.
16
 
17
   This program is distributed in the hope that it will be useful, but WITHOUT
18
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
20
   more details.
21
 
22
   You should have received a copy of the GNU General Public License along
23
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
24
 
25
/*-----------------------------------------------------------------------------
26
   This version for the OpenRISC 1000 architecture is an update by Jeremy
27
   Bennett for GDB 6.8. All code converted to ANSI C style and in general to
28
   GDB format.
29
 
30
   Signed immediate constants are printed as such (the old version printed
31
   them as unsigned hex). Where appropriate symbolic names are used for
32
   immediate branch and jump targets.
33
   --------------------------------------------------------------------------*/
34
 
35
 
36
#include "dis-asm.h"
37
#include "opcode/or32.h"
38
#include "safe-ctype.h"
39
#include <string.h>
40
#include <stdlib.h>
41
 
42
 
43
#define EXTEND29(x) ((x) & (unsigned long) 0x10000000 ? ((x) | (unsigned long) 0xf0000000) : ((x)))
44
 
45
/* A cop out - this is in defs.h, but including that from the main GDB
46
   component would be a pain. Really the dependency on CORE_ADDR ought to be
47
   added to the or1k-tdep.c, rather than being here. Something for the
48
   future. */
49
typedef bfd_vma CORE_ADDR;
50
 
51
 
52
/* Function to look up an address as a symbol. Found in the GDB area */
53
extern int
54
build_address_symbolic (CORE_ADDR   addr,
55
                        int         do_demangle,
56
                        char      **name,
57
                        int        *offset,
58
                        char      **filename,
59
                        int        *line,
60
                        int        *unmapped);
61
 
62
 
63
/*!----------------------------------------------------------------------------
64
   Map 4 bytes of instruction into one 32-bit word for big-endian target
65
 
66
   @param[in]  insn_ch  The 4 bytes of the instruction
67
   @param[out] insn     The 32-bit word
68
   --------------------------------------------------------------------------*/
69
 
70
static void
71
find_bytes_big (unsigned char *insn_ch,
72
                unsigned long *insn)
73
{
74
  *insn =
75
    ((unsigned long) insn_ch[0] << 24) +
76
    ((unsigned long) insn_ch[1] << 16) +
77
    ((unsigned long) insn_ch[2] << 8) +
78
    ((unsigned long) insn_ch[3]);
79
 
80
}       /* find_bytes_big() */
81
 
82
 
83
/*!----------------------------------------------------------------------------
84
   Map 4 bytes of instruction into one 32-bit word for little-endian target
85
 
86
   @param[in]  insn_ch  The 4 bytes of the instruction
87
   @param[out] insn     The 32-bit word
88
   --------------------------------------------------------------------------*/
89
 
90
static void
91
find_bytes_little (unsigned char *insn_ch,
92
                   unsigned long *insn)
93
{
94
  *insn =
95
    ((unsigned long) insn_ch[3] << 24) +
96
    ((unsigned long) insn_ch[2] << 16) +
97
    ((unsigned long) insn_ch[1] << 8) +
98
    ((unsigned long) insn_ch[0]);
99
 
100
}       /* find_bytes_little() */
101
 
102
 
103
/*!----------------------------------------------------------------------------
104
   Extract an instruction field
105
 
106
   @param[in] param_ch     The character identifying the field
107
   @param[in] enc_initial  A string with 1 char for each bit in the
108
                           instruction, the char indicating the field the bit
109
                           belongs to
110
   @param[in] insn         The instruction
111
 
112
   @return  The value of the field
113
   --------------------------------------------------------------------------*/
114
 
115
static unsigned long
116
or32_extract (char               param_ch,
117
              char              *enc_initial,
118
              unsigned long int  insn)
119
{
120
  char              *enc;
121
  unsigned long int  ret       = 0;
122
  int                opc_pos   = 0;
123
  int                param_pos = 0;
124
 
125
  for (enc = enc_initial; *enc != '\0'; enc++)
126
    {
127
      if (*enc == param_ch)
128
        {
129
          if ((enc - 2    >= enc_initial) &&
130
              (*(enc - 2) == '0')         &&
131
              (*(enc - 1) == 'x'))
132
            {
133
              continue;
134
            }
135
          else
136
            {
137
              param_pos++;
138
            }
139
        }
140
    }
141
 
142
  opc_pos = 32;
143
 
144
  for (enc = enc_initial; *enc != '\0'; )
145
    {
146
      if ((*enc == '0') && (*(enc + 1) == 'x'))
147
        {
148
          opc_pos -= 4;
149
 
150
          if ((param_ch == '0') || (param_ch == '1'))
151
            {
152
              unsigned long tmp = strtoul (enc, NULL, 16);
153
 
154
              if (param_ch == '0') {
155
                tmp = 15 - tmp;
156
              }
157
 
158
              ret |= tmp << opc_pos;
159
            }
160
 
161
          enc += 3;
162
        }
163
      else if ((*enc == '0') || (*enc == '1'))
164
        {
165
          opc_pos--;
166
 
167
          if (param_ch == *enc) {
168
            ret |= 1 << opc_pos;
169
          }
170
 
171
          enc++;
172
        }
173
      else if (*enc == param_ch)
174
        {
175
          opc_pos--;
176
          param_pos--;
177
          ret += ((insn >> opc_pos) & 0x1) << param_pos;
178
 
179
          if (!param_pos               &&
180
              letter_signed (param_ch) &&
181
              ret >> (letter_range (param_ch) - 1))
182
            {
183
              ret |= 0xffffffff << letter_range(param_ch);
184
            }
185
          enc++;
186
        }
187
      else if (ISALPHA (*enc))
188
        {
189
          opc_pos--;
190
          enc++;
191
        }
192
      else if (*enc == '-')
193
        {
194
          opc_pos--;
195
          enc++;
196
        }
197
      else
198
        {
199
          enc++;
200
        }
201
    }
202
 
203
  return ret;
204
 
205
}       /* or32_extract() */
206
 
207
 
208
/*!----------------------------------------------------------------------------
209
   Test if an instruction matches an encoding
210
 
211
   @param[in] insn      The instruction
212
   @param[in] encoding  The encoding
213
 
214
   @return  1 (true) if they match, 0 otherwise
215
   --------------------------------------------------------------------------*/
216
 
217
static int
218
or32_opcode_match (unsigned long insn, char *encoding)
219
{
220
  unsigned long ones, zeros;
221
 
222
  ones  = or32_extract ('1', encoding, insn);
223
  zeros = or32_extract ('0', encoding, insn);
224
 
225
  if ((insn & ones) != ones)
226
    {
227
      return 0;
228
    }
229
 
230
  if ((~insn & zeros) != zeros)
231
    {
232
      return 0;
233
    }
234
 
235
  return 1;
236
 
237
}       /* or32_opcode_match() */
238
 
239
 
240
/*!----------------------------------------------------------------------------
241
   Print register to INFO->STREAM.
242
 
243
   Used only by print_insn.
244
 
245
   @param[in] param_ch  The character encoding the field of interest
246
   @param[in] encoding  The encoding
247
   @param[in] insn      The instruction
248
   @param[in] info      Info about the disassembly, in particular with the
249
                        stream to write to.
250
   --------------------------------------------------------------------------*/
251
 
252
static void
253
or32_print_register (char param_ch,
254
                     char *encoding,
255
                     unsigned long insn,
256
                     struct disassemble_info *info)
257
{
258
  int regnum = or32_extract (param_ch, encoding, insn);
259
 
260
  switch (param_ch)
261
    {
262
    case 'A':
263
    case 'B':
264
    case 'D':
265
      (*info->fprintf_func) (info->stream, "r%d", regnum);
266
      break;
267
 
268
    default:
269
      if (regnum < 16)
270
        {
271
          (*info->fprintf_func) (info->stream, "r%d", regnum);
272
        }
273
      else if (regnum < 32)
274
        {
275
          (*info->fprintf_func) (info->stream, "r%d", regnum-16);
276
        }
277
      else
278
        {
279
          (*info->fprintf_func) (info->stream, "X%d", regnum);
280
        }
281
    }
282
}       /* or32_print_register() */
283
 
284
 
285
 
286
/*!----------------------------------------------------------------------------
287
   Print immediate to INFO->STREAM.
288
 
289
   Used only by print_insn.
290
 
291
   Fixed in GDB 6.8 to print signed immediate fields correctly and to set the
292
   target fields of jump and branch to symbols if possible.
293
 
294
   @param[in] memaddr   Address of this instruction
295
   @param[in] param_ch  The character encoding the field of interest
296
   @param[in] encoding  The encoding
297
   @param[in] insn      The instruction
298
   @param[in] info      Info about the disassembly, in particular with the
299
                        stream to write to.
300
   --------------------------------------------------------------------------*/
301
 
302
/* Print immediate to INFO->STREAM. Used only by print_insn.  */
303
 
304
static void
305
or32_print_immediate( bfd_vma                  memaddr,
306
                      char                     param_ch,
307
                      char                    *encoding,
308
                      unsigned long            insn,
309
                      struct disassemble_info *info)
310
{
311
  int imm = or32_extract(param_ch, encoding, insn);
312
 
313
  if ('N' == param_ch)
314
    {
315
      CORE_ADDR  target_addr = (CORE_ADDR)(memaddr + (4 * imm));
316
      char      *name        = NULL;
317
      char      *filename    = NULL;
318
      int        unmapped    = 0;
319
      int        offset      = 0;
320
      int        line        = 0;
321
 
322
      if( 0 == build_address_symbolic( target_addr, 1, &name, &offset,
323
                                       &filename, &line, &unmapped ))
324
        {
325
          (*info->fprintf_func) (info->stream, "<" );
326
 
327
          if( unmapped )
328
            {
329
              (*info->fprintf_func) (info->stream, "*");
330
            }
331
 
332
          (*info->fprintf_func) (info->stream, "%s", name);
333
 
334
          if( offset )
335
            {
336
              (*info->fprintf_func) (info->stream, "+%d", offset);
337
            }
338
 
339
          (*info->fprintf_func) (info->stream, ">" );
340
        }
341
      else
342
        {
343
          (*info->fprintf_func) (info->stream, "0x%x", imm);
344
        }
345
    }
346
  else if (letter_signed(param_ch))
347
    {
348
      (*info->fprintf_func) (info->stream, "%d", imm);
349
    }
350
  else
351
    {
352
      (*info->fprintf_func) (info->stream, "0x%x", imm);
353
    }
354
}       /* or32_print_immediate() */
355
 
356
 
357
/*!----------------------------------------------------------------------------
358
   Print one instruction
359
 
360
   Print one instruction from MEMADDR on INFO->STREAM.
361
 
362
   @param[in] memaddr   Address of the instruction to print
363
   @param[in] info      Info about the disassembly, in particular with the
364
                        stream to write to.
365
 
366
   @return   The size of the instruction (always 4 on or32).
367
   --------------------------------------------------------------------------*/
368
 
369
static int
370
print_insn (bfd_vma                  memaddr,
371
            struct disassemble_info *info)
372
{
373
  /* The raw instruction.  */
374
  unsigned char insn_ch[4];
375
  /* Address. Will be sign extened 27-bit.  */
376
  unsigned long addr;
377
  /* The four bytes of the instruction.  */
378
  unsigned long insn;
379
 
380
  typedef void (*find_byte_func_type) (unsigned char *, unsigned long *);
381
 
382
  find_byte_func_type find_byte_func = (find_byte_func_type) info->private_data;
383
  struct or32_opcode const *opcode;
384
 
385
  int status =
386
    (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
387
 
388
  if (status != 0)
389
    {
390
      (*info->memory_error_func) (status, memaddr, info);
391
      return -1;
392
    }
393
 
394
  (*find_byte_func) (&insn_ch[0], &insn);
395
 
396
  for (opcode = &or32_opcodes[0];
397
       opcode < &or32_opcodes[or32_num_opcodes];
398
       ++opcode)
399
    {
400
      if (or32_opcode_match (insn, opcode->encoding))
401
        {
402
          char *s;
403
 
404
          (*info->fprintf_func) (info->stream, "%-8s ", opcode->name);
405
 
406
          for (s = opcode->args; *s != '\0'; ++s)
407
            {
408
              switch (*s)
409
                {
410
                case '\0':
411
                  return 4;
412
 
413
                case 'r':
414
                  or32_print_register (*++s, opcode->encoding, insn, info);
415
                  break;
416
 
417
                case 'X':
418
                  addr = or32_extract ('X', opcode->encoding, insn) << 2;
419
 
420
                  /* Calulate the correct address.  XXX is this really correct
421
                     ??  */
422
                  addr = memaddr + EXTEND29 (addr);
423
 
424
                  (*info->print_address_func)
425
                    (addr, info);
426
                  break;
427
 
428
                default:
429
                  if (strchr (opcode->encoding, *s))
430
                    {
431
                      or32_print_immediate (memaddr, *s, opcode->encoding,
432
                                            insn, info);
433
                    }
434
                  else
435
                    {
436
                      (*info->fprintf_func) (info->stream, "%c", *s);
437
                    }
438
                }
439
            }
440
 
441
          return 4;
442
        }
443
    }
444
 
445
  /* This used to be %8x for binutils.  */
446
  (*info->fprintf_func) (info->stream, ".word 0x%08lx", insn);
447
  return 4;
448
 
449
}       /* print_insn() */
450
 
451
 
452
/*!----------------------------------------------------------------------------
453
   Disassemble a big-endian or32 instruction
454
 
455
   Print one instruction from MEMADDR on INFO->STREAM.
456
 
457
   @param[in] memaddr   Address of the instruction to print
458
   @param[in] info      Info about the disassembly, in particular with the
459
                        stream to write to.
460
 
461
   @return   The size of the instruction (always 4 on or32).
462
   --------------------------------------------------------------------------*/
463
 
464
int
465
print_insn_big_or32 (bfd_vma                  memaddr,
466
                     struct disassemble_info *info)
467
{
468
  info->private_data = find_bytes_big;
469
 
470
  return print_insn (memaddr, info);
471
 
472
}       /* print_insn_big_or32() */
473
 
474
 
475
/*!----------------------------------------------------------------------------
476
   Disassemble a little-endian or32 instruction
477
 
478
   Print one instruction from MEMADDR on INFO->STREAM.
479
 
480
   @param[in] memaddr   Address of the instruction to print
481
   @param[in] info      Info about the disassembly, in particular with the
482
                        stream to write to.
483
 
484
   @return   The size of the instruction (always 4 on or32).
485
   --------------------------------------------------------------------------*/
486
 
487
int
488
print_insn_little_or32 (bfd_vma                  memaddr,
489
                        struct disassemble_info *info)
490
{
491
  info->private_data = find_bytes_little;
492
 
493
  return print_insn (memaddr, info);
494
 
495
}       /* print_insn_little_or32() */

powered by: WebSVN 2.1.0

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