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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [tc-xstormy16.c] - Blame information for rev 158

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

Line No. Rev Author Line
1 16 khays
/* tc-xstormy16.c -- Assembler for the Sanyo XSTORMY16.
2
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
3
   Free Software Foundation.
4
 
5
   This file is part of GAS, the GNU Assembler.
6
 
7
   GAS is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
 
12
   GAS is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with GAS; see the file COPYING.  If not, write to
19
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20
   Boston, MA 02110-1301, USA.  */
21
 
22
#include "as.h"
23
#include "subsegs.h"
24
#include "symcat.h"
25
#include "opcodes/xstormy16-desc.h"
26
#include "opcodes/xstormy16-opc.h"
27
#include "cgen.h"
28
 
29
/* Structure to hold all of the different components describing
30
   an individual instruction.  */
31
typedef struct
32
{
33
  const CGEN_INSN *     insn;
34
  const CGEN_INSN *     orig_insn;
35
  CGEN_FIELDS           fields;
36
#if CGEN_INT_INSN_P
37
  CGEN_INSN_INT         buffer [1];
38
#define INSN_VALUE(buf) (*(buf))
39
#else
40
  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
41
#define INSN_VALUE(buf) (buf)
42
#endif
43
  char *                addr;
44
  fragS *               frag;
45
  int                   num_fixups;
46
  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
47
  int                   indices [MAX_OPERAND_INSTANCES];
48
}
49
xstormy16_insn;
50
 
51
const char comment_chars[]        = ";";
52
const char line_comment_chars[]   = "#";
53
const char line_separator_chars[] = "|";
54
const char EXP_CHARS[]            = "eE";
55
const char FLT_CHARS[]            = "dD";
56
 
57
#define O_fptr_symbol   (O_max + 1)
58
 
59
#define XSTORMY16_SHORTOPTS ""
60
const char * md_shortopts = XSTORMY16_SHORTOPTS;
61
 
62
struct option md_longopts[] =
63
{
64
  {NULL, no_argument, NULL, 0}
65
};
66
size_t md_longopts_size = sizeof (md_longopts);
67
 
68
int
69
md_parse_option (int    c ATTRIBUTE_UNUSED,
70
                 char * arg ATTRIBUTE_UNUSED)
71
{
72
  return 0;
73
}
74
 
75
void
76
md_show_usage (FILE * stream)
77
{
78
  fprintf (stream, _(" XSTORMY16 specific command line options:\n"));
79
}
80
 
81
/* The target specific pseudo-ops which we support.  */
82
const pseudo_typeS md_pseudo_table[] =
83
{
84
  { "word",     cons,           4 },
85
  { NULL,       NULL,           0 }
86
};
87
 
88
 
89
void
90
md_begin (void)
91
{
92
  /* Initialize the `cgen' interface.  */
93
 
94
  /* Set the machine number and endian.  */
95
  gas_cgen_cpu_desc = xstormy16_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
96
                                          CGEN_CPU_OPEN_ENDIAN,
97
                                          CGEN_ENDIAN_LITTLE,
98
                                          CGEN_CPU_OPEN_END);
99
  xstormy16_cgen_init_asm (gas_cgen_cpu_desc);
100
 
101
  /* This is a callback from cgen to gas to parse operands.  */
102
  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
103
}
104
 
105
static bfd_boolean skipping_fptr = FALSE;
106
 
107
void
108
md_assemble (char * str)
109
{
110
  xstormy16_insn insn;
111
  char *    errmsg;
112
 
113
  /* Make sure that if we had an erroneous input line which triggered
114
     the skipping_fptr boolean that it does not affect following lines.  */
115
  skipping_fptr = FALSE;
116
 
117
  /* Initialize GAS's cgen interface for a new instruction.  */
118
  gas_cgen_init_parse ();
119
 
120
  insn.insn = xstormy16_cgen_assemble_insn
121
    (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
122
 
123
  if (!insn.insn)
124
    {
125
      as_bad ("%s", errmsg);
126
      return;
127
    }
128
 
129
  /* Doesn't really matter what we pass for RELAX_P here.  */
130
  gas_cgen_finish_insn (insn.insn, insn.buffer,
131
                        CGEN_FIELDS_BITSIZE (& insn.fields), 0, NULL);
132
}
133
 
134
void
135
md_operand (expressionS * e)
136
{
137
  if (*input_line_pointer != '@')
138
    return;
139
 
140
  if (strncmp (input_line_pointer + 1, "fptr", 4) == 0)
141
    {
142
      input_line_pointer += 5;
143
      SKIP_WHITESPACE ();
144
      if (*input_line_pointer != '(')
145
        {
146
          as_bad (_("Expected '('"));
147
          goto err;
148
        }
149
      input_line_pointer++;
150
 
151
      expression (e);
152
 
153
      if (*input_line_pointer != ')')
154
        {
155
          as_bad (_("Missing ')'"));
156
          goto err;
157
        }
158
      input_line_pointer++;
159
      SKIP_WHITESPACE ();
160
 
161
      if (e->X_op != O_symbol)
162
        as_bad (_("Not a symbolic expression"));
163
      else if (* input_line_pointer == '-')
164
        /* We are computing the difference of two function pointers
165
           like this:
166
 
167
            .hword  @fptr (foo) - @fptr (bar)
168
 
169
          In this situation we do not want to generate O_fptr_symbol
170
          operands because the result is an absolute value, not a
171
          function pointer.
172
 
173
          We need to make the check here, rather than when the fixup
174
          is generated as the function names (foo & bar in the above
175
          example) might be local symbols and we want the expression
176
          to be evaluated now.  This kind of thing can happen when
177
          gcc is generating computed gotos.  */
178
        skipping_fptr = TRUE;
179
      else if (skipping_fptr)
180
        skipping_fptr = FALSE;
181
      else
182
        e->X_op = O_fptr_symbol;
183
    }
184
 
185
  return;
186
 err:
187
  ignore_rest_of_line ();
188
}
189
 
190
/* Called while parsing data to create a fixup.
191
   Create BFD_RELOC_XSTORMY16_FPTR16 relocations.  */
192
 
193
void
194
xstormy16_cons_fix_new (fragS *f,
195
                        int where,
196
                        int nbytes,
197
                        expressionS *exp)
198
{
199
  bfd_reloc_code_real_type code;
200
 
201
  if (exp->X_op == O_fptr_symbol)
202
    {
203
      switch (nbytes)
204
        {
205
        case 4:
206
          /* This can happen when gcc is generating debug output.
207
             For example it can create a stab with the address of
208
             a function:
209
 
210
                .stabs  "foo:F(0,21)",36,0,0,@fptr(foo)
211
 
212
             Since this does not involve switching code pages, we
213
             just allow the reloc to be generated without any
214
             @fptr behaviour.  */
215
          exp->X_op = O_symbol;
216
          code = BFD_RELOC_32;
217
          break;
218
 
219
        case 2:
220
          exp->X_op = O_symbol;
221
          code = BFD_RELOC_XSTORMY16_FPTR16;
222
          break;
223
 
224
        default:
225
          as_bad (_("unsupported fptr fixup size %d"), nbytes);
226
          return;
227
        }
228
    }
229
  else if (nbytes == 1)
230
    code = BFD_RELOC_8;
231
  else if (nbytes == 2)
232
    code = BFD_RELOC_16;
233
  else if (nbytes == 4)
234
    code = BFD_RELOC_32;
235
  else
236
    {
237
      as_bad (_("unsupported fixup size %d"), nbytes);
238
      return;
239
    }
240
 
241
  fix_new_exp (f, where, nbytes, exp, 0, code);
242
}
243
 
244
/* Called while parsing an instruction to create a fixup.
245
   Create BFD_RELOC_XSTORMY16_FPTR16 relocations.  */
246
 
247
fixS *
248
xstormy16_cgen_record_fixup_exp (fragS *              frag,
249
                                 int                  where,
250
                                 const CGEN_INSN *    insn,
251
                                 int                  length,
252
                                 const CGEN_OPERAND * operand,
253
                                 int                  opinfo,
254
                                 expressionS *        exp)
255
{
256
  fixS *fixP;
257
  operatorT op = exp->X_op;
258
 
259
  if (op == O_fptr_symbol)
260
    exp->X_op = O_symbol;
261
 
262
  fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
263
                                    operand, opinfo, exp);
264
 
265
  if (op == O_fptr_symbol)
266
    {
267
      if (operand->type != XSTORMY16_OPERAND_IMM16)
268
        as_bad (_("unsupported fptr fixup"));
269
      else
270
        {
271
          fixP->fx_r_type = BFD_RELOC_XSTORMY16_FPTR16;
272
          fixP->fx_where += 2;
273
        }
274
    }
275
 
276
  return fixP;
277
}
278
 
279
valueT
280
md_section_align (segT segment, valueT size)
281
{
282
  int align = bfd_get_section_alignment (stdoutput, segment);
283
 
284
  return ((size + (1 << align) - 1) & (-1 << align));
285
}
286
 
287
symbolS *
288
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
289
{
290
  return 0;
291
}
292
 
293
/* Return an initial guess of the length by which a fragment must grow to
294
   hold a branch to reach its destination.
295
   Also updates fr_type/fr_subtype as necessary.
296
 
297
   Called just before doing relaxation.
298
   Any symbol that is now undefined will not become defined.
299
   The guess for fr_var is ACTUALLY the growth beyond fr_fix.
300
   Whatever we do to grow fr_fix or fr_var contributes to our returned value.
301
   Although it may not be explicit in the frag, pretend fr_var starts with a
302
 
303
 
304
int
305
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
306
                               segT    segment ATTRIBUTE_UNUSED)
307
{
308
  /* No assembler relaxation is defined (or necessary) for this port.  */
309
  abort ();
310
}
311
 
312
/* *fragP has been relaxed to its final size, and now needs to have
313
   the bytes inside it modified to conform to the new size.
314
 
315
   Called after relaxation is finished.
316
   fragP->fr_type == rs_machine_dependent.
317
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
318
 
319
void
320
md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
321
                 segT    sec ATTRIBUTE_UNUSED,
322
                 fragS * fragP ATTRIBUTE_UNUSED)
323
{
324
  /* No assembler relaxation is defined (or necessary) for this port.  */
325
  abort ();
326
}
327
 
328
/* Functions concerning relocs.  */
329
 
330
/* The location from which a PC relative jump should be calculated,
331
   given a PC relative reloc.  */
332
 
333
long
334
md_pcrel_from_section (fixS * fixP, segT sec)
335
{
336
  if ((fixP->fx_addsy != (symbolS *) NULL
337
       && (! S_IS_DEFINED (fixP->fx_addsy)
338
           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
339
      || xstormy16_force_relocation (fixP))
340
    /* The symbol is undefined,
341
       or it is defined but not in this section,
342
       or the relocation will be relative to this symbol not the section symbol.
343
       Let the linker figure it out.  */
344
    return 0;
345
 
346
  return fixP->fx_frag->fr_address + fixP->fx_where;
347
}
348
 
349
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
350
   Returns BFD_RELOC_NONE if no reloc type can be found.
351
   *FIXP may be modified if desired.  */
352
 
353
bfd_reloc_code_real_type
354
md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
355
                      const CGEN_OPERAND * operand,
356
                      fixS *               fixP)
357
{
358
  switch (operand->type)
359
    {
360
    case XSTORMY16_OPERAND_IMM2:
361
    case XSTORMY16_OPERAND_IMM3:
362
    case XSTORMY16_OPERAND_IMM3B:
363
    case XSTORMY16_OPERAND_IMM4:
364
    case XSTORMY16_OPERAND_HMEM8:
365
      return BFD_RELOC_NONE;
366
 
367
    case XSTORMY16_OPERAND_IMM12:
368
      fixP->fx_where += 2;
369
      return BFD_RELOC_XSTORMY16_12;
370
 
371
    case XSTORMY16_OPERAND_IMM8:
372
    case XSTORMY16_OPERAND_LMEM8:
373
      return fixP->fx_pcrel ? BFD_RELOC_8_PCREL : BFD_RELOC_8;
374
 
375
    case XSTORMY16_OPERAND_IMM16:
376
      /* This might have been processed at parse time.  */
377
      fixP->fx_where += 2;
378
      if (fixP->fx_cgen.opinfo && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
379
        return fixP->fx_cgen.opinfo;
380
      return fixP->fx_pcrel ? BFD_RELOC_16_PCREL : BFD_RELOC_16;
381
 
382
    case XSTORMY16_OPERAND_ABS24:
383
      return BFD_RELOC_XSTORMY16_24;
384
 
385
    case XSTORMY16_OPERAND_REL8_4:
386
      fixP->fx_addnumber -= 2;
387
    case XSTORMY16_OPERAND_REL8_2:
388
      fixP->fx_addnumber -= 2;
389
      fixP->fx_pcrel = 1;
390
      return BFD_RELOC_8_PCREL;
391
 
392
    case XSTORMY16_OPERAND_REL12:
393
      fixP->fx_where += 2;
394
      /* Fall through...  */
395
    case XSTORMY16_OPERAND_REL12A:
396
      fixP->fx_addnumber -= 2;
397
      fixP->fx_pcrel = 1;
398
      return BFD_RELOC_XSTORMY16_REL_12;
399
 
400
    default : /* avoid -Wall warning */
401
      abort ();
402
    }
403
}
404
 
405
/* See whether we need to force a relocation into the output file.
406
   This is used to force out switch and PC relative relocations when
407
   relaxing.  */
408
 
409
int
410
xstormy16_force_relocation (fixS * fix)
411
{
412
  if (fix->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
413
    return 1;
414
 
415
  return generic_force_reloc (fix);
416
}
417
 
418
/* Return true if a relocation against a symbol may be replaced with
419
   a relocation against section+offset.  */
420
 
421
bfd_boolean
422
xstormy16_fix_adjustable (fixS * fixP)
423
{
424
  /* We need the symbol name for the VTABLE entries.  */
425
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
426
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
427
    return FALSE;
428
 
429
  if (fixP->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
430
    return FALSE;
431
 
432
  return TRUE;
433
}
434
 
435
/* This is a copy of gas_cgen_md_apply_fix, with some enhancements to
436
   do various things that would not be valid for all ports.  */
437
 
438
void
439
xstormy16_md_apply_fix (fixS *   fixP,
440
                         valueT * valueP,
441
                         segT     seg ATTRIBUTE_UNUSED)
442
{
443
  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
444
  valueT value = *valueP;
445
  /* Canonical name, since used a lot.  */
446
  CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
447
 
448
  /* md_cgen_lookup_reloc() will adjust this to compensate for where
449
     in the opcode the relocation happens, for pcrel relocations.  We
450
     have no other way of keeping track of what this offset needs to
451
     be.  */
452
  fixP->fx_addnumber = 0;
453
 
454
  /* This port has pc-relative relocs and DIFF_EXPR_OK defined, so
455
     it must deal with turning a BFD_RELOC_{8,16,32,64} into a
456
     BFD_RELOC_*_PCREL for the case of
457
 
458
        .word something-.  */
459
  if (fixP->fx_pcrel)
460
    switch (fixP->fx_r_type)
461
      {
462
      case BFD_RELOC_8:
463
        fixP->fx_r_type = BFD_RELOC_8_PCREL;
464
        break;
465
      case BFD_RELOC_16:
466
        fixP->fx_r_type = BFD_RELOC_16_PCREL;
467
        break;
468
      case BFD_RELOC_32:
469
        fixP->fx_r_type = BFD_RELOC_32_PCREL;
470
        break;
471
      case BFD_RELOC_64:
472
        fixP->fx_r_type = BFD_RELOC_64_PCREL;
473
        break;
474
      default:
475
        break;
476
      }
477
 
478
  if (fixP->fx_addsy == (symbolS *) NULL)
479
    fixP->fx_done = 1;
480
 
481
  /* We don't actually support subtracting a symbol.  */
482
  if (fixP->fx_subsy != (symbolS *) NULL)
483
    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
484
 
485
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
486
    {
487
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
488
      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
489
      const char *errmsg;
490
      bfd_reloc_code_real_type reloc_type;
491
      CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
492
      const CGEN_INSN *insn = fixP->fx_cgen.insn;
493
 
494
      /* If the reloc has been fully resolved finish the operand here.  */
495
      /* FIXME: This duplicates the capabilities of code in BFD.  */
496
      if (fixP->fx_done)
497
        {
498
          CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
499
          CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
500
 
501
#if CGEN_INT_INSN_P
502
          {
503
            CGEN_INSN_INT insn_value =
504
              cgen_get_insn_value (cd, (unsigned char *) where,
505
                                   CGEN_INSN_BITSIZE (insn));
506
 
507
            /* ??? 0 is passed for `pc'.  */
508
            errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
509
                                                   &insn_value, (bfd_vma) 0);
510
            cgen_put_insn_value (cd, (unsigned char *) where,
511
                                 CGEN_INSN_BITSIZE (insn), insn_value);
512
          }
513
#else
514
          /* ??? 0 is passed for `pc'.  */
515
          errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
516
                                                 (unsigned char *) where,
517
                                                 (bfd_vma) 0);
518
#endif
519
          if (errmsg)
520
            as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
521
        }
522
 
523
      if (fixP->fx_done)
524
        return;
525
 
526
      /* The operand isn't fully resolved.  Determine a BFD reloc value
527
         based on the operand information and leave it to
528
         bfd_install_relocation.  Note that this doesn't work when
529
         !partial_inplace.  */
530
 
531
      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
532
      if (reloc_type != BFD_RELOC_NONE)
533
        fixP->fx_r_type = reloc_type;
534
      else
535
        {
536
          as_bad_where (fixP->fx_file, fixP->fx_line,
537
                        _("unresolved expression that must be resolved"));
538
          fixP->fx_done = 1;
539
          return;
540
        }
541
    }
542
  else if (fixP->fx_done)
543
    {
544
      /* We're finished with this fixup.  Install it because
545
         bfd_install_relocation won't be called to do it.  */
546
      switch (fixP->fx_r_type)
547
        {
548
        case BFD_RELOC_8:
549
          md_number_to_chars (where, value, 1);
550
          break;
551
        case BFD_RELOC_16:
552
          md_number_to_chars (where, value, 2);
553
          break;
554
        case BFD_RELOC_32:
555
          md_number_to_chars (where, value, 4);
556
          break;
557
        case BFD_RELOC_64:
558
          md_number_to_chars (where, value, 8);
559
          break;
560
        default:
561
          as_bad_where (fixP->fx_file, fixP->fx_line,
562
                        _("internal error: can't install fix for reloc type %d (`%s')"),
563
                        fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
564
          break;
565
        }
566
    }
567
  else
568
    {
569
      /* bfd_install_relocation will be called to finish things up.  */
570
    }
571
 
572
  /* This is a RELA port.  Thus, it does not need to store a
573
     value if it is going to make a reloc.  What's more, when
574
     assembling a line like
575
 
576
     .byte global-0x7f00
577
 
578
     we'll get a spurious error message if we try to stuff 0x7f00 into
579
     the byte.  */
580
  if (! fixP->fx_done)
581
    *valueP = 0;
582
 
583
  /* Tuck `value' away for use by tc_gen_reloc.
584
     See the comment describing fx_addnumber in write.h.
585
     This field is misnamed (or misused :-).  */
586
  fixP->fx_addnumber += value;
587
}
588
 
589
 
590
/* Write a value out to the object file, using the appropriate endianness.  */
591
 
592
void
593
md_number_to_chars (char * buf, valueT val, int n)
594
{
595
  number_to_chars_littleendian (buf, val, n);
596
}
597
 
598
char *
599
md_atof (int type, char * litP, int * sizeP)
600
{
601
  return ieee_md_atof (type, litP, sizeP, FALSE);
602
}

powered by: WebSVN 2.1.0

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