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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [cpu/] [m32r.opc] - Blame information for rev 303

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

Line No. Rev Author Line
1 24 khays
/* M32R opcode support.  -*- C -*-
2
 
3
   Copyright 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2009
4
   Free Software Foundation, Inc.
5
 
6
   Contributed by Red Hat Inc; developed under contract from
7
   Mitsubishi Electric Corporation.
8
 
9
   This file is part of the GNU Binutils.
10
 
11
   This program is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3 of the License, or
14
   (at your option) any later version.
15
 
16
   This program is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
 
21
   You should have received a copy of the GNU General Public License
22
   along with this program; if not, write to the Free Software
23
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24
   MA 02110-1301, USA.  */
25
 
26
 
27
/* This file is an addendum to m32r.cpu.  Heavy use of C code isn't
28
   appropriate in .cpu files, so it resides here.  This especially applies
29
   to assembly/disassembly where parsing/printing can be quite involved.
30
   Such things aren't really part of the specification of the cpu, per se,
31
   so .cpu files provide the general framework and .opc files handle the
32
   nitty-gritty details as necessary.
33
 
34
   Each section is delimited with start and end markers.
35
 
36
   -opc.h additions use: "-- opc.h"
37
   -opc.c additions use: "-- opc.c"
38
   -asm.c additions use: "-- asm.c"
39
   -dis.c additions use: "-- dis.c"
40
   -ibd.h additions use: "-- ibd.h"  */
41
 
42
/* -- opc.h */
43
 
44
#undef  CGEN_DIS_HASH_SIZE
45
#define CGEN_DIS_HASH_SIZE 256
46
#undef  CGEN_DIS_HASH
47
#if 0
48
#define X(b) (((unsigned char *) (b))[0] & 0xf0)
49
#define CGEN_DIS_HASH(buffer, value) \
50
(X (buffer) | \
51
 (X (buffer) == 0x40 || X (buffer) == 0xe0 || X (buffer) == 0x60 || X (buffer) == 0x50 ? 0 \
52
  : X (buffer) == 0x70 || X (buffer) == 0xf0 ? (((unsigned char *) (buffer))[0] & 0xf) \
53
  : X (buffer) == 0x30 ? ((((unsigned char *) (buffer))[1] & 0x70) >> 4) \
54
  : ((((unsigned char *) (buffer))[1] & 0xf0) >> 4)))
55
#else
56
#define CGEN_DIS_HASH(buffer, value) m32r_cgen_dis_hash (buffer, value)
57
extern unsigned int m32r_cgen_dis_hash (const char *, CGEN_INSN_INT);
58
#endif
59
 
60
/* -- */
61
 
62
/* -- opc.c */
63
unsigned int
64
m32r_cgen_dis_hash (const char * buf ATTRIBUTE_UNUSED, CGEN_INSN_INT value)
65
{
66
  unsigned int x;
67
 
68
  if (value & 0xffff0000) /* 32bit instructions.  */
69
    value = (value >> 16) & 0xffff;
70
 
71
  x = (value >> 8) & 0xf0;
72
  if (x == 0x40 || x == 0xe0 || x == 0x60 || x == 0x50)
73
    return x;
74
 
75
  if (x == 0x70 || x == 0xf0)
76
    return x | ((value >> 8) & 0x0f);
77
 
78
  if (x == 0x30)
79
    return x | ((value & 0x70) >> 4);
80
  else
81
    return x | ((value & 0xf0) >> 4);
82
}
83
 
84
/* -- */
85
 
86
/* -- asm.c */
87
static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
88
 
89
/* Handle '#' prefixes (i.e. skip over them).  */
90
 
91
static const char *
92
parse_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
93
            const char **strp,
94
            int opindex ATTRIBUTE_UNUSED,
95
            long *valuep ATTRIBUTE_UNUSED)
96
{
97
  if (**strp == '#')
98
    ++*strp;
99
  return NULL;
100
}
101
 
102
/* Handle shigh(), high().  */
103
 
104
static const char *
105
parse_hi16 (CGEN_CPU_DESC cd,
106
            const char **strp,
107
            int opindex,
108
            unsigned long *valuep)
109
{
110
  const char *errmsg;
111
  enum cgen_parse_operand_result result_type;
112
  bfd_vma value;
113
 
114
  if (**strp == '#')
115
    ++*strp;
116
 
117
  if (strncasecmp (*strp, "high(", 5) == 0)
118
    {
119
      *strp += 5;
120
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
121
                                   & result_type, & value);
122
      if (**strp != ')')
123
        return MISSING_CLOSING_PARENTHESIS;
124
      ++*strp;
125
      if (errmsg == NULL
126
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
127
        {
128
          value >>= 16;
129
          value &= 0xffff;
130
        }
131
      *valuep = value;
132
      return errmsg;
133
    }
134
  else if (strncasecmp (*strp, "shigh(", 6) == 0)
135
    {
136
      *strp += 6;
137
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
138
                                   & result_type, & value);
139
      if (**strp != ')')
140
        return MISSING_CLOSING_PARENTHESIS;
141
      ++*strp;
142
      if (errmsg == NULL
143
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
144
        {
145
          value += 0x8000;
146
          value >>= 16;
147
          value &= 0xffff;
148
        }
149
      *valuep = value;
150
      return errmsg;
151
    }
152
 
153
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
154
}
155
 
156
/* Handle low() in a signed context.  Also handle sda().
157
   The signedness of the value doesn't matter to low(), but this also
158
   handles the case where low() isn't present.  */
159
 
160
static const char *
161
parse_slo16 (CGEN_CPU_DESC cd,
162
             const char ** strp,
163
             int opindex,
164
             long * valuep)
165
{
166
  const char *errmsg;
167
  enum cgen_parse_operand_result result_type;
168
  bfd_vma value;
169
 
170
  if (**strp == '#')
171
    ++*strp;
172
 
173
  if (strncasecmp (*strp, "low(", 4) == 0)
174
    {
175
      *strp += 4;
176
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
177
                                   & result_type, & value);
178
      if (**strp != ')')
179
        return MISSING_CLOSING_PARENTHESIS;
180
      ++*strp;
181
      if (errmsg == NULL
182
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
183
        value = ((value & 0xffff) ^ 0x8000) - 0x8000;
184
      *valuep = value;
185
      return errmsg;
186
    }
187
 
188
  if (strncasecmp (*strp, "sda(", 4) == 0)
189
    {
190
      *strp += 4;
191
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
192
                                   NULL, & value);
193
      if (**strp != ')')
194
        return MISSING_CLOSING_PARENTHESIS;
195
      ++*strp;
196
      *valuep = value;
197
      return errmsg;
198
    }
199
 
200
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
201
}
202
 
203
/* Handle low() in an unsigned context.
204
   The signedness of the value doesn't matter to low(), but this also
205
   handles the case where low() isn't present.  */
206
 
207
static const char *
208
parse_ulo16 (CGEN_CPU_DESC cd,
209
             const char **strp,
210
             int opindex,
211
             unsigned long *valuep)
212
{
213
  const char *errmsg;
214
  enum cgen_parse_operand_result result_type;
215
  bfd_vma value;
216
 
217
  if (**strp == '#')
218
    ++*strp;
219
 
220
  if (strncasecmp (*strp, "low(", 4) == 0)
221
    {
222
      *strp += 4;
223
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
224
                                   & result_type, & value);
225
      if (**strp != ')')
226
        return MISSING_CLOSING_PARENTHESIS;
227
      ++*strp;
228
      if (errmsg == NULL
229
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
230
        value &= 0xffff;
231
      *valuep = value;
232
      return errmsg;
233
    }
234
 
235
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
236
}
237
 
238
/* -- */
239
 
240
/* -- dis.c */
241
 
242
/* Print signed operands with '#' prefixes.  */
243
 
244
static void
245
print_signed_with_hash_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
246
                               void * dis_info,
247
                               long value,
248
                               unsigned int attrs ATTRIBUTE_UNUSED,
249
                               bfd_vma pc ATTRIBUTE_UNUSED,
250
                               int length ATTRIBUTE_UNUSED)
251
{
252
  disassemble_info *info = (disassemble_info *) dis_info;
253
 
254
  (*info->fprintf_func) (info->stream, "#");
255
  (*info->fprintf_func) (info->stream, "%ld", value);
256
}
257
 
258
/* Print unsigned operands with '#' prefixes.  */
259
 
260
static void
261
print_unsigned_with_hash_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
262
                                 void * dis_info,
263
                                 long value,
264
                                 unsigned int attrs ATTRIBUTE_UNUSED,
265
                                 bfd_vma pc ATTRIBUTE_UNUSED,
266
                                 int length ATTRIBUTE_UNUSED)
267
{
268
  disassemble_info *info = (disassemble_info *) dis_info;
269
 
270
  (*info->fprintf_func) (info->stream, "#");
271
  (*info->fprintf_func) (info->stream, "0x%lx", value);
272
}
273
 
274
/* Handle '#' prefixes as operands.  */
275
 
276
static void
277
print_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
278
            void * dis_info,
279
            long value ATTRIBUTE_UNUSED,
280
            unsigned int attrs ATTRIBUTE_UNUSED,
281
            bfd_vma pc ATTRIBUTE_UNUSED,
282
            int length ATTRIBUTE_UNUSED)
283
{
284
  disassemble_info *info = (disassemble_info *) dis_info;
285
 
286
  (*info->fprintf_func) (info->stream, "#");
287
}
288
 
289
#undef  CGEN_PRINT_INSN
290
#define CGEN_PRINT_INSN my_print_insn
291
 
292
static int
293
my_print_insn (CGEN_CPU_DESC cd,
294
               bfd_vma pc,
295
               disassemble_info *info)
296
{
297
  bfd_byte buffer[CGEN_MAX_INSN_SIZE];
298
  bfd_byte *buf = buffer;
299
  int status;
300
  int buflen = (pc & 3) == 0 ? 4 : 2;
301
  int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
302
  bfd_byte *x;
303
 
304
  /* Read the base part of the insn.  */
305
 
306
  status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
307
                                      buf, buflen, info);
308
  if (status != 0)
309
    {
310
      (*info->memory_error_func) (status, pc, info);
311
      return -1;
312
    }
313
 
314
  /* 32 bit insn?  */
315
  x = (big_p ? &buf[0] : &buf[3]);
316
  if ((pc & 3) == 0 && (*x & 0x80) != 0)
317
    return print_insn (cd, pc, info, buf, buflen);
318
 
319
  /* Print the first insn.  */
320
  if ((pc & 3) == 0)
321
    {
322
      buf += (big_p ? 0 : 2);
323
      if (print_insn (cd, pc, info, buf, 2) == 0)
324
        (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
325
      buf += (big_p ? 2 : -2);
326
    }
327
 
328
  x = (big_p ? &buf[0] : &buf[1]);
329
  if (*x & 0x80)
330
    {
331
      /* Parallel.  */
332
      (*info->fprintf_func) (info->stream, " || ");
333
      *x &= 0x7f;
334
    }
335
  else
336
    (*info->fprintf_func) (info->stream, " -> ");
337
 
338
  /* The "& 3" is to pass a consistent address.
339
     Parallel insns arguably both begin on the word boundary.
340
     Also, branch insns are calculated relative to the word boundary.  */
341
  if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
342
    (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
343
 
344
  return (pc & 3) ? 2 : 4;
345
}
346
 
347
/* -- */

powered by: WebSVN 2.1.0

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