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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [cpu/] [epiphany.opc] - Blame information for rev 183

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

Line No. Rev Author Line
1 163 khays
/* Adapteva epiphany opcode support.  -*- C -*-
2
 
3
   Copyright 2009, 2011 Free Software Foundation, Inc.
4
 
5
   Contributed by Embecosm on behalf of Adapteva, Inc.
6
 
7
   This file is part of the GNU Binutils and of GDB.
8
 
9
   This program 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 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public 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
/*
25
   Each section is delimited with start and end markers.
26
 
27
   -opc.h additions use: "-- opc.h"
28
   -opc.c additions use: "-- opc.c"
29
   -asm.c additions use: "-- asm.c"
30
   -dis.c additions use: "-- dis.c"
31
   -ibd.h additions use: "-- ibd.h".  */
32
 
33
/* -- opc.h */
34
 
35
/* enumerate relaxation types for gas. */
36
typedef enum epiphany_relax_types
37
{
38
  EPIPHANY_RELAX_NONE=0,
39
  EPIPHANY_RELAX_NEED_RELAXING,
40
 
41
  EPIPHANY_RELAX_BRANCH_SHORT,  /* Fits into +127..-128 */
42
  EPIPHANY_RELAX_BRANCH_LONG,   /* b/bl/b +-2*16 */
43
 
44
  EPIPHANY_RELAX_ARITH_SIMM3,   /* add/sub -7..3 */
45
  EPIPHANY_RELAX_ARITH_SIMM11,  /* add/sub -2**11-1 .. 2**10-1 */
46
 
47
  EPIPHANY_RELAX_MOV_IMM8,              /* mov r,imm8 */
48
  EPIPHANY_RELAX_MOV_IMM16,     /* mov r,imm16 */
49
 
50
  EPIPHANY_RELAX_LDST_IMM3,     /* (ldr|str)* r,[r,disp3] */
51
  EPIPHANY_RELAX_LDST_IMM11     /* (ldr|str)* r,[r,disp11] */
52
 
53
} EPIPHANY_RELAX_TYPES;
54
 
55
/* Override disassembly hashing... */
56
 
57
/* Can only depend on instruction having 4 decode bits which gets us to the
58
   major groups of 16/32 instructions. */
59
#undef CGEN_DIS_HASH_SIZE
60
#if 1
61
 
62
/* hash code on the 4 LSBs */
63
#define CGEN_DIS_HASH_SIZE 16
64
 
65
#define CGEN_DIS_HASH(buf, value) ((*buf) & 0xf)
66
#else
67
#define CGEN_DIS_HASH_SIZE 1
68
#define CGEN_DIS_HASH(buf, value) 0
69
#endif
70
 
71
extern const char * parse_shortregs (CGEN_CPU_DESC cd,
72
                                     const char ** strp,
73
                                     CGEN_KEYWORD * keywords,
74
                                     long * valuep);
75
 
76
extern const char * parse_branch_addr (CGEN_CPU_DESC cd,
77
                                       const char ** strp,
78
                                       int opindex,
79
                                       int opinfo,
80
                                       enum cgen_parse_operand_result * resultp,
81
                                       bfd_vma *valuep);
82
 
83
/* Allows reason codes to be output when assembler errors occur.  */
84
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
85
 
86
 
87
/* -- opc.c */
88
 
89
 
90
 
91
/* -- asm.c */
92
const char *
93
parse_shortregs (CGEN_CPU_DESC cd,
94
                 const char ** strp,
95
                 CGEN_KEYWORD * keywords,
96
                 long * regno)
97
{
98
  const char * errmsg;
99
 
100
  /* Parse register.  */
101
  errmsg = cgen_parse_keyword (cd, strp, keywords, regno);
102
 
103
  if (errmsg)
104
    return errmsg;
105
 
106
  if (*regno > 7)
107
    errmsg = _("register unavailable for short instructions");
108
 
109
  return errmsg;
110
}
111
 
112
static const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
113
                                        long *);
114
 
115
static const char *
116
parse_uimm_not_reg (CGEN_CPU_DESC cd,
117
                    const char ** strp,
118
                    int opindex,
119
                    unsigned long * valuep)
120
{
121
  long * svalp = (void *) valuep;
122
  return parse_simm_not_reg (cd, strp, opindex, svalp);
123
}
124
 
125
/* Handle simm3/simm11/imm3/imm12.  */
126
 
127
static const char *
128
parse_simm_not_reg (CGEN_CPU_DESC cd,
129
                   const char ** strp,
130
                   int opindex,
131
                   long * valuep)
132
{
133
  const char * errmsg;
134
 
135
  int   sign = 0;
136
  int   bits = 0;
137
 
138
  switch (opindex)
139
    {
140
    case EPIPHANY_OPERAND_SIMM3:
141
      sign = 1; bits = 3; break;
142
    case EPIPHANY_OPERAND_SIMM11:
143
      sign = 1; bits = 11; break;
144
    case EPIPHANY_OPERAND_DISP3:
145
      sign = 0; bits = 3; break;
146
    case EPIPHANY_OPERAND_DISP11:
147
      /* Load/store displacement is a sign-magnitude 12 bit value.  */
148
      sign = 0; bits = 11; break;
149
    }
150
 
151
  /* First try to parse as a register name and reject the operand.  */
152
  errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep);
153
  if (!errmsg)
154
    return _("register name used as immediate value");
155
 
156
  errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep)
157
            : cgen_parse_unsigned_integer (cd, strp, opindex,
158
                                          (unsigned long *) valuep));
159
  if (errmsg)
160
    return errmsg;
161
 
162
  if (sign)
163
    errmsg = cgen_validate_signed_integer (*valuep,
164
                                          -((1L << bits) - 1), (1 << (bits - 1)) - 1);
165
  else
166
    errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1);
167
 
168
  return errmsg;
169
}
170
 
171
static const char *
172
parse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
173
                 const char ** strp,
174
                 int opindex ATTRIBUTE_UNUSED,
175
                 unsigned long *valuep)
176
{
177
  if (**strp == '#')
178
    ++*strp;                    /* Skip leading hashes.  */
179
 
180
  if (**strp == '-')
181
    {
182
      *valuep = 1;
183
      ++*strp;
184
    }
185
  else if (**strp == '+')
186
    {
187
      *valuep = 0;
188
      ++*strp;
189
    }
190
  else
191
    *valuep = 0;
192
 
193
  return NULL;
194
}
195
 
196
static const char *
197
parse_imm8 (CGEN_CPU_DESC cd,
198
            const char ** strp,
199
            int opindex,
200
            bfd_reloc_code_real_type code,
201
            enum cgen_parse_operand_result * result_type,
202
            bfd_vma * valuep)
203
{
204
  const char * errmsg;
205
  enum cgen_parse_operand_result rt;
206
  long dummyval;
207
 
208
  if (!result_type)
209
    result_type = &rt;
210
 
211
  code = BFD_RELOC_NONE;
212
 
213
  if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval)
214
      || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
215
                              &dummyval))
216
    /* Don't treat "mov ip,ip" as a move-immediate.  */
217
    return _("register source in immediate move");
218
 
219
  errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep);
220
  if (errmsg)
221
    return errmsg;
222
 
223
  if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
224
    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff);
225
  else
226
    errmsg = _("byte relocation unsupported");
227
 
228
  *valuep &= 0xff;
229
  return errmsg;
230
}
231
 
232
static const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
233
 
234
static const char *
235
parse_imm16 (CGEN_CPU_DESC cd,
236
             const char ** strp,
237
             int opindex,
238
             bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,
239
             enum cgen_parse_operand_result * result_type,
240
             bfd_vma * valuep)
241
{
242
  const char * errmsg;
243
  enum cgen_parse_operand_result rt;
244
  long dummyval;
245
 
246
  if (!result_type)
247
    result_type = &rt;
248
 
249
  if (strncasecmp (*strp, "%high(", 6) == 0)
250
    {
251
      *strp += 6;
252
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH,
253
                                   result_type, valuep);
254
      if (**strp != ')')
255
        return MISSING_CLOSE_PARENTHESIS;
256
      ++*strp;
257
      *valuep >>= 16;
258
    }
259
  else if (strncasecmp (*strp, "%low(", 5) == 0)
260
    {
261
      *strp += 5;
262
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW,
263
                                   result_type, valuep);
264
      if (**strp != ')')
265
        return MISSING_CLOSE_PARENTHESIS;
266
      ++*strp;
267
    }
268
  else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names,
269
                                &dummyval)
270
           || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
271
                                   &dummyval))
272
    /* Don't treat "mov ip,ip" as a move-immediate.  */
273
    return _("register source in immediate move");
274
  else
275
    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
276
                                 result_type, valuep);
277
 
278
  if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
279
    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff);
280
 
281
  *valuep &= 0xffff;
282
  return errmsg;
283
}
284
 
285
const char *
286
parse_branch_addr (CGEN_CPU_DESC cd,
287
                   const char ** strp,
288
                   int opindex,
289
                   int opinfo ATTRIBUTE_UNUSED,
290
                   enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,
291
                   bfd_vma *valuep ATTRIBUTE_UNUSED)
292
{
293
  const char * errmsg;
294
  enum cgen_parse_operand_result result_type;
295
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
296
  bfd_vma value;
297
 
298
  switch (opindex)
299
    {
300
    case EPIPHANY_OPERAND_SIMM24:
301
      code = BFD_RELOC_EPIPHANY_SIMM24;
302
      break;
303
 
304
    case EPIPHANY_OPERAND_SIMM8:
305
      code = BFD_RELOC_EPIPHANY_SIMM8;
306
      break;
307
 
308
    default:
309
      errmsg = _("ABORT: unknown operand");
310
      return errmsg;
311
    }
312
 
313
  errmsg = cgen_parse_address (cd, strp, opindex, code,
314
                               &result_type, &value);
315
  if (errmsg == NULL)
316
    {
317
      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
318
        {
319
          /* Act as if we had done a PC-relative branch, ala .+num.  */
320
          char buf[20];
321
          const char * bufp = (const char *) buf;
322
 
323
          sprintf (buf, ".+%ld", (long) value);
324
          errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type,
325
                                       &value);
326
        }
327
 
328
      if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
329
        {
330
          /* This will happen for things like (s2-s1) where s2 and s1
331
             are labels.  */
332
          /* Nothing further to be done.  */
333
        }
334
      else
335
        errmsg = _("Not a pc-relative address.");
336
    }
337
  return errmsg;
338
}
339
 
340
/* -- dis.c */
341
 
342
#define CGEN_PRINT_INSN epiphany_print_insn
343
 
344
static int
345
epiphany_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
346
{
347
  bfd_byte buf[CGEN_MAX_INSN_SIZE];
348
  int buflen;
349
  int status;
350
 
351
  info->bytes_per_chunk = 2;
352
 
353
  /* Attempt to read the base part of the insn.  */
354
  info->bytes_per_line = buflen = cd->base_insn_bitsize / 8;
355
  status = (*info->read_memory_func) (pc, buf, buflen, info);
356
 
357
  /* Try again with the minimum part, if min < base.  */
358
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
359
    {
360
      info->bytes_per_line = buflen = cd->min_insn_bitsize / 8;
361
      status = (*info->read_memory_func) (pc, buf, buflen, info);
362
    }
363
 
364
  if (status != 0)
365
    {
366
      (*info->memory_error_func) (status, pc, info);
367
      return -1;
368
    }
369
 
370
  return print_insn (cd, pc, info, buf, buflen);
371
}
372
 
373
 
374
static void
375
print_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
376
                 void * dis_info,
377
                 long value,
378
                 unsigned int attrs ATTRIBUTE_UNUSED,
379
                 bfd_vma pc ATTRIBUTE_UNUSED,
380
                 int length ATTRIBUTE_UNUSED)
381
{
382
  disassemble_info *info = (disassemble_info *) dis_info;
383
  (*info->fprintf_func) (info->stream, value ? "-" : "+");
384
}
385
 
386
static void
387
print_simm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
388
                    void * dis_info,
389
                    long value,
390
                    unsigned int attrs ATTRIBUTE_UNUSED,
391
                    bfd_vma pc ATTRIBUTE_UNUSED,
392
                    int length ATTRIBUTE_UNUSED)
393
{
394
  print_address (cd, dis_info, value, attrs, pc, length);
395
}
396
 
397
static void
398
print_uimm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
399
                    void * dis_info,
400
                    unsigned long value,
401
                    unsigned int attrs ATTRIBUTE_UNUSED,
402
                    bfd_vma pc ATTRIBUTE_UNUSED,
403
                    int length ATTRIBUTE_UNUSED)
404
{
405
  disassemble_info *info = (disassemble_info *)dis_info;
406
 
407
  if (value & 0x800)
408
    (*info->fprintf_func) (info->stream, "-");
409
 
410
  value &= 0x7ff;
411
  print_address (cd, dis_info, value, attrs, pc, length);
412
}
413
 
414
 
415
/* -- */
416
 

powered by: WebSVN 2.1.0

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