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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 163 khays
/* tc-rl78.c -- Assembler for the Renesas RL78
2
   Copyright 2011
3
   Free Software Foundation, Inc.
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 the Free
19
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20
   02110-1301, USA.  */
21
 
22
#include "as.h"
23
#include "struc-symbol.h"
24
#include "obstack.h"
25
#include "safe-ctype.h"
26
#include "dwarf2dbg.h"
27
#include "libbfd.h"
28
#include "elf/common.h"
29
#include "elf/rl78.h"
30
#include "rl78-defs.h"
31
#include "filenames.h"
32
#include "listing.h"
33
#include "sb.h"
34
#include "macro.h"
35
 
36
const char comment_chars[]        = ";";
37
/* Note that input_file.c hand checks for '#' at the beginning of the
38
   first line of the input file.  This is because the compiler outputs
39
   #NO_APP at the beginning of its output.  */
40
const char line_comment_chars[]   = "#";
41
const char line_separator_chars[] = "|";
42
 
43
const char EXP_CHARS[]            = "eE";
44
const char FLT_CHARS[]            = "dD";
45
 
46
/*------------------------------------------------------------------*/
47
 
48
char * rl78_lex_start;
49
char * rl78_lex_end;
50
 
51
typedef struct rl78_bytesT
52
{
53
  char prefix[1];
54
  int n_prefix;
55
  char base[4];
56
  int n_base;
57
  char ops[8];
58
  int n_ops;
59
  struct
60
  {
61
    expressionS  exp;
62
    char         offset;
63
    char         nbits;
64
    char         type; /* RL78REL_*.  */
65
    int          reloc;
66
    fixS *       fixP;
67
  } fixups[2];
68
  int n_fixups;
69
  struct
70
  {
71
    char type;
72
    char field_pos;
73
    char val_ofs;
74
  } relax[2];
75
  int n_relax;
76
  int link_relax;
77
  fixS *link_relax_fixP;
78
  char times_grown;
79
  char times_shrank;
80
} rl78_bytesT;
81
 
82
static rl78_bytesT rl78_bytes;
83
 
84
static void
85
rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
86
{
87
  rl78_bytes.fixups[rl78_bytes.n_fixups].exp = exp;
88
  rl78_bytes.fixups[rl78_bytes.n_fixups].offset = offsetbits;
89
  rl78_bytes.fixups[rl78_bytes.n_fixups].nbits = nbits;
90
  rl78_bytes.fixups[rl78_bytes.n_fixups].type = type;
91
  rl78_bytes.fixups[rl78_bytes.n_fixups].reloc = exp.X_md;
92
  rl78_bytes.n_fixups ++;
93
}
94
 
95
#define rl78_field_fixup(exp, offset, nbits, type)      \
96
  rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
97
 
98
#define rl78_op_fixup(exp, offset, nbits, type)         \
99
  rl78_fixup (exp, offset + 8 * (rl78_bytes.n_prefix + rl78_bytes.n_base), nbits, type)
100
 
101
void
102
rl78_prefix (int p)
103
{
104
  rl78_bytes.prefix[0] = p;
105
  rl78_bytes.n_prefix = 1;
106
}
107
 
108
int
109
rl78_has_prefix ()
110
{
111
  return rl78_bytes.n_prefix;
112
}
113
 
114
void
115
rl78_base1 (int b1)
116
{
117
  rl78_bytes.base[0] = b1;
118
  rl78_bytes.n_base = 1;
119
}
120
 
121
void
122
rl78_base2 (int b1, int b2)
123
{
124
  rl78_bytes.base[0] = b1;
125
  rl78_bytes.base[1] = b2;
126
  rl78_bytes.n_base = 2;
127
}
128
 
129
void
130
rl78_base3 (int b1, int b2, int b3)
131
{
132
  rl78_bytes.base[0] = b1;
133
  rl78_bytes.base[1] = b2;
134
  rl78_bytes.base[2] = b3;
135
  rl78_bytes.n_base = 3;
136
}
137
 
138
void
139
rl78_base4 (int b1, int b2, int b3, int b4)
140
{
141
  rl78_bytes.base[0] = b1;
142
  rl78_bytes.base[1] = b2;
143
  rl78_bytes.base[2] = b3;
144
  rl78_bytes.base[3] = b4;
145
  rl78_bytes.n_base = 4;
146
}
147
 
148
#define F_PRECISION 2
149
 
150
void
151
rl78_op (expressionS exp, int nbytes, int type)
152
{
153
  int v = 0;
154
 
155
  if ((exp.X_op == O_constant || exp.X_op == O_big)
156
      && type != RL78REL_PCREL)
157
    {
158
      if (exp.X_op == O_big && exp.X_add_number <= 0)
159
        {
160
          LITTLENUM_TYPE w[2];
161
          char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
162
 
163
          gen_to_words (w, F_PRECISION, 8);
164
          ip[3] = w[0] >> 8;
165
          ip[2] = w[0];
166
          ip[1] = w[1] >> 8;
167
          ip[0] = w[1];
168
          rl78_bytes.n_ops += 4;
169
        }
170
      else
171
        {
172
          v = exp.X_add_number;
173
          while (nbytes)
174
            {
175
              rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
176
              v >>= 8;
177
              nbytes --;
178
            }
179
        }
180
    }
181
  else
182
    {
183
      rl78_op_fixup (exp, rl78_bytes.n_ops * 8, nbytes * 8, type);
184
      memset (rl78_bytes.ops + rl78_bytes.n_ops, 0, nbytes);
185
      rl78_bytes.n_ops += nbytes;
186
    }
187
}
188
 
189
/* This gets complicated when the field spans bytes, because fields
190
   are numbered from the MSB of the first byte as zero, and bits are
191
   stored LSB towards the LSB of the byte.  Thus, a simple four-bit
192
   insertion of 12 at position 4 of 0x00 yields: 0x0b.  A three-bit
193
   insertion of b'MXL at position 7 is like this:
194
 
195
     - - - -  - - - -   - - - -  - - - -
196
                    M   X L               */
197
 
198
void
199
rl78_field (int val, int pos, int sz)
200
{
201
  int valm;
202
  int bytep, bitp;
203
 
204
  if (sz > 0)
205
    {
206
      if (val < 0 || val >= (1 << sz))
207
        as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, sz);
208
    }
209
  else
210
    {
211
      sz = - sz;
212
      if (val < -(1 << (sz - 1)) || val >= (1 << (sz - 1)))
213
        as_bad (_("Value %d doesn't fit in signed %d-bit field"), val, sz);
214
    }
215
 
216
  /* This code points at 'M' in the above example.  */
217
  bytep = pos / 8;
218
  bitp = pos % 8;
219
 
220
  while (bitp + sz > 8)
221
    {
222
      int ssz = 8 - bitp;
223
      int svalm;
224
 
225
      svalm = val >> (sz - ssz);
226
      svalm = svalm & ((1 << ssz) - 1);
227
      svalm = svalm << (8 - bitp - ssz);
228
      gas_assert (bytep < rl78_bytes.n_base);
229
      rl78_bytes.base[bytep] |= svalm;
230
 
231
      bitp = 0;
232
      sz -= ssz;
233
      bytep ++;
234
    }
235
  valm = val & ((1 << sz) - 1);
236
  valm = valm << (8 - bitp - sz);
237
  gas_assert (bytep < rl78_bytes.n_base);
238
  rl78_bytes.base[bytep] |= valm;
239
}
240
 
241
/*------------------------------------------------------------------*/
242
 
243
#define RL78_SHORTOPTS ""
244
const char * md_shortopts = RL78_SHORTOPTS;
245
 
246
/* Assembler options.  */
247
struct option md_longopts[] =
248
{
249
  {NULL, no_argument, NULL, 0}
250
};
251
size_t md_longopts_size = sizeof (md_longopts);
252
 
253
int
254
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
255
{
256
  return 0;
257
}
258
 
259
void
260
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
261
{
262
}
263
 
264
 
265
static void
266
s_bss (int ignore ATTRIBUTE_UNUSED)
267
{
268
  int temp;
269
 
270
  temp = get_absolute_expression ();
271
  subseg_set (bss_section, (subsegT) temp);
272
  demand_empty_rest_of_line ();
273
}
274
 
275
/* The target specific pseudo-ops which we support.  */
276
const pseudo_typeS md_pseudo_table[] =
277
{
278
  /* Our "standard" pseudos. */
279
  { "double",   float_cons,    'd' },
280
  { "bss",      s_bss,          0 },
281
  { "3byte",    cons,           3 },
282
  { "int",      cons,           4 },
283
  { "word",     cons,           4 },
284
 
285
  /* End of list marker.  */
286
  { NULL,       NULL,           0 }
287
};
288
 
289
void
290
md_begin (void)
291
{
292
}
293
 
294
void
295
rl78_md_end (void)
296
{
297
}
298
 
299
/* Write a value out to the object file, using the appropriate endianness.  */
300
void
301
md_number_to_chars (char * buf, valueT val, int n)
302
{
303
  number_to_chars_littleendian (buf, val, n);
304
}
305
 
306
static struct
307
{
308
  char * fname;
309
  int    reloc;
310
}
311
reloc_functions[] =
312
{
313
  { "lo16", BFD_RELOC_RL78_LO16 },
314
  { "hi16", BFD_RELOC_RL78_HI16 },
315
  { "hi8",  BFD_RELOC_RL78_HI8 },
316
  { 0, 0 }
317
};
318
 
319
void
320
md_operand (expressionS * exp ATTRIBUTE_UNUSED)
321
{
322
  int reloc = 0;
323
  int i;
324
 
325
  for (i = 0; reloc_functions[i].fname; i++)
326
    {
327
      int flen = strlen (reloc_functions[i].fname);
328
 
329
      if (input_line_pointer[0] == '%'
330
          && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
331
          && input_line_pointer[flen + 1] == '(')
332
        {
333
          reloc = reloc_functions[i].reloc;
334
          input_line_pointer += flen + 2;
335
          break;
336
        }
337
    }
338
  if (reloc == 0)
339
    return;
340
 
341
  expression (exp);
342
  if (* input_line_pointer == ')')
343
    input_line_pointer ++;
344
 
345
  exp->X_md = reloc;
346
}
347
 
348
void
349
rl78_frag_init (fragS * fragP)
350
{
351
  fragP->tc_frag_data = 0;
352
}
353
 
354
char *
355
md_atof (int type, char * litP, int * sizeP)
356
{
357
  return ieee_md_atof (type, litP, sizeP, target_big_endian);
358
}
359
 
360
symbolS *
361
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
362
{
363
  return NULL;
364
}
365
 
366
#define APPEND(B, N_B)                                 \
367
  if (rl78_bytes.N_B)                                  \
368
    {                                                  \
369
      memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B);  \
370
      idx += rl78_bytes.N_B;                           \
371
    }
372
 
373
 
374
void
375
md_assemble (char * str)
376
{
377
  char * bytes;
378
  fragS * frag_then = frag_now;
379
  int idx = 0;
380
  int i;
381
  int rel;
382
  expressionS  *exp;
383
 
384
  /*printf("\033[32mASM: %s\033[0m\n", str);*/
385
 
386
  dwarf2_emit_insn (0);
387
 
388
  memset (& rl78_bytes, 0, sizeof (rl78_bytes));
389
 
390
  rl78_lex_init (str, str + strlen (str));
391
 
392
  rl78_parse ();
393
 
394
  bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
395
  frag_then = frag_now;
396
 
397
  APPEND (prefix, n_prefix);
398
  APPEND (base, n_base);
399
  APPEND (ops, n_ops);
400
 
401
  for (i = 0; i < rl78_bytes.n_fixups; i ++)
402
    {
403
      /* index: [nbytes][type] */
404
      static int reloc_map[5][4] =
405
        {
406
          { 0,            0 },
407
          { BFD_RELOC_8,  BFD_RELOC_8_PCREL },
408
          { BFD_RELOC_16, BFD_RELOC_16_PCREL },
409
          { BFD_RELOC_24, BFD_RELOC_24_PCREL },
410
          { BFD_RELOC_32, BFD_RELOC_32_PCREL },
411
        };
412
      fixS * f;
413
 
414
      idx = rl78_bytes.fixups[i].offset / 8;
415
      rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
416
 
417
      if (rl78_bytes.fixups[i].reloc)
418
        rel = rl78_bytes.fixups[i].reloc;
419
 
420
      if (frag_then->tc_frag_data)
421
        exp = & frag_then->tc_frag_data->fixups[i].exp;
422
      else
423
        exp = & rl78_bytes.fixups[i].exp;
424
 
425
      f = fix_new_exp (frag_then,
426
                       (char *) bytes + idx - frag_then->fr_literal,
427
                       rl78_bytes.fixups[i].nbits / 8,
428
                       exp,
429
                       rl78_bytes.fixups[i].type == RL78REL_PCREL ? 1 : 0,
430
                       rel);
431
      if (frag_then->tc_frag_data)
432
        frag_then->tc_frag_data->fixups[i].fixP = f;
433
    }
434
}
435
 
436
void
437
rl78_cons_fix_new (fragS *      frag,
438
                 int            where,
439
                 int            size,
440
                 expressionS *  exp)
441
{
442
  bfd_reloc_code_real_type type;
443
 
444
  switch (size)
445
    {
446
    case 1:
447
      type = BFD_RELOC_8;
448
      break;
449
    case 2:
450
      type = BFD_RELOC_16;
451
      break;
452
    case 3:
453
      type = BFD_RELOC_24;
454
      break;
455
    case 4:
456
      type = BFD_RELOC_32;
457
      break;
458
    default:
459
      as_bad (_("unsupported constant size %d\n"), size);
460
      return;
461
    }
462
 
463
  if (exp->X_op == O_subtract && exp->X_op_symbol)
464
    {
465
      if (size != 4 && size != 2 && size != 1)
466
        as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
467
      else
468
        type = BFD_RELOC_RL78_DIFF;
469
    }
470
 
471
  fix_new_exp (frag, where, (int) size, exp, 0, type);
472
}
473
 
474
/* No relaxation just yet */
475
int
476
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
477
{
478
  return 0;
479
}
480
arelent **
481
tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
482
{
483
  static arelent * reloc[8];
484
  int rp;
485
 
486
  if (fixp->fx_r_type == BFD_RELOC_NONE)
487
    {
488
      reloc[0] = NULL;
489
      return reloc;
490
    }
491
 
492
  if (fixp->fx_subsy
493
      && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
494
    {
495
      fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
496
      fixp->fx_subsy = NULL;
497
    }
498
 
499
  reloc[0]                 = (arelent *) xmalloc (sizeof (arelent));
500
  reloc[0]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));
501
  * reloc[0]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
502
  reloc[0]->address       = fixp->fx_frag->fr_address + fixp->fx_where;
503
  reloc[0]->addend        = fixp->fx_offset;
504
 
505
  if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
506
      && fixp->fx_subsy)
507
    {
508
      fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
509
    }
510
 
511
#define OPX(REL,SYM,ADD)                                                        \
512
  reloc[rp]                = (arelent *) xmalloc (sizeof (arelent));            \
513
  reloc[rp]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));         \
514
  reloc[rp]->howto         = bfd_reloc_type_lookup (stdoutput, REL);            \
515
  reloc[rp]->addend        = ADD;                                               \
516
  * reloc[rp]->sym_ptr_ptr = SYM;                                               \
517
  reloc[rp]->address       = fixp->fx_frag->fr_address + fixp->fx_where;        \
518
  reloc[++rp] = NULL
519
#define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
520
#define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
521
#define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
522
#define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
523
 
524
  rp = 1;
525
 
526
  /* Certain BFD relocations cannot be translated directly into
527
     a single (non-Red Hat) RL78 relocation, but instead need
528
     multiple RL78 relocations - handle them here.  */
529
  switch (fixp->fx_r_type)
530
    {
531
    case BFD_RELOC_RL78_DIFF:
532
      SYM0 ();
533
      OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
534
      OP(OP_SUBTRACT);
535
 
536
      switch (fixp->fx_size)
537
        {
538
        case 1:
539
          OP(ABS8);
540
          break;
541
        case 2:
542
          OP (ABS16);
543
          break;
544
        case 4:
545
          OP (ABS32);
546
          break;
547
        }
548
      break;
549
 
550
    case BFD_RELOC_RL78_NEG32:
551
      SYM0 ();
552
      OP (OP_NEG);
553
      OP (ABS32);
554
      break;
555
 
556
    case BFD_RELOC_RL78_LO16:
557
      SYM0 ();
558
      OPIMM (0xffff);
559
      OP (OP_AND);
560
      OP (ABS16);
561
      break;
562
 
563
    case BFD_RELOC_RL78_HI16:
564
      SYM0 ();
565
      OPIMM (16);
566
      OP (OP_SHRA);
567
      OP (ABS16);
568
      break;
569
 
570
    case BFD_RELOC_RL78_HI8:
571
      SYM0 ();
572
      OPIMM (16);
573
      OP (OP_SHRA);
574
      OPIMM (0xff);
575
      OP (OP_AND);
576
      OP (ABS8);
577
      break;
578
 
579
    default:
580
      reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
581
      reloc[1] = NULL;
582
      break;
583
    }
584
 
585
  return reloc;
586
}
587
 
588
int
589
rl78_validate_fix_sub (struct fix * f)
590
{
591
  /* We permit the subtraction of two symbols in a few cases.  */
592
  /* mov #sym1-sym2, R3 */
593
  if (f->fx_r_type == BFD_RELOC_RL78_32_OP)
594
    return 1;
595
  /* .long sym1-sym2 */
596
  if (f->fx_r_type == BFD_RELOC_RL78_DIFF
597
      && ! f->fx_pcrel
598
      && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
599
    return 1;
600
  return 0;
601
}
602
 
603
long
604
md_pcrel_from_section (fixS * fixP, segT sec)
605
{
606
  long rv;
607
 
608
  if (fixP->fx_addsy != NULL
609
      && (! S_IS_DEFINED (fixP->fx_addsy)
610
          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
611
    /* The symbol is undefined (or is defined but not in this section).
612
       Let the linker figure it out.  */
613
    return 0;
614
 
615
  rv = fixP->fx_frag->fr_address + fixP->fx_where;
616
  switch (fixP->fx_r_type)
617
    {
618
    case BFD_RELOC_8_PCREL:
619
      rv += 1;
620
      break;
621
    case BFD_RELOC_16_PCREL:
622
      rv += 2;
623
      break;
624
    default:
625
      break;
626
    }
627
  return rv;
628
}
629
 
630
void
631
md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
632
              valueT *     t ATTRIBUTE_UNUSED,
633
              segT         s ATTRIBUTE_UNUSED)
634
{
635
  char * op;
636
  unsigned long val;
637
 
638
  if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
639
    return;
640
  if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
641
    return;
642
 
643
  op = f->fx_frag->fr_literal + f->fx_where;
644
  val = (unsigned long) * t;
645
 
646
  switch (f->fx_r_type)
647
    {
648
    case BFD_RELOC_NONE:
649
      break;
650
 
651
    case BFD_RELOC_8:
652
    case BFD_RELOC_8_PCREL:
653
      op[0] = val;
654
      break;
655
 
656
    case BFD_RELOC_16:
657
    case BFD_RELOC_16_PCREL:
658
      op[0] = val;
659
      op[1] = val >> 8;
660
      break;
661
 
662
    case BFD_RELOC_24:
663
      op[0] = val;
664
      op[1] = val >> 8;
665
      op[2] = val >> 16;
666
      break;
667
 
668
    case BFD_RELOC_32:
669
    case BFD_RELOC_RL78_DIFF:
670
      op[0] = val;
671
      op[1] = val >> 8;
672
      op[2] = val >> 16;
673
      op[3] = val >> 24;
674
      break;
675
 
676
    default:
677
      as_bad (_("Unknown reloc in md_apply_fix: %s"),
678
              bfd_get_reloc_code_name (f->fx_r_type));
679
      break;
680
    }
681
 
682
  if (f->fx_addsy == NULL)
683
    f->fx_done = 1;
684
}
685
 
686
valueT
687
md_section_align (segT segment, valueT size)
688
{
689
  int align = bfd_get_section_alignment (stdoutput, segment);
690
  return ((size + (1 << align) - 1) & (-1 << align));
691
}
692
 
693
void
694
md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
695
                 segT    segment ATTRIBUTE_UNUSED,
696
                 fragS * fragP ATTRIBUTE_UNUSED)
697
{
698
  /* No relaxation yet */
699
}

powered by: WebSVN 2.1.0

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