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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [binutils/] [binutils-2.16.1/] [opcodes/] [or32-dis.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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