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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [m32r-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 "m32r-desc.h"
35
#include "m32r-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
/* Handle '#' prefixes (i.e. skip over them).  */
51
 
52
static const char *
53
parse_hash (cd, strp, opindex, valuep)
54
     CGEN_CPU_DESC cd;
55
     const char **strp;
56
     int opindex;
57
     unsigned long *valuep;
58
{
59
  if (**strp == '#')
60
    ++*strp;
61
  return NULL;
62
}
63
 
64
/* Handle shigh(), high().  */
65
 
66
static const char *
67
parse_hi16 (cd, strp, opindex, valuep)
68
     CGEN_CPU_DESC cd;
69
     const char **strp;
70
     int opindex;
71
     unsigned long *valuep;
72
{
73
  const char *errmsg;
74
  enum cgen_parse_operand_result result_type;
75
  bfd_vma value;
76
 
77
  if (**strp == '#')
78
    ++*strp;
79
 
80
  if (strncasecmp (*strp, "high(", 5) == 0)
81
    {
82
      *strp += 5;
83
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
84
                                   &result_type, &value);
85
      if (**strp != ')')
86
        return "missing `)'";
87
      ++*strp;
88
      if (errmsg == NULL
89
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
90
        value >>= 16;
91
      *valuep = value;
92
      return errmsg;
93
    }
94
  else if (strncasecmp (*strp, "shigh(", 6) == 0)
95
    {
96
      *strp += 6;
97
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
98
                                   &result_type, &value);
99
      if (**strp != ')')
100
        return "missing `)'";
101
      ++*strp;
102
      if (errmsg == NULL
103
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
104
        value = (value >> 16) + (value & 0x8000 ? 1 : 0);
105
      *valuep = value;
106
      return errmsg;
107
    }
108
 
109
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
110
}
111
 
112
/* Handle low() in a signed context.  Also handle sda().
113
   The signedness of the value doesn't matter to low(), but this also
114
   handles the case where low() isn't present.  */
115
 
116
static const char *
117
parse_slo16 (cd, strp, opindex, valuep)
118
     CGEN_CPU_DESC cd;
119
     const char **strp;
120
     int opindex;
121
     long *valuep;
122
{
123
  const char *errmsg;
124
  enum cgen_parse_operand_result result_type;
125
  bfd_vma value;
126
 
127
  if (**strp == '#')
128
    ++*strp;
129
 
130
  if (strncasecmp (*strp, "low(", 4) == 0)
131
    {
132
      *strp += 4;
133
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
134
                                   &result_type, &value);
135
      if (**strp != ')')
136
        return "missing `)'";
137
      ++*strp;
138
      if (errmsg == NULL
139
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
140
        value &= 0xffff;
141
      *valuep = value;
142
      return errmsg;
143
    }
144
 
145
  if (strncasecmp (*strp, "sda(", 4) == 0)
146
    {
147
      *strp += 4;
148
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
149
                                   NULL, &value);
150
      if (**strp != ')')
151
        return "missing `)'";
152
      ++*strp;
153
      *valuep = value;
154
      return errmsg;
155
    }
156
 
157
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
158
}
159
 
160
/* Handle low() in an unsigned context.
161
   The signedness of the value doesn't matter to low(), but this also
162
   handles the case where low() isn't present.  */
163
 
164
static const char *
165
parse_ulo16 (cd, strp, opindex, valuep)
166
     CGEN_CPU_DESC cd;
167
     const char **strp;
168
     int opindex;
169
     unsigned long *valuep;
170
{
171
  const char *errmsg;
172
  enum cgen_parse_operand_result result_type;
173
  bfd_vma value;
174
 
175
  if (**strp == '#')
176
    ++*strp;
177
 
178
  if (strncasecmp (*strp, "low(", 4) == 0)
179
    {
180
      *strp += 4;
181
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
182
                                   &result_type, &value);
183
      if (**strp != ')')
184
        return "missing `)'";
185
      ++*strp;
186
      if (errmsg == NULL
187
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
188
        value &= 0xffff;
189
      *valuep = value;
190
      return errmsg;
191
    }
192
 
193
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
194
}
195
 
196
/* -- */
197
 
198
/* Main entry point for operand parsing.
199
 
200
   This function is basically just a big switch statement.  Earlier versions
201
   used tables to look up the function to use, but
202
   - if the table contains both assembler and disassembler functions then
203
     the disassembler contains much of the assembler and vice-versa,
204
   - there's a lot of inlining possibilities as things grow,
205
   - using a switch statement avoids the function call overhead.
206
 
207
   This function could be moved into `parse_insn_normal', but keeping it
208
   separate makes clear the interface between `parse_insn_normal' and each of
209
   the handlers.
210
*/
211
 
212
const char *
213
m32r_cgen_parse_operand (cd, opindex, strp, fields)
214
     CGEN_CPU_DESC cd;
215
     int opindex;
216
     const char ** strp;
217
     CGEN_FIELDS * fields;
218
{
219
  const char * errmsg = NULL;
220
  /* Used by scalar operands that still need to be parsed.  */
221
  long junk;
222
 
223
  switch (opindex)
224
    {
225
    case M32R_OPERAND_ACC :
226
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
227
      break;
228
    case M32R_OPERAND_ACCD :
229
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
230
      break;
231
    case M32R_OPERAND_ACCS :
232
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
233
      break;
234
    case M32R_OPERAND_DCR :
235
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r1);
236
      break;
237
    case M32R_OPERAND_DISP16 :
238
      {
239
        bfd_vma value;
240
        errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP16, 0, NULL,  & value);
241
        fields->f_disp16 = value;
242
      }
243
      break;
244
    case M32R_OPERAND_DISP24 :
245
      {
246
        bfd_vma value;
247
        errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP24, 0, NULL,  & value);
248
        fields->f_disp24 = value;
249
      }
250
      break;
251
    case M32R_OPERAND_DISP8 :
252
      {
253
        bfd_vma value;
254
        errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP8, 0, NULL,  & value);
255
        fields->f_disp8 = value;
256
      }
257
      break;
258
    case M32R_OPERAND_DR :
259
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
260
      break;
261
    case M32R_OPERAND_HASH :
262
      errmsg = parse_hash (cd, strp, M32R_OPERAND_HASH, &junk);
263
      break;
264
    case M32R_OPERAND_HI16 :
265
      errmsg = parse_hi16 (cd, strp, M32R_OPERAND_HI16, &fields->f_hi16);
266
      break;
267
    case M32R_OPERAND_IMM1 :
268
      errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_IMM1, &fields->f_imm1);
269
      break;
270
    case M32R_OPERAND_SCR :
271
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r2);
272
      break;
273
    case M32R_OPERAND_SIMM16 :
274
      errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM16, &fields->f_simm16);
275
      break;
276
    case M32R_OPERAND_SIMM8 :
277
      errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM8, &fields->f_simm8);
278
      break;
279
    case M32R_OPERAND_SLO16 :
280
      errmsg = parse_slo16 (cd, strp, M32R_OPERAND_SLO16, &fields->f_simm16);
281
      break;
282
    case M32R_OPERAND_SR :
283
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
284
      break;
285
    case M32R_OPERAND_SRC1 :
286
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
287
      break;
288
    case M32R_OPERAND_SRC2 :
289
      errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
290
      break;
291
    case M32R_OPERAND_UIMM16 :
292
      errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM16, &fields->f_uimm16);
293
      break;
294
    case M32R_OPERAND_UIMM24 :
295
      {
296
        bfd_vma value;
297
        errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_UIMM24, 0, NULL,  & value);
298
        fields->f_uimm24 = value;
299
      }
300
      break;
301
    case M32R_OPERAND_UIMM4 :
302
      errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM4, &fields->f_uimm4);
303
      break;
304
    case M32R_OPERAND_UIMM5 :
305
      errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM5, &fields->f_uimm5);
306
      break;
307
    case M32R_OPERAND_ULO16 :
308
      errmsg = parse_ulo16 (cd, strp, M32R_OPERAND_ULO16, &fields->f_uimm16);
309
      break;
310
 
311
    default :
312
      /* xgettext:c-format */
313
      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
314
      abort ();
315
  }
316
 
317
  return errmsg;
318
}
319
 
320
cgen_parse_fn * const m32r_cgen_parse_handlers[] =
321
{
322
  parse_insn_normal,
323
};
324
 
325
void
326
m32r_cgen_init_asm (cd)
327
     CGEN_CPU_DESC cd;
328
{
329
  m32r_cgen_init_opcode_table (cd);
330
  m32r_cgen_init_ibld_table (cd);
331
  cd->parse_handlers = & m32r_cgen_parse_handlers[0];
332
  cd->parse_operand = m32r_cgen_parse_operand;
333
}
334
 
335
 
336
/* Default insn parser.
337
 
338
   The syntax string is scanned and operands are parsed and stored in FIELDS.
339
   Relocs are queued as we go via other callbacks.
340
 
341
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
342
   parse the instruction, we return 0 and the caller will start over from
343
   the beginning.  Backtracking will be necessary in parsing subexpressions,
344
   but that can be handled there.  Not handling backtracking here may get
345
   expensive in the case of the m68k.  Deal with later.
346
 
347
   Returns NULL for success, an error message for failure.
348
*/
349
 
350
static const char *
351
parse_insn_normal (cd, insn, strp, fields)
352
     CGEN_CPU_DESC cd;
353
     const CGEN_INSN *insn;
354
     const char **strp;
355
     CGEN_FIELDS *fields;
356
{
357
  /* ??? Runtime added insns not handled yet.  */
358
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
359
  const char *str = *strp;
360
  const char *errmsg;
361
  const char *p;
362
  const CGEN_SYNTAX_CHAR_TYPE * syn;
363
#ifdef CGEN_MNEMONIC_OPERANDS
364
  /* FIXME: wip */
365
  int past_opcode_p;
366
#endif
367
 
368
  /* For now we assume the mnemonic is first (there are no leading operands).
369
     We can parse it without needing to set up operand parsing.
370
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
371
     not be called from GAS.  */
372
  p = CGEN_INSN_MNEMONIC (insn);
373
  while (*p && tolower (*p) == tolower (*str))
374
    ++p, ++str;
375
 
376
  if (* p)
377
    return _("unrecognized instruction");
378
 
379
#ifndef CGEN_MNEMONIC_OPERANDS
380
  if (* str && !isspace (* str))
381
    return _("unrecognized instruction");
382
#endif
383
 
384
  CGEN_INIT_PARSE (cd);
385
  cgen_init_parse_operand (cd);
386
#ifdef CGEN_MNEMONIC_OPERANDS
387
  past_opcode_p = 0;
388
#endif
389
 
390
  /* We don't check for (*str != '\0') here because we want to parse
391
     any trailing fake arguments in the syntax string.  */
392
  syn = CGEN_SYNTAX_STRING (syntax);
393
 
394
  /* Mnemonics come first for now, ensure valid string.  */
395
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
396
    abort ();
397
 
398
  ++syn;
399
 
400
  while (* syn != 0)
401
    {
402
      /* Non operand chars must match exactly.  */
403
      if (CGEN_SYNTAX_CHAR_P (* syn))
404
        {
405
          /* FIXME: While we allow for non-GAS callers above, we assume the
406
             first char after the mnemonic part is a space.  */
407
          /* FIXME: We also take inappropriate advantage of the fact that
408
             GAS's input scrubber will remove extraneous blanks.  */
409
          if (tolower (*str) == tolower (CGEN_SYNTAX_CHAR (* syn)))
410
            {
411
#ifdef CGEN_MNEMONIC_OPERANDS
412
              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
413
                past_opcode_p = 1;
414
#endif
415
              ++ syn;
416
              ++ str;
417
            }
418
          else if (*str)
419
            {
420
              /* Syntax char didn't match.  Can't be this insn.  */
421
              static char msg [80];
422
              /* xgettext:c-format */
423
              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
424
                       CGEN_SYNTAX_CHAR(*syn), *str);
425
              return msg;
426
            }
427
          else
428
            {
429
              /* Ran out of input.  */
430
              static char msg [80];
431
              /* xgettext:c-format */
432
              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
433
                       CGEN_SYNTAX_CHAR(*syn));
434
              return msg;
435
            }
436
          continue;
437
        }
438
 
439
      /* We have an operand of some sort.  */
440
      errmsg = m32r_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
441
                                          &str, fields);
442
      if (errmsg)
443
        return errmsg;
444
 
445
      /* Done with this operand, continue with next one.  */
446
      ++ syn;
447
    }
448
 
449
  /* If we're at the end of the syntax string, we're done.  */
450
  if (* syn == 0)
451
    {
452
      /* FIXME: For the moment we assume a valid `str' can only contain
453
         blanks now.  IE: We needn't try again with a longer version of
454
         the insn and it is assumed that longer versions of insns appear
455
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
456
      while (isspace (* str))
457
        ++ str;
458
 
459
      if (* str != '\0')
460
        return _("junk at end of line"); /* FIXME: would like to include `str' */
461
 
462
      return NULL;
463
    }
464
 
465
  /* We couldn't parse it.  */
466
  return _("unrecognized instruction");
467
}
468
 
469
/* Main entry point.
470
   This routine is called for each instruction to be assembled.
471
   STR points to the insn to be assembled.
472
   We assume all necessary tables have been initialized.
473
   The assembled instruction, less any fixups, is stored in BUF.
474
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
475
   still needs to be converted to target byte order, otherwise BUF is an array
476
   of bytes in target byte order.
477
   The result is a pointer to the insn's entry in the opcode table,
478
   or NULL if an error occured (an error message will have already been
479
   printed).
480
 
481
   Note that when processing (non-alias) macro-insns,
482
   this function recurses.
483
 
484
   ??? It's possible to make this cpu-independent.
485
   One would have to deal with a few minor things.
486
   At this point in time doing so would be more of a curiosity than useful
487
   [for example this file isn't _that_ big], but keeping the possibility in
488
   mind helps keep the design clean.  */
489
 
490
const CGEN_INSN *
491
m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg)
492
     CGEN_CPU_DESC cd;
493
     const char *str;
494
     CGEN_FIELDS *fields;
495
     CGEN_INSN_BYTES_PTR buf;
496
     char **errmsg;
497
{
498
  const char *start;
499
  CGEN_INSN_LIST *ilist;
500
  const char *parse_errmsg = NULL;
501
  const char *insert_errmsg = NULL;
502
 
503
  /* Skip leading white space.  */
504
  while (isspace (* str))
505
    ++ str;
506
 
507
  /* The instructions are stored in hashed lists.
508
     Get the first in the list.  */
509
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
510
 
511
  /* Keep looking until we find a match.  */
512
 
513
  start = str;
514
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
515
    {
516
      const CGEN_INSN *insn = ilist->insn;
517
 
518
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
519
      /* not usually needed as unsupported opcodes shouldn't be in the hash lists */
520
      /* Is this insn supported by the selected cpu?  */
521
      if (! m32r_cgen_insn_supported (cd, insn))
522
        continue;
523
#endif
524
 
525
      /* If the RELAX attribute is set, this is an insn that shouldn't be
526
         chosen immediately.  Instead, it is used during assembler/linker
527
         relaxation if possible.  */
528
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
529
        continue;
530
 
531
      str = start;
532
 
533
      /* Allow parse/insert handlers to obtain length of insn.  */
534
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
535
 
536
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
537
      if (parse_errmsg != NULL)
538
        continue;
539
 
540
      /* ??? 0 is passed for `pc' */
541
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
542
                                                 (bfd_vma) 0);
543
      if (insert_errmsg != NULL)
544
        continue;
545
 
546
      /* It is up to the caller to actually output the insn and any
547
         queued relocs.  */
548
      return insn;
549
    }
550
 
551
  {
552
    static char errbuf[150];
553
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
554
    const char *tmp_errmsg;
555
 
556
    /* If requesting verbose error messages, use insert_errmsg.
557
       Failing that, use parse_errmsg */
558
    tmp_errmsg = (insert_errmsg ? insert_errmsg :
559
                  parse_errmsg ? parse_errmsg :
560
                  _("unrecognized instruction"));
561
 
562
    if (strlen (start) > 50)
563
      /* xgettext:c-format */
564
      sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
565
    else
566
      /* xgettext:c-format */
567
      sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
568
#else
569
    if (strlen (start) > 50)
570
      /* xgettext:c-format */
571
      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
572
    else
573
      /* xgettext:c-format */
574
      sprintf (errbuf, _("bad instruction `%.50s'"), start);
575
#endif
576
 
577
    *errmsg = errbuf;
578
    return NULL;
579
  }
580
}
581
 
582
#if 0 /* This calls back to GAS which we can't do without care.  */
583
 
584
/* Record each member of OPVALS in the assembler's symbol table.
585
   This lets GAS parse registers for us.
586
   ??? Interesting idea but not currently used.  */
587
 
588
/* Record each member of OPVALS in the assembler's symbol table.
589
   FIXME: Not currently used.  */
590
 
591
void
592
m32r_cgen_asm_hash_keywords (cd, opvals)
593
     CGEN_CPU_DESC cd;
594
     CGEN_KEYWORD *opvals;
595
{
596
  CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
597
  const CGEN_KEYWORD_ENTRY * ke;
598
 
599
  while ((ke = cgen_keyword_search_next (& search)) != NULL)
600
    {
601
#if 0 /* Unnecessary, should be done in the search routine.  */
602
      if (! m32r_cgen_opval_supported (ke))
603
        continue;
604
#endif
605
      cgen_asm_record_register (cd, ke->name, ke->value);
606
    }
607
}
608
 
609
#endif /* 0 */

powered by: WebSVN 2.1.0

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