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 298

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
   Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
3
   Contributed by Damjan Lampret <lampret@opencores.org>.
4
   Modified from a29k port.
5
 
6
   This file is part of the GNU opcodes library.
7
 
8 225 jeremybenn
   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 24 jeremybenn
   any later version.
12
 
13 225 jeremybenn
   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 24 jeremybenn
 
18 225 jeremybenn
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22 24 jeremybenn
 
23 225 jeremybenn
#define DEBUG 0
24 24 jeremybenn
 
25
#include "dis-asm.h"
26
#include "opcode/or32.h"
27
#include "safe-ctype.h"
28
#include <string.h>
29
#include <stdlib.h>
30
 
31 225 jeremybenn
#define EXTEND28(x) ((x) & (unsigned long) 0x08000000 ? ((x) | (unsigned long) 0xf0000000) : ((x)))
32 24 jeremybenn
 
33 225 jeremybenn
/* Now find the four bytes of INSN_CH and put them in *INSN.  */
34 24 jeremybenn
 
35
static void
36 225 jeremybenn
find_bytes_big (unsigned char *insn_ch, unsigned long *insn)
37 24 jeremybenn
{
38
  *insn =
39
    ((unsigned long) insn_ch[0] << 24) +
40
    ((unsigned long) insn_ch[1] << 16) +
41
    ((unsigned long) insn_ch[2] << 8) +
42
    ((unsigned long) insn_ch[3]);
43 225 jeremybenn
#if DEBUG
44
  printf ("find_bytes_big3: %x\n", *insn);
45
#endif
46
}
47 24 jeremybenn
 
48
static void
49 225 jeremybenn
find_bytes_little (unsigned char *insn_ch, unsigned long *insn)
50 24 jeremybenn
{
51
  *insn =
52
    ((unsigned long) insn_ch[3] << 24) +
53
    ((unsigned long) insn_ch[2] << 16) +
54
    ((unsigned long) insn_ch[1] << 8) +
55
    ((unsigned long) insn_ch[0]);
56 225 jeremybenn
}
57 24 jeremybenn
 
58 225 jeremybenn
typedef void (*find_byte_func_type) (unsigned char *, unsigned long *);
59 24 jeremybenn
 
60
static unsigned long
61 225 jeremybenn
or32_extract (char param_ch, char *enc_initial, unsigned long insn)
62 24 jeremybenn
{
63 225 jeremybenn
  char *enc;
64
  unsigned long ret = 0;
65
  int opc_pos = 0;
66
  int param_pos = 0;
67 24 jeremybenn
 
68
  for (enc = enc_initial; *enc != '\0'; enc++)
69 225 jeremybenn
    if (*enc == param_ch)
70
      {
71
        if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
72
          continue;
73
        else
74
          param_pos++;
75
      }
76 24 jeremybenn
 
77 225 jeremybenn
#if DEBUG
78
  printf ("or32_extract: %c %x ", param_ch, param_pos);
79
#endif
80 24 jeremybenn
  opc_pos = 32;
81
 
82
  for (enc = enc_initial; *enc != '\0'; )
83 225 jeremybenn
    if ((*enc == '0') && (*(enc + 1) == 'x'))
84
      {
85
        opc_pos -= 4;
86 24 jeremybenn
 
87 225 jeremybenn
        if ((param_ch == '0') || (param_ch == '1'))
88
          {
89
            unsigned long tmp = strtoul (enc, NULL, 16);
90
#if DEBUG
91
            printf (" enc=%s, tmp=%x ", enc, tmp);
92
#endif
93
            if (param_ch == '0')
94
              tmp = 15 - tmp;
95
            ret |= tmp << opc_pos;
96
          }
97
        enc += 3;
98
      }
99
    else if ((*enc == '0') || (*enc == '1'))
100
      {
101
        opc_pos--;
102
        if (param_ch == *enc)
103
          ret |= 1 << opc_pos;
104
        enc++;
105
      }
106
    else if (*enc == param_ch)
107
      {
108
        opc_pos--;
109
        param_pos--;
110
#if DEBUG
111
        printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
112
#endif
113
        ret += ((insn >> opc_pos) & 0x1) << param_pos;
114 24 jeremybenn
 
115 225 jeremybenn
        if (!param_pos
116
            && letter_signed (param_ch)
117
            && ret >> (letter_range (param_ch) - 1))
118
          {
119
#if DEBUG
120
            printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n",
121
                    ret, opc_pos, param_pos);
122
#endif
123
            ret |= 0xffffffff << letter_range(param_ch);
124
#if DEBUG
125
            printf ("\n  after conversion to signed: ret=%x\n", ret);
126
#endif
127 24 jeremybenn
          }
128 225 jeremybenn
        enc++;
129
      }
130
    else if (ISALPHA (*enc))
131
      {
132
        opc_pos--;
133
        enc++;
134
      }
135
    else if (*enc == '-')
136
      {
137
        opc_pos--;
138
        enc++;
139
      }
140
    else
141
      enc++;
142 24 jeremybenn
 
143 225 jeremybenn
#if DEBUG
144
  printf ("ret=%x\n", ret);
145
#endif
146 24 jeremybenn
  return ret;
147 225 jeremybenn
}
148 24 jeremybenn
 
149
static int
150
or32_opcode_match (unsigned long insn, char *encoding)
151
{
152
  unsigned long ones, zeros;
153
 
154 225 jeremybenn
#if DEBUG
155
  printf ("or32_opcode_match: %.8lx\n", insn);
156
#endif    
157 24 jeremybenn
  ones  = or32_extract ('1', encoding, insn);
158
  zeros = or32_extract ('0', encoding, insn);
159 225 jeremybenn
 
160
  // Added 090430 - jb - fixed problem where upper 4 bytes of a 64-bit long weren't getting setup properly for comparison
161
  // As a result, instructions weren't getting decoded properly
162
  insn &= 0xffffffff;
163
  ones &= 0xffffffff;
164
  zeros &= 0xffffffff;
165 24 jeremybenn
 
166 225 jeremybenn
#if DEBUG
167
  printf ("ones: %x \n", ones);
168
  printf ("zeros: %x \n", zeros);
169
#endif
170 24 jeremybenn
  if ((insn & ones) != ones)
171
    {
172 225 jeremybenn
#if DEBUG
173
      printf ("ret1\n");
174
#endif
175 24 jeremybenn
      return 0;
176
    }
177
 
178
  if ((~insn & zeros) != zeros)
179
    {
180 225 jeremybenn
#if DEBUG
181
      printf ("ret2\n");
182
#endif
183 24 jeremybenn
      return 0;
184
    }
185
 
186 225 jeremybenn
#if DEBUG
187
  printf ("ret3\n");
188
#endif
189 24 jeremybenn
  return 1;
190 225 jeremybenn
}
191 24 jeremybenn
 
192 225 jeremybenn
/* Print register to INFO->STREAM. Used only by print_insn.  */
193 24 jeremybenn
 
194
static void
195
or32_print_register (char param_ch,
196
                     char *encoding,
197
                     unsigned long insn,
198
                     struct disassemble_info *info)
199
{
200
  int regnum = or32_extract (param_ch, encoding, insn);
201
 
202 225 jeremybenn
#if DEBUG
203
  printf ("or32_print_register: %c, %s, %x\n", param_ch, encoding, insn);
204
#endif  
205
  if (param_ch == 'A')
206
    (*info->fprintf_func) (info->stream, "r%d", regnum);
207
  else if (param_ch == 'B')
208
    (*info->fprintf_func) (info->stream, "r%d", regnum);
209
  else if (param_ch == 'D')
210
    (*info->fprintf_func) (info->stream, "r%d", regnum);
211
  else if (regnum < 16)
212
    (*info->fprintf_func) (info->stream, "r%d", regnum);
213
  else if (regnum < 32)
214
    (*info->fprintf_func) (info->stream, "r%d", regnum-16);
215
  else
216
    (*info->fprintf_func) (info->stream, "X%d", regnum);
217
}
218 24 jeremybenn
 
219
/* Print immediate to INFO->STREAM. Used only by print_insn.  */
220
 
221
static void
222 225 jeremybenn
or32_print_immediate (char param_ch,
223
                      char *encoding,
224
                      unsigned long insn,
225 24 jeremybenn
                      struct disassemble_info *info)
226
{
227
  int imm = or32_extract(param_ch, encoding, insn);
228
 
229 225 jeremybenn
  if (letter_signed(param_ch))
230
    (*info->fprintf_func) (info->stream, "0x%x", imm);
231
/*    (*info->fprintf_func) (info->stream, "%d", imm); */
232 24 jeremybenn
  else
233 225 jeremybenn
    (*info->fprintf_func) (info->stream, "0x%x", imm);
234
}
235 24 jeremybenn
 
236 225 jeremybenn
/* Print one instruction from MEMADDR on INFO->STREAM.
237
   Return the size of the instruction (always 4 on or32).  */
238 24 jeremybenn
 
239
static int
240 225 jeremybenn
print_insn (bfd_vma memaddr, struct disassemble_info *info)
241 24 jeremybenn
{
242
  /* The raw instruction.  */
243
  unsigned char insn_ch[4];
244
  /* Address. Will be sign extened 27-bit.  */
245
  unsigned long addr;
246
  /* The four bytes of the instruction.  */
247
  unsigned long insn;
248
  find_byte_func_type find_byte_func = (find_byte_func_type) info->private_data;
249 225 jeremybenn
  struct or32_opcode const * opcode;
250 24 jeremybenn
 
251 225 jeremybenn
  {
252
    int status =
253
      (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
254 24 jeremybenn
 
255 225 jeremybenn
    if (status != 0)
256
      {
257
        (*info->memory_error_func) (status, memaddr, info);
258
        return -1;
259
      }
260
  }
261 24 jeremybenn
 
262
  (*find_byte_func) (&insn_ch[0], &insn);
263
 
264
  for (opcode = &or32_opcodes[0];
265
       opcode < &or32_opcodes[or32_num_opcodes];
266
       ++opcode)
267
    {
268
      if (or32_opcode_match (insn, opcode->encoding))
269
        {
270
          char *s;
271
 
272 225 jeremybenn
          (*info->fprintf_func) (info->stream, "%s ", opcode->name);
273 24 jeremybenn
 
274
          for (s = opcode->args; *s != '\0'; ++s)
275
            {
276
              switch (*s)
277
                {
278
                case '\0':
279
                  return 4;
280
 
281
                case 'r':
282
                  or32_print_register (*++s, opcode->encoding, insn, info);
283
                  break;
284
 
285 225 jeremybenn
                case 'N':
286
                  addr = or32_extract ('N', opcode->encoding, insn) << 2;
287 24 jeremybenn
 
288 225 jeremybenn
                  /* Calulate the correct address.  */
289
                  addr = memaddr + EXTEND28 (addr);
290 24 jeremybenn
 
291
                  (*info->print_address_func)
292
                    (addr, info);
293
                  break;
294
 
295
                default:
296
                  if (strchr (opcode->encoding, *s))
297 225 jeremybenn
                    or32_print_immediate (*s, opcode->encoding, insn, info);
298 24 jeremybenn
                  else
299 225 jeremybenn
                    (*info->fprintf_func) (info->stream, "%c", *s);
300
                }
301 24 jeremybenn
            }
302
 
303
          return 4;
304
        }
305
    }
306
 
307
  /* This used to be %8x for binutils.  */
308 225 jeremybenn
  (*info->fprintf_func)
309
    (info->stream, ".word 0x%08lx", insn);
310 24 jeremybenn
  return 4;
311 225 jeremybenn
}
312 24 jeremybenn
 
313 225 jeremybenn
/* Disassemble a big-endian or32 instruction.  */
314 24 jeremybenn
 
315
int
316 225 jeremybenn
print_insn_big_or32 (bfd_vma memaddr, struct disassemble_info *info)
317 24 jeremybenn
{
318
  info->private_data = find_bytes_big;
319
 
320
  return print_insn (memaddr, info);
321 225 jeremybenn
}
322 24 jeremybenn
 
323 225 jeremybenn
/* Disassemble a little-endian or32 instruction.  */
324 24 jeremybenn
 
325
int
326 225 jeremybenn
print_insn_little_or32 (bfd_vma memaddr, struct disassemble_info *info)
327 24 jeremybenn
{
328
  info->private_data = find_bytes_little;
329
  return print_insn (memaddr, info);
330 225 jeremybenn
}

powered by: WebSVN 2.1.0

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