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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [openrisc-asm.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Assembler interface for targets using CGEN. -*- C -*-
2
   CGEN: Cpu tools GENerator
3
 
4
THIS FILE IS MACHINE GENERATED WITH CGEN.
5
- the resultant file is machine generated, cgen-asm.in isn't
6
 
7
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
 
9
This file is part of the GNU Binutils and GDB, the GNU debugger.
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 2, or (at your option)
14
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 Foundation, Inc.,
23
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24
 
25
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26
   Keep that in mind.  */
27
 
28
#include "sysdep.h"
29
#include <ctype.h>
30
#include <stdio.h>
31
#include "ansidecl.h"
32
#include "bfd.h"
33
#include "symcat.h"
34
#include "openrisc-desc.h"
35
#include "openrisc-opc.h"
36
#include "opintl.h"
37
 
38
#undef min
39
#define min(a,b) ((a) < (b) ? (a) : (b))
40
#undef max
41
#define max(a,b) ((a) > (b) ? (a) : (b))
42
 
43
static const char * parse_insn_normal
44
     PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
45
 
46
/* -- assembler routines inserted here */
47
 
48
/* -- asm.c */
49
 
50
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
51
 
52
long
53
openrisc_sign_extend_16bit (value)
54
     long value;
55
{
56
  return (long) (short) value;
57
}
58
 
59
 
60
/* Handle hi().  */
61
 
62
static const char *
63
parse_hi16 (cd, strp, opindex, valuep)
64
     CGEN_CPU_DESC cd;
65
     const char **strp;
66
     int opindex;
67
     unsigned long *valuep;
68
{
69
  const char *errmsg;
70
  enum cgen_parse_operand_result result_type;
71
  bfd_vma value;
72
 
73
  if (**strp == '#')
74
    ++*strp;
75
 
76
  if (strncasecmp (*strp, "hi(", 3) == 0)
77
    {
78
      *strp += 3;
79
 
80
#if 0
81
      errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
82
      if (errmsg != NULL)
83
        fprintf (stderr, "parse_hi: %s\n", errmsg);
84
      if (errmsg != NULL)
85
#endif
86
        errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
87
                                     &result_type, &value);
88
      if (**strp != ')')
89
        return "missing `)'";
90
      ++*strp;
91
      if (errmsg == NULL
92
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
93
        value >>= 16;
94
      *valuep = (long) (short) value;
95
 
96
      return errmsg;
97
    }
98
  else
99
    {
100
      if (**strp == '-')
101
        errmsg = cgen_parse_signed_integer (cd, strp, opindex, (long *) &value);
102
      else
103
        errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, &value);
104
    }
105
  *valuep = (long) (short) (value & 0xffff);
106
  return errmsg;
107
}
108
 
109
 
110
/* Handle lo() */
111
 
112
static const char *
113
parse_lo16 (cd, strp, opindex, valuep)
114
     CGEN_CPU_DESC cd;
115
     const char **strp;
116
     int opindex;
117
     unsigned long *valuep;
118
{
119
  const char *errmsg;
120
  enum cgen_parse_operand_result result_type;
121
  bfd_vma value;
122
 
123
  if (**strp == '#')
124
    ++*strp;
125
 
126
  if (strncasecmp (*strp, "lo(", 3) == 0)
127
    {
128
      *strp += 3;
129
 
130
#if 0 
131
      errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
132
      if (errmsg != NULL)
133
        fprintf (stderr, "parse_lo: %s\n", errmsg);
134
 
135
      if (errmsg != NULL)
136
#endif
137
        errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
138
                                     &result_type, &value);
139
      if (**strp != ')')
140
        return "missing `)'";
141
      ++*strp;
142
      if (errmsg == NULL
143
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
144
        value &= 0xffff;
145
      *valuep = (long) (short) value;
146
 
147
      return errmsg;
148
    }
149
 
150
  if (**strp == '-')
151
    errmsg = cgen_parse_signed_integer (cd, strp, opindex, (long *) &value);
152
  else
153
    errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, &value);
154
  *valuep = (long) (short) (value & 0xffff);
155
  return errmsg;
156
}
157
 
158
/* -- */
159
 
160
/* Main entry point for operand parsing.
161
 
162
   This function is basically just a big switch statement.  Earlier versions
163
   used tables to look up the function to use, but
164
   - if the table contains both assembler and disassembler functions then
165
     the disassembler contains much of the assembler and vice-versa,
166
   - there's a lot of inlining possibilities as things grow,
167
   - using a switch statement avoids the function call overhead.
168
 
169
   This function could be moved into `parse_insn_normal', but keeping it
170
   separate makes clear the interface between `parse_insn_normal' and each of
171
   the handlers.
172
*/
173
 
174
const char *
175
openrisc_cgen_parse_operand (cd, opindex, strp, fields)
176
     CGEN_CPU_DESC cd;
177
     int opindex;
178
     const char ** strp;
179
     CGEN_FIELDS * fields;
180
{
181
  const char * errmsg = NULL;
182
  /* Used by scalar operands that still need to be parsed.  */
183
  long junk;
184
 
185
  switch (opindex)
186
    {
187
    case OPENRISC_OPERAND_ABS_26 :
188
      {
189
        bfd_vma value;
190
        errmsg = cgen_parse_address (cd, strp, OPENRISC_OPERAND_ABS_26, 0, NULL,  & value);
191
        fields->f_abs26 = value;
192
      }
193
      break;
194
    case OPENRISC_OPERAND_DISP_26 :
195
      {
196
        bfd_vma value;
197
        errmsg = cgen_parse_address (cd, strp, OPENRISC_OPERAND_DISP_26, 0, NULL,  & value);
198
        fields->f_disp26 = value;
199
      }
200
      break;
201
    case OPENRISC_OPERAND_HI16 :
202
      errmsg = parse_hi16 (cd, strp, OPENRISC_OPERAND_HI16, &fields->f_simm16);
203
      break;
204
    case OPENRISC_OPERAND_LO16 :
205
      errmsg = parse_lo16 (cd, strp, OPENRISC_OPERAND_LO16, &fields->f_lo16);
206
      break;
207
    case OPENRISC_OPERAND_OP_F_23 :
208
      errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_OP_F_23, &fields->f_op4);
209
      break;
210
    case OPENRISC_OPERAND_OP_F_3 :
211
      errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_OP_F_3, &fields->f_op5);
212
      break;
213
    case OPENRISC_OPERAND_RA :
214
      errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r2);
215
      break;
216
    case OPENRISC_OPERAND_RB :
217
      errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r3);
218
      break;
219
    case OPENRISC_OPERAND_RD :
220
      errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r1);
221
      break;
222
    case OPENRISC_OPERAND_SIMM_16 :
223
      errmsg = cgen_parse_signed_integer (cd, strp, OPENRISC_OPERAND_SIMM_16, &fields->f_simm16);
224
      break;
225
    case OPENRISC_OPERAND_UI16NC :
226
      errmsg = parse_lo16 (cd, strp, OPENRISC_OPERAND_UI16NC, &fields->f_i16nc);
227
      break;
228
    case OPENRISC_OPERAND_UIMM_16 :
229
      errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_UIMM_16, &fields->f_uimm16);
230
      break;
231
    case OPENRISC_OPERAND_UIMM_5 :
232
      errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_UIMM_5, &fields->f_uimm5);
233
      break;
234
 
235
    default :
236
      /* xgettext:c-format */
237
      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
238
      abort ();
239
  }
240
 
241
  return errmsg;
242
}
243
 
244
cgen_parse_fn * const openrisc_cgen_parse_handlers[] =
245
{
246
  parse_insn_normal,
247
};
248
 
249
void
250
openrisc_cgen_init_asm (cd)
251
     CGEN_CPU_DESC cd;
252
{
253
  openrisc_cgen_init_opcode_table (cd);
254
  openrisc_cgen_init_ibld_table (cd);
255
  cd->parse_handlers = & openrisc_cgen_parse_handlers[0];
256
  cd->parse_operand = openrisc_cgen_parse_operand;
257
}
258
 
259
 
260
/* Default insn parser.
261
 
262
   The syntax string is scanned and operands are parsed and stored in FIELDS.
263
   Relocs are queued as we go via other callbacks.
264
 
265
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
266
   parse the instruction, we return 0 and the caller will start over from
267
   the beginning.  Backtracking will be necessary in parsing subexpressions,
268
   but that can be handled there.  Not handling backtracking here may get
269
   expensive in the case of the m68k.  Deal with later.
270
 
271
   Returns NULL for success, an error message for failure.
272
*/
273
 
274
static const char *
275
parse_insn_normal (cd, insn, strp, fields)
276
     CGEN_CPU_DESC cd;
277
     const CGEN_INSN *insn;
278
     const char **strp;
279
     CGEN_FIELDS *fields;
280
{
281
  /* ??? Runtime added insns not handled yet.  */
282
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
283
  const char *str = *strp;
284
  const char *errmsg;
285
  const char *p;
286
  const CGEN_SYNTAX_CHAR_TYPE * syn;
287
#ifdef CGEN_MNEMONIC_OPERANDS
288
  /* FIXME: wip */
289
  int past_opcode_p;
290
#endif
291
 
292
  /* For now we assume the mnemonic is first (there are no leading operands).
293
     We can parse it without needing to set up operand parsing.
294
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
295
     not be called from GAS.  */
296
  p = CGEN_INSN_MNEMONIC (insn);
297
  while (*p && tolower (*p) == tolower (*str))
298
    ++p, ++str;
299
 
300
  if (* p)
301
    return _("unrecognized instruction");
302
 
303
#ifndef CGEN_MNEMONIC_OPERANDS
304
  if (* str && !isspace (* str))
305
    return _("unrecognized instruction");
306
#endif
307
 
308
  CGEN_INIT_PARSE (cd);
309
  cgen_init_parse_operand (cd);
310
#ifdef CGEN_MNEMONIC_OPERANDS
311
  past_opcode_p = 0;
312
#endif
313
 
314
  /* We don't check for (*str != '\0') here because we want to parse
315
     any trailing fake arguments in the syntax string.  */
316
  syn = CGEN_SYNTAX_STRING (syntax);
317
 
318
  /* Mnemonics come first for now, ensure valid string.  */
319
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
320
    abort ();
321
 
322
  ++syn;
323
 
324
  while (* syn != 0)
325
    {
326
      /* Non operand chars must match exactly.  */
327
      if (CGEN_SYNTAX_CHAR_P (* syn))
328
        {
329
          /* FIXME: While we allow for non-GAS callers above, we assume the
330
             first char after the mnemonic part is a space.  */
331
          /* FIXME: We also take inappropriate advantage of the fact that
332
             GAS's input scrubber will remove extraneous blanks.  */
333
          if (tolower (*str) == tolower (CGEN_SYNTAX_CHAR (* syn)))
334
            {
335
#ifdef CGEN_MNEMONIC_OPERANDS
336
              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
337
                past_opcode_p = 1;
338
#endif
339
              ++ syn;
340
              ++ str;
341
            }
342
          else if (*str)
343
            {
344
              /* Syntax char didn't match.  Can't be this insn.  */
345
              static char msg [80];
346
              /* xgettext:c-format */
347
              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
348
                       CGEN_SYNTAX_CHAR(*syn), *str);
349
              return msg;
350
            }
351
          else
352
            {
353
              /* Ran out of input.  */
354
              static char msg [80];
355
              /* xgettext:c-format */
356
              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
357
                       CGEN_SYNTAX_CHAR(*syn));
358
              return msg;
359
            }
360
          continue;
361
        }
362
 
363
      /* We have an operand of some sort.  */
364
      errmsg = openrisc_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
365
                                          &str, fields);
366
      if (errmsg)
367
        return errmsg;
368
 
369
      /* Done with this operand, continue with next one.  */
370
      ++ syn;
371
    }
372
 
373
  /* If we're at the end of the syntax string, we're done.  */
374
  if (* syn == 0)
375
    {
376
      /* FIXME: For the moment we assume a valid `str' can only contain
377
         blanks now.  IE: We needn't try again with a longer version of
378
         the insn and it is assumed that longer versions of insns appear
379
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
380
      while (isspace (* str))
381
        ++ str;
382
 
383
      if (* str != '\0')
384
        return _("junk at end of line"); /* FIXME: would like to include `str' */
385
 
386
      return NULL;
387
    }
388
 
389
  /* We couldn't parse it.  */
390
  return _("unrecognized instruction");
391
}
392
 
393
/* Main entry point.
394
   This routine is called for each instruction to be assembled.
395
   STR points to the insn to be assembled.
396
   We assume all necessary tables have been initialized.
397
   The assembled instruction, less any fixups, is stored in BUF.
398
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
399
   still needs to be converted to target byte order, otherwise BUF is an array
400
   of bytes in target byte order.
401
   The result is a pointer to the insn's entry in the opcode table,
402
   or NULL if an error occured (an error message will have already been
403
   printed).
404
 
405
   Note that when processing (non-alias) macro-insns,
406
   this function recurses.
407
 
408
   ??? It's possible to make this cpu-independent.
409
   One would have to deal with a few minor things.
410
   At this point in time doing so would be more of a curiosity than useful
411
   [for example this file isn't _that_ big], but keeping the possibility in
412
   mind helps keep the design clean.  */
413
 
414
const CGEN_INSN *
415
openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg)
416
     CGEN_CPU_DESC cd;
417
     const char *str;
418
     CGEN_FIELDS *fields;
419
     CGEN_INSN_BYTES_PTR buf;
420
     char **errmsg;
421
{
422
  const char *start;
423
  CGEN_INSN_LIST *ilist;
424
  const char *parse_errmsg = NULL;
425
  const char *insert_errmsg = NULL;
426
 
427
  /* Skip leading white space.  */
428
  while (isspace (* str))
429
    ++ str;
430
 
431
  /* The instructions are stored in hashed lists.
432
     Get the first in the list.  */
433
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
434
 
435
  /* Keep looking until we find a match.  */
436
 
437
  start = str;
438
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
439
    {
440
      const CGEN_INSN *insn = ilist->insn;
441
 
442
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
443
      /* not usually needed as unsupported opcodes shouldn't be in the hash lists */
444
      /* Is this insn supported by the selected cpu?  */
445
      if (! openrisc_cgen_insn_supported (cd, insn))
446
        continue;
447
#endif
448
 
449
      /* If the RELAX attribute is set, this is an insn that shouldn't be
450
         chosen immediately.  Instead, it is used during assembler/linker
451
         relaxation if possible.  */
452
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
453
        continue;
454
 
455
      str = start;
456
 
457
      /* Allow parse/insert handlers to obtain length of insn.  */
458
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
459
 
460
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
461
      if (parse_errmsg != NULL)
462
        continue;
463
 
464
      /* ??? 0 is passed for `pc' */
465
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
466
                                                 (bfd_vma) 0);
467
      if (insert_errmsg != NULL)
468
        continue;
469
 
470
      /* It is up to the caller to actually output the insn and any
471
         queued relocs.  */
472
      return insn;
473
    }
474
 
475
  {
476
    static char errbuf[150];
477
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
478
    const char *tmp_errmsg;
479
 
480
    /* If requesting verbose error messages, use insert_errmsg.
481
       Failing that, use parse_errmsg */
482
    tmp_errmsg = (insert_errmsg ? insert_errmsg :
483
                  parse_errmsg ? parse_errmsg :
484
                  _("unrecognized instruction"));
485
 
486
    if (strlen (start) > 50)
487
      /* xgettext:c-format */
488
      sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
489
    else
490
      /* xgettext:c-format */
491
      sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
492
#else
493
    if (strlen (start) > 50)
494
      /* xgettext:c-format */
495
      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
496
    else
497
      /* xgettext:c-format */
498
      sprintf (errbuf, _("bad instruction `%.50s'"), start);
499
#endif
500
 
501
    *errmsg = errbuf;
502
    return NULL;
503
  }
504
}
505
 
506
#if 0 /* This calls back to GAS which we can't do without care.  */
507
 
508
/* Record each member of OPVALS in the assembler's symbol table.
509
   This lets GAS parse registers for us.
510
   ??? Interesting idea but not currently used.  */
511
 
512
/* Record each member of OPVALS in the assembler's symbol table.
513
   FIXME: Not currently used.  */
514
 
515
void
516
openrisc_cgen_asm_hash_keywords (cd, opvals)
517
     CGEN_CPU_DESC cd;
518
     CGEN_KEYWORD *opvals;
519
{
520
  CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
521
  const CGEN_KEYWORD_ENTRY * ke;
522
 
523
  while ((ke = cgen_keyword_search_next (& search)) != NULL)
524
    {
525
#if 0 /* Unnecessary, should be done in the search routine.  */
526
      if (! openrisc_cgen_opval_supported (ke))
527
        continue;
528
#endif
529
      cgen_asm_record_register (cd, ke->name, ke->value);
530
    }
531
}
532
 
533
#endif /* 0 */

powered by: WebSVN 2.1.0

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