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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [or1k-dis.c] - Blame information for rev 1772

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

Line No. Rev Author Line
1 578 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 NO_RELOC 20
23
#define RELOC_32 1
24
#define RELOC_8 2
25
#define RELOC_CONST 3
26
#define RELOC_CONSTH 4
27
 
28
#define DEBUG 0
29
 
30
#include "dis-asm.h"
31
#include "opcode/or1k.h"
32
 
33
#include <ctype.h>
34
#include <string.h>
35
 
36
/* Now find the four bytes of INSN_CH and put them in *INSN.  */
37
static void
38
find_bytes_big (insn_ch, insn)
39
     unsigned char *insn_ch;
40
     unsigned long *insn;
41
{
42
  *insn = ((unsigned long)insn_ch[0] << 24) +
43
      ((unsigned long)insn_ch[1] << 16) +
44
      ((unsigned long)insn_ch[2] << 8) +
45
      (unsigned long)insn_ch[3];
46
#if DEBUG
47
      printf("find_bytes_big3: %x\n", *insn);
48
#endif
49
}
50
 
51
static void
52
find_bytes_little (insn_ch, insn)
53
     unsigned char *insn_ch;
54
     unsigned long *insn;
55
{
56
  *insn = ((unsigned long)insn_ch[3] << 24) +
57
      ((unsigned long)insn_ch[2] << 16) +
58
      ((unsigned long)insn_ch[1] << 8) +
59
      (unsigned long)insn_ch[0];
60
}
61
 
62
 
63
typedef void (*find_byte_func_type)
64
     PARAMS ((unsigned char *, unsigned long *));
65
 
66
static unsigned long
67
or32_extract(param_ch, enc_initial, insn)
68
     char param_ch;
69
     char *enc_initial;
70
     unsigned long insn;
71
{
72
  char *enc;
73
  unsigned long ret = 0;
74
        int opc_pos = 0;
75
        int param_pos = 0;
76
 
77
        for (enc = enc_initial; *enc != '\0'; enc++)
78
                if (*enc == param_ch)
79
                        param_pos++;
80
 
81
#if DEBUG
82
  printf("or32_extract: %x ", param_pos);
83
#endif
84
        opc_pos = 32;
85
        for (enc = enc_initial; *enc != '\0'; )
86
                if ((*enc == '0') && (*(enc+1) == 'x')) {
87
                  opc_pos -= 4;
88
                  if ((param_ch == '0') || (param_ch == '1')) {
89
                        unsigned long tmp = strtol(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
                  opc_pos--;
101
                  if (param_ch == *enc)
102
                        ret |= 1 << opc_pos;
103
                  enc++;
104
                }
105
                else if (*enc == param_ch) {
106
                        opc_pos--;
107
                        param_pos--;
108
#if DEBUG
109
                        printf("\n  ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
110
#endif
111
                        if (islower(param_ch))
112
                          ret -= ((insn >> opc_pos) & 0x1) << param_pos;
113
                  else
114
                          ret += ((insn >> opc_pos) & 0x1) << param_pos;
115
                        enc++;
116
                }
117
                else if (isalpha(*enc)) {
118
                        opc_pos--;
119
                        enc++;
120
                }
121
                else if (*enc == '-') {
122
                  opc_pos--;
123
                  enc++;
124
                }
125
                else
126
                        enc++;
127
 
128
#if DEBUG
129
  printf("ret=%x\n", ret);
130
#endif
131
  return ret;
132
}
133
 
134
static int
135
or32_opcode_match (insn, encoding)
136
     unsigned long insn;
137
     char *encoding;
138
{
139
  unsigned long ones, zeros;
140
 
141
#if DEBUG
142
  printf("or32_opcode_match: %.8lx\n", insn);
143
#endif    
144
  ones = or32_extract('1', encoding, insn);
145
  zeros = or32_extract('0', encoding, insn);
146
 
147
#if DEBUG
148
  printf("ones: %x \n", ones);
149
  printf("zeros: %x \n", zeros);
150
#endif
151
  if ((insn & ones) != ones) {
152
#if DEBUG
153
    printf("ret1\n");
154
#endif
155
    return 0;
156
  }
157
 
158
  if ((~insn & zeros) != zeros) {
159
#if DEBUG
160
    printf("ret2\n");
161
#endif
162
    return 0;
163
  }
164
 
165
#if DEBUG
166
  printf("ret3\n");
167
#endif
168
  return 1;
169
}
170
 
171
 
172
/* Print register to INFO->STREAM. Used only by print_insn. */
173
 
174
static void
175
or32_print_register (param_ch, encoding, insn, info)
176
     char param_ch;
177
     char *encoding;
178
     unsigned long insn;
179
     struct disassemble_info *info;
180
{
181
  int regnum = or32_extract(param_ch, encoding, insn);
182
 
183
#if DEBUG
184
  printf("or32_print_register: %c, %s, %x\n", param_ch, encoding, insn);
185
#endif  
186
  if (param_ch == 'A')
187
    (*info->fprintf_func) (info->stream, "a%d", regnum);
188
  else if (param_ch == 'B')
189
                (*info->fprintf_func) (info->stream, "b%d", regnum);
190
  else if (param_ch == 'S')
191
                (*info->fprintf_func) (info->stream, "s%d", regnum);
192
        else if (regnum < 16)
193
                (*info->fprintf_func) (info->stream, "a%d", regnum);
194
        else if (regnum < 32)
195
                (*info->fprintf_func) (info->stream, "b%d", regnum-16);
196
  else
197
                (*info->fprintf_func) (info->stream, "X%d", regnum);
198
}
199
 
200
/* Print immediate to INFO->STREAM. Used only by print_insn. */
201
 
202
static void
203
or32_print_immediate (param_ch, encoding, insn, info)
204
     char param_ch;
205
     char *encoding;
206
     unsigned long insn;
207
     struct disassemble_info *info;
208
{
209
  int imm = or32_extract(param_ch, encoding, insn);
210
 
211
  if (islower(param_ch))
212
    (*info->fprintf_func) (info->stream, "%d", imm);
213
  else
214
                (*info->fprintf_func) (info->stream, "%u", imm);
215
}
216
 
217
/* Print one instruction from MEMADDR on INFO->STREAM.
218
   Return the size of the instruction (always 4 on or32).  */
219
 
220
static int
221
print_insn (memaddr, info)
222
     bfd_vma memaddr;
223
     struct disassemble_info *info;
224
{
225
  /* The raw instruction.  */
226
  unsigned char insn_ch[4];
227
 
228
  /* The four bytes of the instruction.  */
229
  unsigned long insn;
230
 
231
  find_byte_func_type find_byte_func = (find_byte_func_type)info->private_data;
232
 
233
  struct or32_opcode CONST * opcode;
234
 
235
  {
236
    int status =
237
      (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
238
    if (status != 0)
239
      {
240
  (*info->memory_error_func) (status, memaddr, info);
241
  return -1;
242
      }
243
  }
244
 
245
  (*find_byte_func) (&insn_ch[0], &insn);
246
 
247
  for (opcode = &or32_opcodes[0];
248
       opcode < &or32_opcodes[num_opcodes];
249
       ++opcode)
250
    {
251
      if (or32_opcode_match (insn, opcode->encoding))
252
  {
253
    char *s;
254
 
255
    (*info->fprintf_func) (info->stream, "%s ", opcode->name);
256
    for (s = opcode->args; *s != '\0'; ++s)
257
      {
258
        switch (*s)
259
    {
260
    case '\0':
261
      return 4;
262
 
263
    case 'r':
264
      or32_print_register(*++s, opcode->encoding, insn, info);
265
      break;
266
 
267
    case 'X':
268
      (*info->print_address_func)
269
        (or32_extract ('X', opcode->encoding, insn), info);
270
      break;
271
 
272
    default:
273
      if (strchr (opcode->encoding, *s))
274
        or32_print_immediate (*s, opcode->encoding, insn, info);
275
      else
276
        (*info->fprintf_func) (info->stream, "%c", *s);
277
    }
278
      }
279
 
280
    return 4;
281
  }
282
    }
283
  /* This used to be %8x for binutils.  */
284
  (*info->fprintf_func)
285
    (info->stream, ".word 0x%08x", insn);
286
  return 4;
287
}
288
 
289
/* Disassemble a big-endian or32 instruction.  */
290
int
291
print_insn_big_or32 (memaddr, info)
292
     bfd_vma memaddr;
293
     struct disassemble_info *info;
294
{
295
  info->private_data = (PTR) find_bytes_big;
296
  return print_insn (memaddr, info);
297
}
298
 
299
/* Disassemble a little-endian or32 instruction.  */
300
int
301
print_insn_little_or32 (memaddr, info)
302
     bfd_vma memaddr;
303
     struct disassemble_info *info;
304
{
305
  info->private_data = (PTR) find_bytes_little;
306
  return print_insn (memaddr, info);
307
}

powered by: WebSVN 2.1.0

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