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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 18 khays
/* Print TI TMS320C80 (MVP) instructions
2
   Copyright 1996, 1997, 1998, 2000, 2005, 2007 Free Software Foundation, Inc.
3
 
4
   This file is part of the GNU opcodes library.
5
 
6
   This library is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
 
11
   It is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
 
21
#include <stdio.h>
22
 
23
#include "sysdep.h"
24
#include "opcode/tic80.h"
25
#include "dis-asm.h"
26
 
27
static int length;
28
 
29
/* Print an integer operand.  Try to be somewhat smart about the
30
   format by assuming that small positive or negative integers are
31
   probably loop increment values, structure offsets, or similar
32
   values that are more meaningful printed as signed decimal values.
33
   Larger numbers are probably better printed as hex values.  */
34
 
35
static void
36
print_operand_integer (struct disassemble_info *info, long value)
37
{
38
  if ((value > 9999 || value < -9999))
39
    (*info->fprintf_func) (info->stream, "%#lx", value);
40
  else
41
    (*info->fprintf_func) (info->stream, "%ld", value);
42
}
43
 
44
/* FIXME: depends upon sizeof (long) == sizeof (float) and
45
   also upon host floating point format matching target
46
   floating point format.  */
47
 
48
static void
49
print_operand_float (struct disassemble_info *info, long value)
50
{
51
  union { float f; long l; } fval;
52
 
53
  fval.l = value;
54
  (*info->fprintf_func) (info->stream, "%g", fval.f);
55
}
56
 
57
static void
58
print_operand_control_register (struct disassemble_info *info, long value)
59
{
60
  const char *tmp;
61
 
62
  tmp = tic80_value_to_symbol (value, TIC80_OPERAND_CR);
63
  if (tmp != NULL)
64
    (*info->fprintf_func) (info->stream, "%s", tmp);
65
  else
66
    (*info->fprintf_func) (info->stream, "%#lx", value);
67
}
68
 
69
static void
70
print_operand_condition_code (struct disassemble_info *info, long value)
71
{
72
  const char *tmp;
73
 
74
  tmp = tic80_value_to_symbol (value, TIC80_OPERAND_CC);
75
  if (tmp != NULL)
76
    (*info->fprintf_func) (info->stream, "%s", tmp);
77
  else
78
    (*info->fprintf_func) (info->stream, "%ld", value);
79
}
80
 
81
static void
82
print_operand_bitnum (struct disassemble_info *info, long value)
83
{
84
  int bitnum;
85
  const char *tmp;
86
 
87
  bitnum = ~value & 0x1F;
88
  tmp = tic80_value_to_symbol (bitnum, TIC80_OPERAND_BITNUM);
89
  if (tmp != NULL)
90
    (*info->fprintf_func) (info->stream, "%s", tmp);
91
  else
92
    (*info->fprintf_func) (info->stream, "%d", bitnum);
93
}
94
 
95
/* Print the operand as directed by the flags.  */
96
 
97
#define M_SI(insn,op) ((((op)->flags & TIC80_OPERAND_M_SI) != 0) && ((insn) & (1 << 17)))
98
#define M_LI(insn,op) ((((op)->flags & TIC80_OPERAND_M_LI) != 0) && ((insn) & (1 << 15)))
99
#define R_SCALED(insn,op) ((((op)->flags & TIC80_OPERAND_SCALED) != 0) && ((insn) & (1 << 11)))
100
 
101
static void
102
print_operand (struct disassemble_info *info,
103
               long value,
104
               unsigned long insn,
105
               const struct tic80_operand *operand,
106
               bfd_vma memaddr)
107
{
108
  if ((operand->flags & TIC80_OPERAND_GPR) != 0)
109
    {
110
      (*info->fprintf_func) (info->stream, "r%ld", value);
111
      if (M_SI (insn, operand) || M_LI (insn, operand))
112
        {
113
          (*info->fprintf_func) (info->stream, ":m");
114
        }
115
    }
116
  else if ((operand->flags & TIC80_OPERAND_FPA) != 0)
117
    (*info->fprintf_func) (info->stream, "a%ld", value);
118
 
119
  else if ((operand->flags & TIC80_OPERAND_PCREL) != 0)
120
    (*info->print_address_func) (memaddr + 4 * value, info);
121
 
122
  else if ((operand->flags & TIC80_OPERAND_BASEREL) != 0)
123
    (*info->print_address_func) (value, info);
124
 
125
  else if ((operand->flags & TIC80_OPERAND_BITNUM) != 0)
126
    print_operand_bitnum (info, value);
127
 
128
  else if ((operand->flags & TIC80_OPERAND_CC) != 0)
129
    print_operand_condition_code (info, value);
130
 
131
  else if ((operand->flags & TIC80_OPERAND_CR) != 0)
132
    print_operand_control_register (info, value);
133
 
134
  else if ((operand->flags & TIC80_OPERAND_FLOAT) != 0)
135
    print_operand_float (info, value);
136
 
137
  else if ((operand->flags & TIC80_OPERAND_BITFIELD))
138
    (*info->fprintf_func) (info->stream, "%#lx", value);
139
 
140
  else
141
    print_operand_integer (info, value);
142
 
143
  /* If this is a scaled operand, then print the modifier.  */
144
  if (R_SCALED (insn, operand))
145
    (*info->fprintf_func) (info->stream, ":s");
146
}
147
 
148
/* Get the next 32 bit word from the instruction stream and convert it
149
   into internal format in the unsigned long INSN, for which we are
150
   passed the address.  Return 0 on success, -1 on error.  */
151
 
152
static int
153
fill_instruction (struct disassemble_info *info,
154
                  bfd_vma memaddr,
155
                  unsigned long *insnp)
156
{
157
  bfd_byte buffer[4];
158
  int status;
159
 
160
  /* Get the bits for the next 32 bit word and put in buffer.  */
161
  status = (*info->read_memory_func) (memaddr + length, buffer, 4, info);
162
  if (status != 0)
163
    {
164
      (*info->memory_error_func) (status, memaddr, info);
165
      return -1;
166
    }
167
 
168
  /* Read was successful, so increment count of bytes read and convert
169
     the bits into internal format.  */
170
 
171
  length += 4;
172
  if (info->endian == BFD_ENDIAN_LITTLE)
173
    *insnp = bfd_getl32 (buffer);
174
 
175
  else if (info->endian == BFD_ENDIAN_BIG)
176
    *insnp = bfd_getb32 (buffer);
177
 
178
  else
179
    /* FIXME: Should probably just default to one or the other.  */
180
    abort ();
181
 
182
  return 0;
183
}
184
 
185
/* We have chosen an opcode table entry.  */
186
 
187
static int
188
print_one_instruction (struct disassemble_info *info,
189
                       bfd_vma memaddr,
190
                       unsigned long insn,
191
                       const struct tic80_opcode *opcode)
192
{
193
  const struct tic80_operand *operand;
194
  long value;
195
  int status;
196
  const unsigned char *opindex;
197
  int close_paren;
198
 
199
  (*info->fprintf_func) (info->stream, "%-10s", opcode->name);
200
 
201
  for (opindex = opcode->operands; *opindex != 0; opindex++)
202
    {
203
      operand = tic80_operands + *opindex;
204
 
205
      /* Extract the value from the instruction.  */
206
      if (operand->extract)
207
        value = (*operand->extract) (insn, NULL);
208
 
209
      else if (operand->bits == 32)
210
        {
211
          status = fill_instruction (info, memaddr, (unsigned long *) &value);
212
          if (status == -1)
213
            return status;
214
        }
215
      else
216
        {
217
          value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
218
 
219
          if ((operand->flags & TIC80_OPERAND_SIGNED) != 0
220
              && (value & (1 << (operand->bits - 1))) != 0)
221
            value -= 1 << operand->bits;
222
        }
223
 
224
      /* If this operand is enclosed in parenthesis, then print
225
         the open paren, otherwise just print the regular comma
226
         separator, except for the first operand.  */
227
      if ((operand->flags & TIC80_OPERAND_PARENS) == 0)
228
        {
229
          close_paren = 0;
230
          if (opindex != opcode->operands)
231
            (*info->fprintf_func) (info->stream, ",");
232
        }
233
      else
234
        {
235
          close_paren = 1;
236
          (*info->fprintf_func) (info->stream, "(");
237
        }
238
 
239
      print_operand (info, value, insn, operand, memaddr);
240
 
241
      /* If we printed an open paren before printing this operand, close
242
         it now. The flag gets reset on each loop.  */
243
      if (close_paren)
244
        (*info->fprintf_func) (info->stream, ")");
245
    }
246
 
247
  return length;
248
}
249
 
250
/* There are no specific bits that tell us for certain whether a vector
251
   instruction opcode contains one or two instructions.  However since
252
   a destination register of r0 is illegal, we can check for nonzero
253
   values in both destination register fields.  Only opcodes that have
254
   two valid instructions will have non-zero in both.  */
255
 
256
#define TWO_INSN(insn) ((((insn) & (0x1F << 27)) != 0) && (((insn) & (0x1F << 22)) != 0))
257
 
258
static int
259
print_instruction (struct disassemble_info *info,
260
                   bfd_vma memaddr,
261
                   unsigned long insn,
262
                   const struct tic80_opcode *vec_opcode)
263
{
264
  const struct tic80_opcode *opcode;
265
  const struct tic80_opcode *opcode_end;
266
 
267
  /* Find the first opcode match in the opcodes table.  For vector
268
     opcodes (vec_opcode != NULL) find the first match that is not the
269
     previously found match.  FIXME: there should be faster ways to
270
     search (hash table or binary search), but don't worry too much
271
     about it until other TIc80 support is finished.  */
272
 
273
  opcode_end = tic80_opcodes + tic80_num_opcodes;
274
  for (opcode = tic80_opcodes; opcode < opcode_end; opcode++)
275
    {
276
      if ((insn & opcode->mask) == opcode->opcode &&
277
          opcode != vec_opcode)
278
        break;
279
    }
280
 
281
  if (opcode == opcode_end)
282
    {
283
      /* No match found, just print the bits as a .word directive.  */
284
      (*info->fprintf_func) (info->stream, ".word %#08lx", insn);
285
    }
286
  else
287
    {
288
      /* Match found, decode the instruction.  */
289
      length = print_one_instruction (info, memaddr, insn, opcode);
290
      if (opcode->flags & TIC80_VECTOR && vec_opcode == NULL && TWO_INSN (insn))
291
        {
292
          /* There is another instruction to print from the same opcode.
293
             Print the separator and then find and print the other
294
             instruction.  */
295
          (*info->fprintf_func) (info->stream, "   ||   ");
296
          length = print_instruction (info, memaddr, insn, opcode);
297
        }
298
    }
299
 
300
  return length;
301
}
302
 
303
int
304
print_insn_tic80 (bfd_vma memaddr, struct disassemble_info *info)
305
{
306
  unsigned long insn;
307
  int status;
308
 
309
  length = 0;
310
  info->bytes_per_line = 8;
311
  status = fill_instruction (info, memaddr, &insn);
312
  if (status != -1)
313
    status = print_instruction (info, memaddr, insn, NULL);
314
 
315
  return status;
316
}

powered by: WebSVN 2.1.0

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