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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [open8-dis.c] - Blame information for rev 53

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

Line No. Rev Author Line
1 18 khays
/* Disassemble Open8 instructions.
2
   Copyright 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008, 2010, 2011
3
   Free Software Foundation, Inc.
4
 
5
   Contributed by Kirk Hays <khays@hayshaus.com>
6
 
7
   This file is part of libopcodes.
8
 
9
   This library 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 3, or (at your option)
12
   any later version.
13
 
14
   It is distributed in the hope that it will be useful, but WITHOUT
15
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17
   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., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
#include "sysdep.h"
25
#include "dis-asm.h"
26
#include "opintl.h"
27
#include "libiberty.h"
28
 
29
struct open8_opcodes_s
30
{
31
  char *name;
32
  char *constraints;
33
  char *opcode;
34
  int insn_size;                /* In bytes.  */
35
  int isa;
36
  unsigned long long opcode_bits;
37
  unsigned long long opcode_mask;
38
};
39
 
40
#define OPEN8_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN, MASK)  \
41
  {#NAME, CONSTR, OPCODE, SIZE, ISA, BIN, MASK},
42
 
43
const struct open8_opcodes_s open8_opcodes[] =
44
  {
45
#include "opcode/open8.h"
46
    {NULL, NULL, NULL, 0, 0, 0, 0}
47
  };
48
 
49
static const char * comment_start = "0x";
50
 
51
static int
52
open8_operand (unsigned long long insn,
53
               int constraint,
54
               char *buf,
55
               int buf_len,
56
               char *comment,
57
               int comment_len,
58
               int *sym,
59
               bfd_vma *sym_addr)
60
{
61
  int ok = 1;
62
  *sym = 0;
63
 
64
  switch (constraint)
65
    {
66
      /* Any register operand.  */
67
    case 'r':
68
      snprintf (buf, buf_len, "r%d", (int) ((insn & REG_MASK) >> REG_SHIFT));
69
      break;
70
 
71
      /* Even numbered register.  */
72
    case 'e':
73
      snprintf (buf, buf_len, "r%d", (int) ((insn & EREG_MASK) >> EREG_SHIFT));
74
      break;
75
 
76
      /* Unsigned offset expression, 8 bits.  */
77
    case 'u':
78
      snprintf (buf, buf_len, "%u", (int) ((insn & U_MASK) >> U_SHIFT));
79
      break;
80
 
81
      /* Signed pc-relative offset expression, 8 bits.  */
82
    case 's':
83
      {
84
        int8_t t = ((insn & S_MASK) >> S_SHIFT);
85
        snprintf (buf, buf_len, "%d", (int)t);  /* Propagate sign bit.  */
86
      }
87
      break;
88
 
89
      /* Immediate value expression, signed, 8 bits.  */
90
    case 'i':
91
      {
92
        int8_t t = ((insn & I_MASK) >> I_SHIFT);
93
        snprintf (buf, buf_len, "%d", (int)t);  /* Propagate sign bit.  */
94
      }
95
      break;
96
 
97
      /* Immediate value expression, 3 bits.  */
98
    case 'n':
99
      {
100
        snprintf (buf, buf_len, "%u", (int) ((insn & N_MASK) >> N_SHIFT));
101
      }
102
      break;
103
 
104
      /* Immediate value expression, 3 bits, indexing PSR.  */
105
    case 'b':
106
      {
107
        snprintf (buf, buf_len, "%u", (int) ((insn & B_MASK) >> B_SHIFT));
108
      }
109
      break;
110
 
111
      /* Memory reference, 16 bits, unsigned.  */
112
    case 'M':
113
      {
114
        *sym = 1;
115
        *sym_addr = (bfd_vma) ((insn & M_MASK) >> M_SHIFT);
116
        snprintf (buf, buf_len, "%#lx", (unsigned long) *sym_addr);
117
        strncpy (comment, comment_start, comment_len);
118
      }
119
      break;
120
 
121
      /* JSR/JMP reference, 16 bits, unsigned.  */
122
    case 'h':
123
      {
124
        *sym = 1;
125
        *sym_addr = (bfd_vma) ((insn & H_MASK) >> H_SHIFT);
126
        snprintf (buf, buf_len, "%#lx", (unsigned long) *sym_addr);
127
        strncpy (comment, comment_start, comment_len);
128
      }
129
      break;
130
 
131
      /* JSR/JMP reference, 16 bits, unsigned, in composite branch.  */
132
    case 'H':
133
      {
134
        *sym = 1;
135
        *sym_addr = (bfd_vma) ((insn & BIG_H_MASK) >> BIG_H_SHIFT);
136
        snprintf (buf, buf_len, "%#lx", (unsigned long) *sym_addr);
137
        strncpy (comment, comment_start, comment_len);
138
      }
139
      break;
140
 
141
      /* autoincrement operator.  */
142
    case 'a':
143
      {
144
        if (insn & A_MASK)
145
          {
146
            snprintf (buf, buf_len, "%s", "++");
147
          }
148
      }
149
      break;
150
 
151
      /* syntactic sugar - comma.  */
152
    case ',':
153
      {
154
        snprintf (buf, buf_len, "%s", ",");
155
      }
156
      break;
157
 
158
    default:
159
      {
160
        snprintf (buf, buf_len, "??");
161
        fprintf (stderr, _("unknown constraint `%c'"), constraint);
162
        ok = 0;
163
      }
164
    }
165
 
166
  return ok;
167
}
168
 
169
static unsigned long long
170
open8_dis_opcode (bfd_vma addr, disassemble_info *info)
171
{
172
  bfd_byte buffer[sizeof (unsigned long long)];
173
  int status;
174
 
175
  int readsize = sizeof buffer;
176
 
177
  /* Make sure we don't try to read past the end of the section.  */
178
  if (addr + readsize >= info->section->size)
179
    {
180
      readsize = info->section->size - addr;
181
      memset (buffer, 0, sizeof buffer);
182
    }
183
 
184
  status = info->read_memory_func (addr, buffer, readsize, info);
185
 
186
  if (status == 0)
187
    return bfd_getl64 (buffer);
188
 
189
  info->memory_error_func (status, addr, info);
190
  return -1;
191
}
192
 
193
 
194
int
195
print_insn_open8 (bfd_vma addr, disassemble_info *info)
196
{
197
  unsigned long long insn;
198
  const struct open8_opcodes_s *opcode;
199
  void *stream = info->stream;
200
  fprintf_ftype prin = info->fprintf_func;
201
  int ok = 0;
202
  char op1[20], op2[20], op3[20], comment1[40], comment2[40], comment3[40];
203
  int comma1 = 0, comma2 = 0;
204
  int sym_op1 = 0, sym_op2 = 0, sym_op3 = 0;
205
  bfd_vma sym_addr1, sym_addr2, sym_addr3;
206
 
207
  if (info->symtab_size == 0)
208
    comment_start = " ";
209
 
210
  insn = open8_dis_opcode (addr, info);
211
 
212
  /* Scan the opcode descriptors, looking for an opcode match.  */
213
  for (opcode = open8_opcodes;
214
       opcode->name;
215
       opcode++)
216
    {
217
      /* If the memory anded with the mask matches required opcode bits,
218
         then we have a match.  */
219
      if ((insn & opcode->opcode_mask) == opcode->opcode_bits)
220
        {
221
          break;
222
        }
223
    }
224
 
225
  op1[0] = 0;
226
  op2[0] = 0;
227
  op3[0] = 0;
228
  comment1[0] = 0;
229
  comment2[0] = 0;
230
  comment3[0] = 0;
231
 
232
  /* Parse the binary value using the constraints.  */
233
  if (opcode->name)
234
    {
235
      char *op = opcode->constraints;
236
 
237
      ok = 1;
238
 
239
      if (*op)
240
        {
241
          /* Grab the first operand.  */
242
          ok = open8_operand (insn,
243
                              *op++,
244
                              op1,
245
                              sizeof op1 - strlen (op1),
246
                              comment1,
247
                              sizeof comment1 - strlen (comment1),
248
                              &sym_op1,
249
                              &sym_addr1);
250
 
251
          /* Note a comma.  */
252
          if (ok && *op == ',')
253
            {
254
              comma1++;
255
              op++;
256
            }
257
 
258
          /* Grab the second operand.  */
259
          if (ok && *op)
260
            {
261
              ok = open8_operand (insn,
262
                                  *op++,
263
                                  op2,
264
                                  sizeof op2 - strlen (op2),
265
                                  (*comment1
266
                                   ? comment2
267
                                   : comment1),
268
                                  (*comment1
269
                                   ? sizeof comment2 - strlen (comment2)
270
                                   : sizeof comment1 - strlen (comment1)),
271
                                  &sym_op2,
272
                                  &sym_addr2);
273
            }
274
 
275
          /* Note a comma.  */
276
          if (ok && *op == ',')
277
            {
278
              comma2++;
279
              op++;
280
            }
281
 
282
          /* Grab the third operand.  */
283
          if (ok && *op)
284
            {
285
              ok = open8_operand (insn,
286
                                  *op++,
287
                                  op3,
288
                                  sizeof op3 - strlen (op3),
289
                                  (*comment1
290
                                   ? (*comment2
291
                                      ? comment3
292
                                      : comment2)
293
                                   : comment1),
294
                                  (*comment1
295
                                   ? (*comment2
296
                                      ? sizeof comment3 - strlen (comment3)
297
                                      : sizeof comment2 - strlen (comment2))
298
                                   : sizeof comment1 - strlen (comment1)),
299
                                  &sym_op3, &sym_addr3);
300
            }
301
 
302
        }
303
    }
304
 
305
  if (!ok)
306
    {
307
      /* Unknown opcode, or invalid combination of operands.  */
308
      snprintf (op1, sizeof op1, "0x%04x", (unsigned int)insn);
309
      op2[0] = 0;
310
      op3[0] = 0;
311
      snprintf (comment1, sizeof comment1, "????");
312
      comment2[0] = 0;
313
      comment3[0] = 0;
314
    }
315
 
316
  (*prin) (stream, "%s", ok ? opcode->name : ".word");
317
 
318
  if (*op1)
319
    (*prin) (stream, "\t%s", op1);
320
 
321
  if (comma1)
322
    (*prin) (stream, "%s",",");
323
 
324
  if (*op2)
325
    (*prin) (stream, " %s", op2);
326
 
327
  if (comma2)
328
    (*prin) (stream, "%s",",");
329
 
330
  if (*op3)
331
    (*prin) (stream, " %s", op3);
332
 
333
  if (*comment1)
334
    (*prin) (stream, "\t; %s", comment1);
335
 
336
  if (sym_op1)
337
    info->print_address_func (sym_addr1, info);
338
 
339
  if (*comment2)
340
    (*prin) (stream, " %s", comment2);
341
 
342
  if (sym_op2)
343
    info->print_address_func (sym_addr2, info);
344
 
345
  if (*comment3)
346
    (*prin) (stream, " %s", comment3);
347
 
348
  if (sym_op3)
349
    info->print_address_func (sym_addr3, info);
350
 
351
  return opcode->insn_size;
352
}

powered by: WebSVN 2.1.0

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