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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [opcodes/] [or32-dis.c] - Blame information for rev 1767

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

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

powered by: WebSVN 2.1.0

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