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

Subversion Repositories or1k

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

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

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

powered by: WebSVN 2.1.0

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