~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to opcodes/ip2k-asm.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 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 <stdio.h>
 
30
#include "ansidecl.h"
 
31
#include "bfd.h"
 
32
#include "symcat.h"
 
33
#include "ip2k-desc.h"
 
34
#include "ip2k-opc.h"
 
35
#include "opintl.h"
 
36
#include "xregex.h"
 
37
#include "libiberty.h"
 
38
#include "safe-ctype.h"
 
39
 
 
40
#undef  min
 
41
#define min(a,b) ((a) < (b) ? (a) : (b))
 
42
#undef  max
 
43
#define max(a,b) ((a) > (b) ? (a) : (b))
 
44
 
 
45
static const char * parse_insn_normal
 
46
  (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
 
47
 
 
48
/* -- assembler routines inserted here.  */
 
49
 
 
50
/* -- asm.c */
 
51
 
 
52
#define PARSE_FUNC_DECL(name) \
 
53
static const char *name PARAMS ((CGEN_CPU_DESC, const char **, int, long *))
 
54
 
 
55
PARSE_FUNC_DECL (parse_fr);
 
56
PARSE_FUNC_DECL (parse_addr16);
 
57
PARSE_FUNC_DECL (parse_addr16_p);
 
58
PARSE_FUNC_DECL (parse_addr16_cjp);
 
59
PARSE_FUNC_DECL (parse_lit8);
 
60
PARSE_FUNC_DECL (parse_bit3);
 
61
 
 
62
 
 
63
static const char *
 
64
parse_fr (cd, strp, opindex, valuep)
 
65
     CGEN_CPU_DESC cd;
 
66
     const char **strp;
 
67
     int opindex;
 
68
     long *valuep;
 
69
{
 
70
  const char *errmsg;
 
71
  const char *old_strp;
 
72
  char *afteroffset; 
 
73
  enum cgen_parse_operand_result result_type;
 
74
  bfd_vma value;
 
75
  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
 
76
  bfd_vma tempvalue;
 
77
 
 
78
  old_strp = *strp;
 
79
  afteroffset = NULL; 
 
80
 
 
81
 
 
82
  /* Check here to see if you're about to try parsing a w as the first arg */
 
83
  /* and return an error if you are.                                       */
 
84
  if ( (strncmp(*strp,"w",1)==0) || (strncmp(*strp,"W",1)==0) )
 
85
    {
 
86
      (*strp)++;
 
87
 
 
88
      if ( (strncmp(*strp,",",1)==0) || ISSPACE(**strp) )
 
89
        {
 
90
          /* We've been passed a w.  Return with an error message so that  */
 
91
          /* cgen will try the next parsing option.                        */
 
92
          errmsg = _("W keyword invalid in FR operand slot.");
 
93
          return errmsg;
 
94
        }
 
95
      *strp = old_strp;
 
96
    }
 
97
 
 
98
 
 
99
  /* Attempt parse as register keyword. */
 
100
  /* old_strp = *strp; */
 
101
 
 
102
  errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names,
 
103
                               valuep);
 
104
  if ( *strp != NULL )
 
105
    if (errmsg == NULL)
 
106
      return errmsg;
 
107
 
 
108
  /* Attempt to parse for "(IP)" */
 
109
  afteroffset = strstr(*strp,"(IP)");
 
110
 
 
111
  if ( afteroffset == NULL)
 
112
    {
 
113
      /* Make sure it's not in lower case */
 
114
      afteroffset = strstr(*strp,"(ip)");
 
115
    }
 
116
 
 
117
  if ( afteroffset != NULL )
 
118
    {
 
119
      if ( afteroffset != *strp )
 
120
        {
 
121
          /* Invalid offset present.*/
 
122
          errmsg = _("offset(IP) is not a valid form");
 
123
          return errmsg;
 
124
        }
 
125
      else
 
126
        {
 
127
          *strp += 4; 
 
128
          *valuep = 0;
 
129
          errmsg = NULL;
 
130
          return errmsg;
 
131
        }
 
132
    }
 
133
 
 
134
  /* Attempt to parse for DP. ex: mov w, offset(DP)  */
 
135
  /*                              mov offset(DP),w   */
 
136
 
 
137
  /* Try parsing it as an address and see what comes back */
 
138
 
 
139
  afteroffset = strstr(*strp,"(DP)");
 
140
 
 
141
  if ( afteroffset == NULL)
 
142
    {
 
143
      /* Maybe it's in lower case */
 
144
      afteroffset = strstr(*strp,"(dp)");
 
145
    }
 
146
 
 
147
  if ( afteroffset != NULL )
 
148
    {
 
149
      if ( afteroffset == *strp )
 
150
        {
 
151
          /* No offset present. Use 0 by default. */
 
152
          tempvalue = 0;
 
153
          errmsg = NULL;
 
154
        }
 
155
      else
 
156
        {
 
157
          errmsg = cgen_parse_address (cd, strp, opindex,
 
158
                                       BFD_RELOC_IP2K_FR_OFFSET,
 
159
                                       & result_type, & tempvalue);
 
160
        }
 
161
 
 
162
      if (errmsg == NULL)
 
163
        {
 
164
          if (tempvalue <= 127)
 
165
            {
 
166
              /* Value is ok.  Fix up the first 2 bits and return */       
 
167
              *valuep = 0x0100 | tempvalue;
 
168
              *strp += 4; /* skip over the (DP) in *strp */
 
169
              return errmsg;
 
170
            }
 
171
          else
 
172
            {
 
173
              /* Found something there in front of (DP) but it's out
 
174
                 of range. */
 
175
              errmsg = _("(DP) offset out of range.");
 
176
              return errmsg;
 
177
            }
 
178
        }
 
179
    }
 
180
 
 
181
 
 
182
  /* Attempt to parse for SP. ex: mov w, offset(SP)  */
 
183
  /*                              mov offset(SP), w  */
 
184
 
 
185
 
 
186
  afteroffset = strstr(*strp,"(SP)");
 
187
 
 
188
  if (afteroffset == NULL)
 
189
    {
 
190
      /* Maybe it's in lower case. */
 
191
      afteroffset = strstr(*strp, "(sp)");
 
192
    }
 
193
 
 
194
  if ( afteroffset != NULL )
 
195
    {
 
196
      if ( afteroffset ==  *strp )
 
197
        {
 
198
          /* No offset present. Use 0 by default. */
 
199
          tempvalue = 0;
 
200
          errmsg = NULL;
 
201
        }
 
202
      else
 
203
        {
 
204
          errmsg = cgen_parse_address (cd, strp, opindex,
 
205
                                       BFD_RELOC_IP2K_FR_OFFSET,
 
206
                                       & result_type, & tempvalue);
 
207
        }
 
208
      if (errmsg == NULL)
 
209
        {
 
210
          if (tempvalue <= 127)
 
211
            {
 
212
              /* Value is ok.  Fix up the first 2 bits and return */
 
213
              *valuep = 0x0180 | tempvalue;
 
214
              *strp += 4; /* skip over the (SP) in *strp */
 
215
              return errmsg;
 
216
            }
 
217
          else
 
218
            {
 
219
              /* Found something there in front of (SP) but it's out
 
220
                 of range. */
 
221
              errmsg = _("(SP) offset out of range.");
 
222
              return errmsg;
 
223
            }
 
224
        
 
225
        }
 
226
    }
 
227
 
 
228
 
 
229
  /* Attempt to parse as an address. */
 
230
  *strp = old_strp;
 
231
  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
 
232
                               & result_type, & value);
 
233
  if (errmsg == NULL)
 
234
    {
 
235
      *valuep = value;
 
236
 
 
237
      /* if a parenthesis is found, warn about invalid form */
 
238
 
 
239
      if (**strp == '(')
 
240
        {
 
241
          errmsg = _("illegal use of parentheses");
 
242
        }
 
243
      /* if a numeric value is specified, ensure that it is between
 
244
         1 and 255 */
 
245
      else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
 
246
        {
 
247
          if (value < 0x1 || value > 0xff)
 
248
            errmsg = _("operand out of range (not between 1 and 255)");
 
249
        }
 
250
    }
 
251
  return errmsg;
 
252
}
 
253
 
 
254
static const char *
 
255
parse_addr16 (cd, strp, opindex, valuep)
 
256
     CGEN_CPU_DESC cd;
 
257
     const char **strp;
 
258
     int opindex;
 
259
     long *valuep;
 
260
{
 
261
  const char *errmsg;
 
262
  enum cgen_parse_operand_result result_type;
 
263
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
 
264
  bfd_vma value;
 
265
 
 
266
  if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16H )
 
267
    code = BFD_RELOC_IP2K_HI8DATA;
 
268
  else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16L )
 
269
    code = BFD_RELOC_IP2K_LO8DATA;
 
270
  else
 
271
    {
 
272
      /* Something is very wrong. opindex has to be one of the above. */
 
273
      errmsg = _("parse_addr16: invalid opindex.");
 
274
      return errmsg;
 
275
    }
 
276
  
 
277
  errmsg = cgen_parse_address (cd, strp, opindex, code,
 
278
                               & result_type, & value);
 
279
  if (errmsg == NULL)
 
280
    {
 
281
      /* We either have a relocation or a number now. */
 
282
      if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
 
283
        {
 
284
          /* We got a number back. */
 
285
          if ( code == BFD_RELOC_IP2K_HI8DATA )
 
286
            value >>= 8;
 
287
          else    /* code = BFD_RELOC_IP2K_LOW8DATA */
 
288
            value &= 0x00FF;
 
289
        }   
 
290
      *valuep = value;
 
291
    }
 
292
 
 
293
  return errmsg;
 
294
}
 
295
 
 
296
 
 
297
static const char *
 
298
parse_addr16_p (cd, strp, opindex, valuep)
 
299
     CGEN_CPU_DESC cd;
 
300
     const char **strp;
 
301
     int opindex;
 
302
     long *valuep;
 
303
{
 
304
  const char *errmsg;
 
305
  enum cgen_parse_operand_result result_type;
 
306
  bfd_reloc_code_real_type code = BFD_RELOC_IP2K_PAGE3;
 
307
  bfd_vma value;
 
308
 
 
309
  errmsg = cgen_parse_address (cd, strp, opindex, code,
 
310
                               & result_type, & value);
 
311
  if (errmsg == NULL)
 
312
    {
 
313
      if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
 
314
        *valuep = (value >> 13) & 0x7;
 
315
      else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
 
316
        *valuep = value;
 
317
    }
 
318
  return errmsg; 
 
319
}
 
320
 
 
321
 
 
322
static const char *
 
323
parse_addr16_cjp (cd, strp, opindex, valuep)
 
324
     CGEN_CPU_DESC cd;
 
325
     const char **strp;
 
326
     int opindex;
 
327
     long *valuep;
 
328
{
 
329
  const char *errmsg;
 
330
  enum cgen_parse_operand_result result_type;
 
331
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
 
332
  bfd_vma value;
 
333
 
 
334
  if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
 
335
    code = BFD_RELOC_IP2K_ADDR16CJP;
 
336
  else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
 
337
    code = BFD_RELOC_IP2K_PAGE3;
 
338
 
 
339
  errmsg = cgen_parse_address (cd, strp, opindex, code,
 
340
                               & result_type, & value);
 
341
  if (errmsg == NULL)
 
342
    {
 
343
      if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
 
344
        {
 
345
          if ( (value & 0x1) == 0)  /* If the address is even .... */
 
346
            {
 
347
              if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
 
348
                *valuep = (value >> 1) & 0x1FFF;  /* Should mask be 1FFF? */
 
349
              else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
 
350
                *valuep = (value >> 14) & 0x7;
 
351
            }
 
352
          else
 
353
            errmsg = _("Byte address required. - must be even.");
 
354
        }
 
355
      else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
 
356
        {
 
357
          /* This will happen for things like (s2-s1) where s2 and s1
 
358
             are labels.  */
 
359
          *valuep = value;
 
360
        }
 
361
      else 
 
362
        errmsg = _("cgen_parse_address returned a symbol. Literal required.");
 
363
    }
 
364
  return errmsg; 
 
365
}
 
366
 
 
367
 
 
368
static const char *
 
369
parse_lit8 (cd, strp, opindex, valuep)
 
370
     CGEN_CPU_DESC cd;
 
371
     const char **strp;
 
372
     int opindex;
 
373
     long *valuep;
 
374
{
 
375
  const char *errmsg;
 
376
  enum cgen_parse_operand_result result_type;
 
377
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
 
378
  bfd_vma value;
 
379
 
 
380
  /* Parse %OP relocating operators. */
 
381
  if (strncmp (*strp, "%bank", 5) == 0)
 
382
    {
 
383
      *strp += 5;
 
384
      code = BFD_RELOC_IP2K_BANK;
 
385
    }
 
386
  else if (strncmp (*strp, "%lo8data", 8) == 0)
 
387
    {
 
388
      *strp += 8;
 
389
      code = BFD_RELOC_IP2K_LO8DATA;
 
390
    }
 
391
  else if (strncmp (*strp, "%hi8data", 8) == 0)
 
392
    {
 
393
      *strp += 8;
 
394
      code = BFD_RELOC_IP2K_HI8DATA;
 
395
    }
 
396
  else if (strncmp (*strp, "%ex8data", 8) == 0)
 
397
    {
 
398
      *strp += 8;
 
399
      code = BFD_RELOC_IP2K_EX8DATA;
 
400
    }
 
401
  else if (strncmp (*strp, "%lo8insn", 8) == 0)
 
402
    {
 
403
      *strp += 8;
 
404
      code = BFD_RELOC_IP2K_LO8INSN;
 
405
    }
 
406
  else if (strncmp (*strp, "%hi8insn", 8) == 0)
 
407
    {
 
408
      *strp += 8;
 
409
      code = BFD_RELOC_IP2K_HI8INSN;
 
410
    }
 
411
  
 
412
 
 
413
  /* Parse %op operand.  */
 
414
  if (code != BFD_RELOC_NONE)
 
415
    {
 
416
      errmsg = cgen_parse_address (cd, strp, opindex, code, 
 
417
                                   & result_type, & value);
 
418
      if ((errmsg == NULL) &&
 
419
          (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
 
420
        errmsg = _("%operator operand is not a symbol");
 
421
 
 
422
      *valuep = value;
 
423
    }
 
424
  /* Parse as a number.  */
 
425
  else
 
426
    {
 
427
      errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
 
428
 
 
429
      /* Truncate to eight bits to accept both signed and unsigned input. */
 
430
      if (errmsg == NULL)
 
431
        *valuep &= 0xFF;
 
432
    }
 
433
 
 
434
  return errmsg;
 
435
}
 
436
 
 
437
static const char *
 
438
parse_bit3 (cd, strp, opindex, valuep)
 
439
     CGEN_CPU_DESC cd;
 
440
     const char **strp;
 
441
     int opindex;
 
442
     long *valuep;
 
443
{
 
444
  const char *errmsg;
 
445
  char mode = 0;
 
446
  long count = 0;
 
447
  unsigned long value;
 
448
 
 
449
  if (strncmp (*strp, "%bit", 4) == 0)
 
450
    {
 
451
      *strp += 4;
 
452
      mode = 1;
 
453
    }
 
454
  else if (strncmp (*strp, "%msbbit", 7) == 0)
 
455
    {
 
456
      *strp += 7;
 
457
      mode = 1;
 
458
    }
 
459
  else if (strncmp (*strp, "%lsbbit", 7) == 0)
 
460
    {
 
461
      *strp += 7;
 
462
      mode = 2;
 
463
    }
 
464
 
 
465
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
 
466
  if (errmsg)
 
467
    return errmsg;
 
468
 
 
469
  if (mode)
 
470
    {
 
471
      value = (unsigned long) *valuep;
 
472
      if (value == 0)
 
473
        {
 
474
          errmsg = _("Attempt to find bit index of 0");
 
475
          return errmsg;
 
476
        }
 
477
    
 
478
      if (mode == 1)
 
479
        {
 
480
          count = 31;
 
481
          while ((value & 0x80000000) == 0)
 
482
            {
 
483
              count--;
 
484
              value <<= 1;
 
485
            }
 
486
        }
 
487
      else if (mode == 2)
 
488
        {
 
489
          count = 0;
 
490
          while ((value & 0x00000001) == 0)
 
491
            {
 
492
              count++;
 
493
              value >>= 1;
 
494
            }
 
495
        }
 
496
    
 
497
      *valuep = count;
 
498
    }
 
499
 
 
500
  return errmsg;
 
501
}
 
502
 
 
503
 
 
504
/* -- dis.c */
 
505
 
 
506
const char * ip2k_cgen_parse_operand
 
507
  PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
 
508
 
 
509
/* Main entry point for operand parsing.
 
510
 
 
511
   This function is basically just a big switch statement.  Earlier versions
 
512
   used tables to look up the function to use, but
 
513
   - if the table contains both assembler and disassembler functions then
 
514
     the disassembler contains much of the assembler and vice-versa,
 
515
   - there's a lot of inlining possibilities as things grow,
 
516
   - using a switch statement avoids the function call overhead.
 
517
 
 
518
   This function could be moved into `parse_insn_normal', but keeping it
 
519
   separate makes clear the interface between `parse_insn_normal' and each of
 
520
   the handlers.  */
 
521
 
 
522
const char *
 
523
ip2k_cgen_parse_operand (cd, opindex, strp, fields)
 
524
     CGEN_CPU_DESC cd;
 
525
     int opindex;
 
526
     const char ** strp;
 
527
     CGEN_FIELDS * fields;
 
528
{
 
529
  const char * errmsg = NULL;
 
530
  /* Used by scalar operands that still need to be parsed.  */
 
531
  long junk ATTRIBUTE_UNUSED;
 
532
 
 
533
  switch (opindex)
 
534
    {
 
535
    case IP2K_OPERAND_ADDR16CJP :
 
536
      errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16CJP, &fields->f_addr16cjp);
 
537
      break;
 
538
    case IP2K_OPERAND_ADDR16H :
 
539
      errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16H, &fields->f_imm8);
 
540
      break;
 
541
    case IP2K_OPERAND_ADDR16L :
 
542
      errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16L, &fields->f_imm8);
 
543
      break;
 
544
    case IP2K_OPERAND_ADDR16P :
 
545
      errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16P, &fields->f_page3);
 
546
      break;
 
547
    case IP2K_OPERAND_BITNO :
 
548
      errmsg = parse_bit3 (cd, strp, IP2K_OPERAND_BITNO, &fields->f_bitno);
 
549
      break;
 
550
    case IP2K_OPERAND_CBIT :
 
551
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_CBIT, &junk);
 
552
      break;
 
553
    case IP2K_OPERAND_DCBIT :
 
554
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_DCBIT, &junk);
 
555
      break;
 
556
    case IP2K_OPERAND_FR :
 
557
      errmsg = parse_fr (cd, strp, IP2K_OPERAND_FR, &fields->f_reg);
 
558
      break;
 
559
    case IP2K_OPERAND_LIT8 :
 
560
      errmsg = parse_lit8 (cd, strp, IP2K_OPERAND_LIT8, &fields->f_imm8);
 
561
      break;
 
562
    case IP2K_OPERAND_PABITS :
 
563
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_PABITS, &junk);
 
564
      break;
 
565
    case IP2K_OPERAND_RETI3 :
 
566
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_RETI3, &fields->f_reti3);
 
567
      break;
 
568
    case IP2K_OPERAND_ZBIT :
 
569
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_ZBIT, &junk);
 
570
      break;
 
571
 
 
572
    default :
 
573
      /* xgettext:c-format */
 
574
      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
 
575
      abort ();
 
576
  }
 
577
 
 
578
  return errmsg;
 
579
}
 
580
 
 
581
cgen_parse_fn * const ip2k_cgen_parse_handlers[] = 
 
582
{
 
583
  parse_insn_normal,
 
584
};
 
585
 
 
586
void
 
587
ip2k_cgen_init_asm (cd)
 
588
     CGEN_CPU_DESC cd;
 
589
{
 
590
  ip2k_cgen_init_opcode_table (cd);
 
591
  ip2k_cgen_init_ibld_table (cd);
 
592
  cd->parse_handlers = & ip2k_cgen_parse_handlers[0];
 
593
  cd->parse_operand = ip2k_cgen_parse_operand;
 
594
}
 
595
 
 
596
 
 
597
 
 
598
/* Regex construction routine.
 
599
 
 
600
   This translates an opcode syntax string into a regex string,
 
601
   by replacing any non-character syntax element (such as an
 
602
   opcode) with the pattern '.*'
 
603
 
 
604
   It then compiles the regex and stores it in the opcode, for
 
605
   later use by ip2k_cgen_assemble_insn
 
606
 
 
607
   Returns NULL for success, an error message for failure.  */
 
608
 
 
609
char * 
 
610
ip2k_cgen_build_insn_regex (CGEN_INSN *insn)
 
611
{  
 
612
  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
 
613
  const char *mnem = CGEN_INSN_MNEMONIC (insn);
 
614
  char rxbuf[CGEN_MAX_RX_ELEMENTS];
 
615
  char *rx = rxbuf;
 
616
  const CGEN_SYNTAX_CHAR_TYPE *syn;
 
617
  int reg_err;
 
618
 
 
619
  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
 
620
 
 
621
  /* Mnemonics come first in the syntax string.  */
 
622
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
 
623
    return _("missing mnemonic in syntax string");
 
624
  ++syn;
 
625
 
 
626
  /* Generate a case sensitive regular expression that emulates case
 
627
     insensitive matching in the "C" locale.  We cannot generate a case
 
628
     insensitive regular expression because in Turkish locales, 'i' and 'I'
 
629
     are not equal modulo case conversion.  */
 
630
 
 
631
  /* Copy the literal mnemonic out of the insn.  */
 
632
  for (; *mnem; mnem++)
 
633
    {
 
634
      char c = *mnem;
 
635
 
 
636
      if (ISALPHA (c))
 
637
        {
 
638
          *rx++ = '[';
 
639
          *rx++ = TOLOWER (c);
 
640
          *rx++ = TOUPPER (c);
 
641
          *rx++ = ']';
 
642
        }
 
643
      else
 
644
        *rx++ = c;
 
645
    }
 
646
 
 
647
  /* Copy any remaining literals from the syntax string into the rx.  */
 
648
  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
 
649
    {
 
650
      if (CGEN_SYNTAX_CHAR_P (* syn)) 
 
651
        {
 
652
          char c = CGEN_SYNTAX_CHAR (* syn);
 
653
 
 
654
          switch (c) 
 
655
            {
 
656
              /* Escape any regex metacharacters in the syntax.  */
 
657
            case '.': case '[': case '\\': 
 
658
            case '*': case '^': case '$': 
 
659
 
 
660
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
 
661
            case '?': case '{': case '}': 
 
662
            case '(': case ')': case '*':
 
663
            case '|': case '+': case ']':
 
664
#endif
 
665
              *rx++ = '\\';
 
666
              *rx++ = c;
 
667
              break;
 
668
 
 
669
            default:
 
670
              if (ISALPHA (c))
 
671
                {
 
672
                  *rx++ = '[';
 
673
                  *rx++ = TOLOWER (c);
 
674
                  *rx++ = TOUPPER (c);
 
675
                  *rx++ = ']';
 
676
                }
 
677
              else
 
678
                *rx++ = c;
 
679
              break;
 
680
            }
 
681
        }
 
682
      else
 
683
        {
 
684
          /* Replace non-syntax fields with globs.  */
 
685
          *rx++ = '.';
 
686
          *rx++ = '*';
 
687
        }
 
688
    }
 
689
 
 
690
  /* Trailing whitespace ok.  */
 
691
  * rx++ = '['; 
 
692
  * rx++ = ' '; 
 
693
  * rx++ = '\t'; 
 
694
  * rx++ = ']'; 
 
695
  * rx++ = '*'; 
 
696
 
 
697
  /* But anchor it after that.  */
 
698
  * rx++ = '$'; 
 
699
  * rx = '\0';
 
700
 
 
701
  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
 
702
  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
 
703
 
 
704
  if (reg_err == 0) 
 
705
    return NULL;
 
706
  else
 
707
    {
 
708
      static char msg[80];
 
709
 
 
710
      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
 
711
      regfree ((regex_t *) CGEN_INSN_RX (insn));
 
712
      free (CGEN_INSN_RX (insn));
 
713
      (CGEN_INSN_RX (insn)) = NULL;
 
714
      return msg;
 
715
    }
 
716
}
 
717
 
 
718
 
 
719
/* Default insn parser.
 
720
 
 
721
   The syntax string is scanned and operands are parsed and stored in FIELDS.
 
722
   Relocs are queued as we go via other callbacks.
 
723
 
 
724
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
 
725
   parse the instruction, we return 0 and the caller will start over from
 
726
   the beginning.  Backtracking will be necessary in parsing subexpressions,
 
727
   but that can be handled there.  Not handling backtracking here may get
 
728
   expensive in the case of the m68k.  Deal with later.
 
729
 
 
730
   Returns NULL for success, an error message for failure.  */
 
731
 
 
732
static const char *
 
733
parse_insn_normal (CGEN_CPU_DESC cd,
 
734
                   const CGEN_INSN *insn,
 
735
                   const char **strp,
 
736
                   CGEN_FIELDS *fields)
 
737
{
 
738
  /* ??? Runtime added insns not handled yet.  */
 
739
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
 
740
  const char *str = *strp;
 
741
  const char *errmsg;
 
742
  const char *p;
 
743
  const CGEN_SYNTAX_CHAR_TYPE * syn;
 
744
#ifdef CGEN_MNEMONIC_OPERANDS
 
745
  /* FIXME: wip */
 
746
  int past_opcode_p;
 
747
#endif
 
748
 
 
749
  /* For now we assume the mnemonic is first (there are no leading operands).
 
750
     We can parse it without needing to set up operand parsing.
 
751
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
 
752
     not be called from GAS.  */
 
753
  p = CGEN_INSN_MNEMONIC (insn);
 
754
  while (*p && TOLOWER (*p) == TOLOWER (*str))
 
755
    ++p, ++str;
 
756
 
 
757
  if (* p)
 
758
    return _("unrecognized instruction");
 
759
 
 
760
#ifndef CGEN_MNEMONIC_OPERANDS
 
761
  if (* str && ! ISSPACE (* str))
 
762
    return _("unrecognized instruction");
 
763
#endif
 
764
 
 
765
  CGEN_INIT_PARSE (cd);
 
766
  cgen_init_parse_operand (cd);
 
767
#ifdef CGEN_MNEMONIC_OPERANDS
 
768
  past_opcode_p = 0;
 
769
#endif
 
770
 
 
771
  /* We don't check for (*str != '\0') here because we want to parse
 
772
     any trailing fake arguments in the syntax string.  */
 
773
  syn = CGEN_SYNTAX_STRING (syntax);
 
774
 
 
775
  /* Mnemonics come first for now, ensure valid string.  */
 
776
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
 
777
    abort ();
 
778
 
 
779
  ++syn;
 
780
 
 
781
  while (* syn != 0)
 
782
    {
 
783
      /* Non operand chars must match exactly.  */
 
784
      if (CGEN_SYNTAX_CHAR_P (* syn))
 
785
        {
 
786
          /* FIXME: While we allow for non-GAS callers above, we assume the
 
787
             first char after the mnemonic part is a space.  */
 
788
          /* FIXME: We also take inappropriate advantage of the fact that
 
789
             GAS's input scrubber will remove extraneous blanks.  */
 
790
          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
 
791
            {
 
792
#ifdef CGEN_MNEMONIC_OPERANDS
 
793
              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
 
794
                past_opcode_p = 1;
 
795
#endif
 
796
              ++ syn;
 
797
              ++ str;
 
798
            }
 
799
          else if (*str)
 
800
            {
 
801
              /* Syntax char didn't match.  Can't be this insn.  */
 
802
              static char msg [80];
 
803
 
 
804
              /* xgettext:c-format */
 
805
              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
 
806
                       CGEN_SYNTAX_CHAR(*syn), *str);
 
807
              return msg;
 
808
            }
 
809
          else
 
810
            {
 
811
              /* Ran out of input.  */
 
812
              static char msg [80];
 
813
 
 
814
              /* xgettext:c-format */
 
815
              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
 
816
                       CGEN_SYNTAX_CHAR(*syn));
 
817
              return msg;
 
818
            }
 
819
          continue;
 
820
        }
 
821
 
 
822
      /* We have an operand of some sort.  */
 
823
      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
 
824
                                          &str, fields);
 
825
      if (errmsg)
 
826
        return errmsg;
 
827
 
 
828
      /* Done with this operand, continue with next one.  */
 
829
      ++ syn;
 
830
    }
 
831
 
 
832
  /* If we're at the end of the syntax string, we're done.  */
 
833
  if (* syn == 0)
 
834
    {
 
835
      /* FIXME: For the moment we assume a valid `str' can only contain
 
836
         blanks now.  IE: We needn't try again with a longer version of
 
837
         the insn and it is assumed that longer versions of insns appear
 
838
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
 
839
      while (ISSPACE (* str))
 
840
        ++ str;
 
841
 
 
842
      if (* str != '\0')
 
843
        return _("junk at end of line"); /* FIXME: would like to include `str' */
 
844
 
 
845
      return NULL;
 
846
    }
 
847
 
 
848
  /* We couldn't parse it.  */
 
849
  return _("unrecognized instruction");
 
850
}
 
851
 
 
852
/* Main entry point.
 
853
   This routine is called for each instruction to be assembled.
 
854
   STR points to the insn to be assembled.
 
855
   We assume all necessary tables have been initialized.
 
856
   The assembled instruction, less any fixups, is stored in BUF.
 
857
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
 
858
   still needs to be converted to target byte order, otherwise BUF is an array
 
859
   of bytes in target byte order.
 
860
   The result is a pointer to the insn's entry in the opcode table,
 
861
   or NULL if an error occured (an error message will have already been
 
862
   printed).
 
863
 
 
864
   Note that when processing (non-alias) macro-insns,
 
865
   this function recurses.
 
866
 
 
867
   ??? It's possible to make this cpu-independent.
 
868
   One would have to deal with a few minor things.
 
869
   At this point in time doing so would be more of a curiosity than useful
 
870
   [for example this file isn't _that_ big], but keeping the possibility in
 
871
   mind helps keep the design clean.  */
 
872
 
 
873
const CGEN_INSN *
 
874
ip2k_cgen_assemble_insn (CGEN_CPU_DESC cd,
 
875
                           const char *str,
 
876
                           CGEN_FIELDS *fields,
 
877
                           CGEN_INSN_BYTES_PTR buf,
 
878
                           char **errmsg)
 
879
{
 
880
  const char *start;
 
881
  CGEN_INSN_LIST *ilist;
 
882
  const char *parse_errmsg = NULL;
 
883
  const char *insert_errmsg = NULL;
 
884
  int recognized_mnemonic = 0;
 
885
 
 
886
  /* Skip leading white space.  */
 
887
  while (ISSPACE (* str))
 
888
    ++ str;
 
889
 
 
890
  /* The instructions are stored in hashed lists.
 
891
     Get the first in the list.  */
 
892
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
 
893
 
 
894
  /* Keep looking until we find a match.  */
 
895
  start = str;
 
896
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
 
897
    {
 
898
      const CGEN_INSN *insn = ilist->insn;
 
899
      recognized_mnemonic = 1;
 
900
 
 
901
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
 
902
      /* Not usually needed as unsupported opcodes
 
903
         shouldn't be in the hash lists.  */
 
904
      /* Is this insn supported by the selected cpu?  */
 
905
      if (! ip2k_cgen_insn_supported (cd, insn))
 
906
        continue;
 
907
#endif
 
908
      /* If the RELAXED attribute is set, this is an insn that shouldn't be
 
909
         chosen immediately.  Instead, it is used during assembler/linker
 
910
         relaxation if possible.  */
 
911
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
 
912
        continue;
 
913
 
 
914
      str = start;
 
915
 
 
916
      /* Skip this insn if str doesn't look right lexically.  */
 
917
      if (CGEN_INSN_RX (insn) != NULL &&
 
918
          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
 
919
        continue;
 
920
 
 
921
      /* Allow parse/insert handlers to obtain length of insn.  */
 
922
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
 
923
 
 
924
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
 
925
      if (parse_errmsg != NULL)
 
926
        continue;
 
927
 
 
928
      /* ??? 0 is passed for `pc'.  */
 
929
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
 
930
                                                 (bfd_vma) 0);
 
931
      if (insert_errmsg != NULL)
 
932
        continue;
 
933
 
 
934
      /* It is up to the caller to actually output the insn and any
 
935
         queued relocs.  */
 
936
      return insn;
 
937
    }
 
938
 
 
939
  {
 
940
    static char errbuf[150];
 
941
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
 
942
    const char *tmp_errmsg;
 
943
 
 
944
    /* If requesting verbose error messages, use insert_errmsg.
 
945
       Failing that, use parse_errmsg.  */
 
946
    tmp_errmsg = (insert_errmsg ? insert_errmsg :
 
947
                  parse_errmsg ? parse_errmsg :
 
948
                  recognized_mnemonic ?
 
949
                  _("unrecognized form of instruction") :
 
950
                  _("unrecognized instruction"));
 
951
 
 
952
    if (strlen (start) > 50)
 
953
      /* xgettext:c-format */
 
954
      sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
 
955
    else 
 
956
      /* xgettext:c-format */
 
957
      sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
 
958
#else
 
959
    if (strlen (start) > 50)
 
960
      /* xgettext:c-format */
 
961
      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
 
962
    else 
 
963
      /* xgettext:c-format */
 
964
      sprintf (errbuf, _("bad instruction `%.50s'"), start);
 
965
#endif
 
966
      
 
967
    *errmsg = errbuf;
 
968
    return NULL;
 
969
  }
 
970
}
 
971
 
 
972
#if 0 /* This calls back to GAS which we can't do without care.  */
 
973
 
 
974
/* Record each member of OPVALS in the assembler's symbol table.
 
975
   This lets GAS parse registers for us.
 
976
   ??? Interesting idea but not currently used.  */
 
977
 
 
978
/* Record each member of OPVALS in the assembler's symbol table.
 
979
   FIXME: Not currently used.  */
 
980
 
 
981
void
 
982
ip2k_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
 
983
{
 
984
  CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
 
985
  const CGEN_KEYWORD_ENTRY * ke;
 
986
 
 
987
  while ((ke = cgen_keyword_search_next (& search)) != NULL)
 
988
    {
 
989
#if 0 /* Unnecessary, should be done in the search routine.  */
 
990
      if (! ip2k_cgen_opval_supported (ke))
 
991
        continue;
 
992
#endif
 
993
      cgen_asm_record_register (cd, ke->name, ke->value);
 
994
    }
 
995
}
 
996
 
 
997
#endif /* 0 */