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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-xstormy16.c] - Blame information for rev 297

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

Line No. Rev Author Line
1 205 julius
/* tc-xstormy16.c -- Assembler for the Sanyo XSTORMY16.
2
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
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
  fixS *fix;
201
 
202
  if (exp->X_op == O_fptr_symbol)
203
    {
204
      switch (nbytes)
205
        {
206
        case 4:
207
          /* This can happen when gcc is generating debug output.
208
             For example it can create a stab with the address of
209
             a function:
210
 
211
                .stabs  "foo:F(0,21)",36,0,0,@fptr(foo)
212
 
213
             Since this does not involve switching code pages, we
214
             just allow the reloc to be generated without any
215
             @fptr behaviour.  */
216
          exp->X_op = O_symbol;
217
          code = BFD_RELOC_32;
218
          break;
219
 
220
        case 2:
221
          exp->X_op = O_symbol;
222
          code = BFD_RELOC_XSTORMY16_FPTR16;
223
          break;
224
 
225
        default:
226
          as_bad (_("unsupported fptr fixup size %d"), nbytes);
227
          return;
228
        }
229
    }
230
  else if (nbytes == 1)
231
    code = BFD_RELOC_8;
232
  else if (nbytes == 2)
233
    code = BFD_RELOC_16;
234
  else if (nbytes == 4)
235
    code = BFD_RELOC_32;
236
  else
237
    {
238
      as_bad (_("unsupported fixup size %d"), nbytes);
239
      return;
240
    }
241
 
242
  fix = fix_new_exp (f, where, nbytes, exp, 0, code);
243
}
244
 
245
/* Called while parsing an instruction to create a fixup.
246
   Create BFD_RELOC_XSTORMY16_FPTR16 relocations.  */
247
 
248
fixS *
249
xstormy16_cgen_record_fixup_exp (fragS *              frag,
250
                                 int                  where,
251
                                 const CGEN_INSN *    insn,
252
                                 int                  length,
253
                                 const CGEN_OPERAND * operand,
254
                                 int                  opinfo,
255
                                 expressionS *        exp)
256
{
257
  fixS *fixP;
258
  operatorT op = exp->X_op;
259
 
260
  if (op == O_fptr_symbol)
261
    exp->X_op = O_symbol;
262
 
263
  fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
264
                                    operand, opinfo, exp);
265
 
266
  if (op == O_fptr_symbol)
267
    {
268
      if (operand->type != XSTORMY16_OPERAND_IMM16)
269
        as_bad (_("unsupported fptr fixup"));
270
      else
271
        {
272
          fixP->fx_r_type = BFD_RELOC_XSTORMY16_FPTR16;
273
          fixP->fx_where += 2;
274
        }
275
    }
276
 
277
  return fixP;
278
}
279
 
280
valueT
281
md_section_align (segT segment, valueT size)
282
{
283
  int align = bfd_get_section_alignment (stdoutput, segment);
284
 
285
  return ((size + (1 << align) - 1) & (-1 << align));
286
}
287
 
288
symbolS *
289
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
290
{
291
  return 0;
292
}
293
 
294
/* Return an initial guess of the length by which a fragment must grow to
295
   hold a branch to reach its destination.
296
   Also updates fr_type/fr_subtype as necessary.
297
 
298
   Called just before doing relaxation.
299
   Any symbol that is now undefined will not become defined.
300
   The guess for fr_var is ACTUALLY the growth beyond fr_fix.
301
   Whatever we do to grow fr_fix or fr_var contributes to our returned value.
302
   Although it may not be explicit in the frag, pretend fr_var starts with a
303
 
304
 
305
int
306
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
307
                               segT    segment ATTRIBUTE_UNUSED)
308
{
309
  /* No assembler relaxation is defined (or necessary) for this port.  */
310
  abort ();
311
}
312
 
313
/* *fragP has been relaxed to its final size, and now needs to have
314
   the bytes inside it modified to conform to the new size.
315
 
316
   Called after relaxation is finished.
317
   fragP->fr_type == rs_machine_dependent.
318
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
319
 
320
void
321
md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
322
                 segT    sec ATTRIBUTE_UNUSED,
323
                 fragS * fragP ATTRIBUTE_UNUSED)
324
{
325
  /* No assembler relaxation is defined (or necessary) for this port.  */
326
  abort ();
327
}
328
 
329
/* Functions concerning relocs.  */
330
 
331
/* The location from which a PC relative jump should be calculated,
332
   given a PC relative reloc.  */
333
 
334
long
335
md_pcrel_from_section (fixS * fixP, segT sec)
336
{
337
  if ((fixP->fx_addsy != (symbolS *) NULL
338
       && (! S_IS_DEFINED (fixP->fx_addsy)
339
           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
340
      || xstormy16_force_relocation (fixP))
341
    /* The symbol is undefined,
342
       or it is defined but not in this section,
343
       or the relocation will be relative to this symbol not the section symbol.
344
       Let the linker figure it out.  */
345
    return 0;
346
 
347
  return fixP->fx_frag->fr_address + fixP->fx_where;
348
}
349
 
350
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
351
   Returns BFD_RELOC_NONE if no reloc type can be found.
352
   *FIXP may be modified if desired.  */
353
 
354
bfd_reloc_code_real_type
355
md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
356
                      const CGEN_OPERAND * operand,
357
                      fixS *               fixP)
358
{
359
  switch (operand->type)
360
    {
361
    case XSTORMY16_OPERAND_IMM2:
362
    case XSTORMY16_OPERAND_IMM3:
363
    case XSTORMY16_OPERAND_IMM3B:
364
    case XSTORMY16_OPERAND_IMM4:
365
    case XSTORMY16_OPERAND_HMEM8:
366
      return BFD_RELOC_NONE;
367
 
368
    case XSTORMY16_OPERAND_IMM12:
369
      fixP->fx_where += 2;
370
      return BFD_RELOC_XSTORMY16_12;
371
 
372
    case XSTORMY16_OPERAND_IMM8:
373
    case XSTORMY16_OPERAND_LMEM8:
374
      return fixP->fx_pcrel ? BFD_RELOC_8_PCREL : BFD_RELOC_8;
375
 
376
    case XSTORMY16_OPERAND_IMM16:
377
      /* This might have been processed at parse time.  */
378
      fixP->fx_where += 2;
379
      if (fixP->fx_cgen.opinfo && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
380
        return fixP->fx_cgen.opinfo;
381
      return fixP->fx_pcrel ? BFD_RELOC_16_PCREL : BFD_RELOC_16;
382
 
383
    case XSTORMY16_OPERAND_ABS24:
384
      return BFD_RELOC_XSTORMY16_24;
385
 
386
    case XSTORMY16_OPERAND_REL8_4:
387
      fixP->fx_addnumber -= 2;
388
    case XSTORMY16_OPERAND_REL8_2:
389
      fixP->fx_addnumber -= 2;
390
      fixP->fx_pcrel = 1;
391
      return BFD_RELOC_8_PCREL;
392
 
393
    case XSTORMY16_OPERAND_REL12:
394
      fixP->fx_where += 2;
395
      /* Fall through...  */
396
    case XSTORMY16_OPERAND_REL12A:
397
      fixP->fx_addnumber -= 2;
398
      fixP->fx_pcrel = 1;
399
      return BFD_RELOC_XSTORMY16_REL_12;
400
 
401
    default : /* avoid -Wall warning */
402
      abort ();
403
    }
404
}
405
 
406
/* See whether we need to force a relocation into the output file.
407
   This is used to force out switch and PC relative relocations when
408
   relaxing.  */
409
 
410
int
411
xstormy16_force_relocation (fixS * fix)
412
{
413
  if (fix->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
414
    return 1;
415
 
416
  return generic_force_reloc (fix);
417
}
418
 
419
/* Return true if a relocation against a symbol may be replaced with
420
   a relocation against section+offset.  */
421
 
422
bfd_boolean
423
xstormy16_fix_adjustable (fixS * fixP)
424
{
425
  /* We need the symbol name for the VTABLE entries.  */
426
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
427
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
428
    return FALSE;
429
 
430
  if (fixP->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
431
    return FALSE;
432
 
433
  return TRUE;
434
}
435
 
436
/* This is a copy of gas_cgen_md_apply_fix, with some enhancements to
437
   do various things that would not be valid for all ports.  */
438
 
439
void
440
xstormy16_md_apply_fix (fixS *   fixP,
441
                         valueT * valueP,
442
                         segT     seg ATTRIBUTE_UNUSED)
443
{
444
  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
445
  valueT value = *valueP;
446
  /* Canonical name, since used a lot.  */
447
  CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
448
 
449
  /* md_cgen_lookup_reloc() will adjust this to compensate for where
450
     in the opcode the relocation happens, for pcrel relocations.  We
451
     have no other way of keeping track of what this offset needs to
452
     be.  */
453
  fixP->fx_addnumber = 0;
454
 
455
  /* This port has pc-relative relocs and DIFF_EXPR_OK defined, so
456
     it must deal with turning a BFD_RELOC_{8,16,32,64} into a
457
     BFD_RELOC_*_PCREL for the case of
458
 
459
        .word something-.  */
460
  if (fixP->fx_pcrel)
461
    switch (fixP->fx_r_type)
462
      {
463
      case BFD_RELOC_8:
464
        fixP->fx_r_type = BFD_RELOC_8_PCREL;
465
        break;
466
      case BFD_RELOC_16:
467
        fixP->fx_r_type = BFD_RELOC_16_PCREL;
468
        break;
469
      case BFD_RELOC_32:
470
        fixP->fx_r_type = BFD_RELOC_32_PCREL;
471
        break;
472
      case BFD_RELOC_64:
473
        fixP->fx_r_type = BFD_RELOC_64_PCREL;
474
        break;
475
      default:
476
        break;
477
      }
478
 
479
  if (fixP->fx_addsy == (symbolS *) NULL)
480
    fixP->fx_done = 1;
481
 
482
  /* We don't actually support subtracting a symbol.  */
483
  if (fixP->fx_subsy != (symbolS *) NULL)
484
    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
485
 
486
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
487
    {
488
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
489
      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
490
      const char *errmsg;
491
      bfd_reloc_code_real_type reloc_type;
492
      CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
493
      const CGEN_INSN *insn = fixP->fx_cgen.insn;
494
 
495
      /* If the reloc has been fully resolved finish the operand here.  */
496
      /* FIXME: This duplicates the capabilities of code in BFD.  */
497
      if (fixP->fx_done)
498
        {
499
          CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
500
          CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
501
 
502
#if CGEN_INT_INSN_P
503
          {
504
            CGEN_INSN_INT insn_value =
505
              cgen_get_insn_value (cd, (unsigned char *) where,
506
                                   CGEN_INSN_BITSIZE (insn));
507
 
508
            /* ??? 0 is passed for `pc'.  */
509
            errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
510
                                                   &insn_value, (bfd_vma) 0);
511
            cgen_put_insn_value (cd, (unsigned char *) where,
512
                                 CGEN_INSN_BITSIZE (insn), insn_value);
513
          }
514
#else
515
          /* ??? 0 is passed for `pc'.  */
516
          errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
517
                                                 (unsigned char *) where,
518
                                                 (bfd_vma) 0);
519
#endif
520
          if (errmsg)
521
            as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
522
        }
523
 
524
      if (fixP->fx_done)
525
        return;
526
 
527
      /* The operand isn't fully resolved.  Determine a BFD reloc value
528
         based on the operand information and leave it to
529
         bfd_install_relocation.  Note that this doesn't work when
530
         !partial_inplace.  */
531
 
532
      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
533
      if (reloc_type != BFD_RELOC_NONE)
534
        fixP->fx_r_type = reloc_type;
535
      else
536
        {
537
          as_bad_where (fixP->fx_file, fixP->fx_line,
538
                        _("unresolved expression that must be resolved"));
539
          fixP->fx_done = 1;
540
          return;
541
        }
542
    }
543
  else if (fixP->fx_done)
544
    {
545
      /* We're finished with this fixup.  Install it because
546
         bfd_install_relocation won't be called to do it.  */
547
      switch (fixP->fx_r_type)
548
        {
549
        case BFD_RELOC_8:
550
          md_number_to_chars (where, value, 1);
551
          break;
552
        case BFD_RELOC_16:
553
          md_number_to_chars (where, value, 2);
554
          break;
555
        case BFD_RELOC_32:
556
          md_number_to_chars (where, value, 4);
557
          break;
558
        case BFD_RELOC_64:
559
          md_number_to_chars (where, value, 8);
560
          break;
561
        default:
562
          as_bad_where (fixP->fx_file, fixP->fx_line,
563
                        _("internal error: can't install fix for reloc type %d (`%s')"),
564
                        fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
565
          break;
566
        }
567
    }
568
  else
569
    {
570
      /* bfd_install_relocation will be called to finish things up.  */
571
    }
572
 
573
  /* This is a RELA port.  Thus, it does not need to store a
574
     value if it is going to make a reloc.  What's more, when
575
     assembling a line like
576
 
577
     .byte global-0x7f00
578
 
579
     we'll get a spurious error message if we try to stuff 0x7f00 into
580
     the byte.  */
581
  if (! fixP->fx_done)
582
    *valueP = 0;
583
 
584
  /* Tuck `value' away for use by tc_gen_reloc.
585
     See the comment describing fx_addnumber in write.h.
586
     This field is misnamed (or misused :-).  */
587
  fixP->fx_addnumber += value;
588
}
589
 
590
 
591
/* Write a value out to the object file, using the appropriate endianness.  */
592
 
593
void
594
md_number_to_chars (char * buf, valueT val, int n)
595
{
596
  number_to_chars_littleendian (buf, val, n);
597
}
598
 
599
char *
600
md_atof (int type, char * litP, int * sizeP)
601
{
602
  return ieee_md_atof (type, litP, sizeP, FALSE);
603
}

powered by: WebSVN 2.1.0

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