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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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