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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-bfin.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 38 julius
/* tc-bfin.c -- Assembler for the ADI Blackfin.
2
   Copyright 2005, 2006, 2007
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 "bfin-defs.h"
25
#include "obstack.h"
26
#include "safe-ctype.h"
27
#ifdef OBJ_ELF
28
#include "dwarf2dbg.h"
29
#endif
30
#include "libbfd.h"
31
#include "elf/common.h"
32
#include "elf/bfin.h"
33
 
34
extern int yyparse (void);
35
struct yy_buffer_state;
36
typedef struct yy_buffer_state *YY_BUFFER_STATE;
37
extern YY_BUFFER_STATE yy_scan_string (const char *yy_str);
38
extern void yy_delete_buffer (YY_BUFFER_STATE b);
39
static parse_state parse (char *line);
40
static void bfin_s_bss PARAMS ((int));
41
static int md_chars_to_number PARAMS ((char *, int));
42
 
43
/* Global variables. */
44
struct bfin_insn *insn;
45
int last_insn_size;
46
 
47
extern struct obstack mempool;
48
FILE *errorf;
49
 
50
/* Flags to set in the elf header */
51
#define DEFAULT_FLAGS 0
52
 
53
#ifdef OBJ_FDPIC_ELF
54
# define DEFAULT_FDPIC EF_BFIN_FDPIC
55
#else
56
# define DEFAULT_FDPIC 0
57
#endif
58
 
59
static flagword bfin_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
60
static const char *bfin_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
61
 
62
/* Registers list.  */
63
struct bfin_reg_entry
64
{
65
  const char *name;
66
  int number;
67
};
68
 
69
static const struct bfin_reg_entry bfin_reg_info[] = {
70
  {"R0.L", REG_RL0},
71
  {"R1.L", REG_RL1},
72
  {"R2.L", REG_RL2},
73
  {"R3.L", REG_RL3},
74
  {"R4.L", REG_RL4},
75
  {"R5.L", REG_RL5},
76
  {"R6.L", REG_RL6},
77
  {"R7.L", REG_RL7},
78
  {"R0.H", REG_RH0},
79
  {"R1.H", REG_RH1},
80
  {"R2.H", REG_RH2},
81
  {"R3.H", REG_RH3},
82
  {"R4.H", REG_RH4},
83
  {"R5.H", REG_RH5},
84
  {"R6.H", REG_RH6},
85
  {"R7.H", REG_RH7},
86
  {"R0", REG_R0},
87
  {"R1", REG_R1},
88
  {"R2", REG_R2},
89
  {"R3", REG_R3},
90
  {"R4", REG_R4},
91
  {"R5", REG_R5},
92
  {"R6", REG_R6},
93
  {"R7", REG_R7},
94
  {"P0", REG_P0},
95
  {"P0.H", REG_P0},
96
  {"P0.L", REG_P0},
97
  {"P1", REG_P1},
98
  {"P1.H", REG_P1},
99
  {"P1.L", REG_P1},
100
  {"P2", REG_P2},
101
  {"P2.H", REG_P2},
102
  {"P2.L", REG_P2},
103
  {"P3", REG_P3},
104
  {"P3.H", REG_P3},
105
  {"P3.L", REG_P3},
106
  {"P4", REG_P4},
107
  {"P4.H", REG_P4},
108
  {"P4.L", REG_P4},
109
  {"P5", REG_P5},
110
  {"P5.H", REG_P5},
111
  {"P5.L", REG_P5},
112
  {"SP", REG_SP},
113
  {"SP.L", REG_SP},
114
  {"SP.H", REG_SP},
115
  {"FP", REG_FP},
116
  {"FP.L", REG_FP},
117
  {"FP.H", REG_FP},
118
  {"A0x", REG_A0x},
119
  {"A1x", REG_A1x},
120
  {"A0w", REG_A0w},
121
  {"A1w", REG_A1w},
122
  {"A0.x", REG_A0x},
123
  {"A1.x", REG_A1x},
124
  {"A0.w", REG_A0w},
125
  {"A1.w", REG_A1w},
126
  {"A0", REG_A0},
127
  {"A0.L", REG_A0},
128
  {"A0.H", REG_A0},
129
  {"A1", REG_A1},
130
  {"A1.L", REG_A1},
131
  {"A1.H", REG_A1},
132
  {"I0", REG_I0},
133
  {"I0.L", REG_I0},
134
  {"I0.H", REG_I0},
135
  {"I1", REG_I1},
136
  {"I1.L", REG_I1},
137
  {"I1.H", REG_I1},
138
  {"I2", REG_I2},
139
  {"I2.L", REG_I2},
140
  {"I2.H", REG_I2},
141
  {"I3", REG_I3},
142
  {"I3.L", REG_I3},
143
  {"I3.H", REG_I3},
144
  {"M0", REG_M0},
145
  {"M0.H", REG_M0},
146
  {"M0.L", REG_M0},
147
  {"M1", REG_M1},
148
  {"M1.H", REG_M1},
149
  {"M1.L", REG_M1},
150
  {"M2", REG_M2},
151
  {"M2.H", REG_M2},
152
  {"M2.L", REG_M2},
153
  {"M3", REG_M3},
154
  {"M3.H", REG_M3},
155
  {"M3.L", REG_M3},
156
  {"B0", REG_B0},
157
  {"B0.H", REG_B0},
158
  {"B0.L", REG_B0},
159
  {"B1", REG_B1},
160
  {"B1.H", REG_B1},
161
  {"B1.L", REG_B1},
162
  {"B2", REG_B2},
163
  {"B2.H", REG_B2},
164
  {"B2.L", REG_B2},
165
  {"B3", REG_B3},
166
  {"B3.H", REG_B3},
167
  {"B3.L", REG_B3},
168
  {"L0", REG_L0},
169
  {"L0.H", REG_L0},
170
  {"L0.L", REG_L0},
171
  {"L1", REG_L1},
172
  {"L1.H", REG_L1},
173
  {"L1.L", REG_L1},
174
  {"L2", REG_L2},
175
  {"L2.H", REG_L2},
176
  {"L2.L", REG_L2},
177
  {"L3", REG_L3},
178
  {"L3.H", REG_L3},
179
  {"L3.L", REG_L3},
180
  {"AZ", S_AZ},
181
  {"AN", S_AN},
182
  {"AC0", S_AC0},
183
  {"AC1", S_AC1},
184
  {"AV0", S_AV0},
185
  {"AV0S", S_AV0S},
186
  {"AV1", S_AV1},
187
  {"AV1S", S_AV1S},
188
  {"AQ", S_AQ},
189
  {"V", S_V},
190
  {"VS", S_VS},
191
  {"sftreset", REG_sftreset},
192
  {"omode", REG_omode},
193
  {"excause", REG_excause},
194
  {"emucause", REG_emucause},
195
  {"idle_req", REG_idle_req},
196
  {"hwerrcause", REG_hwerrcause},
197
  {"CC", REG_CC},
198
  {"LC0", REG_LC0},
199
  {"LC1", REG_LC1},
200
  {"ASTAT", REG_ASTAT},
201
  {"RETS", REG_RETS},
202
  {"LT0", REG_LT0},
203
  {"LB0", REG_LB0},
204
  {"LT1", REG_LT1},
205
  {"LB1", REG_LB1},
206
  {"CYCLES", REG_CYCLES},
207
  {"CYCLES2", REG_CYCLES2},
208
  {"USP", REG_USP},
209
  {"SEQSTAT", REG_SEQSTAT},
210
  {"SYSCFG", REG_SYSCFG},
211
  {"RETI", REG_RETI},
212
  {"RETX", REG_RETX},
213
  {"RETN", REG_RETN},
214
  {"RETE", REG_RETE},
215
  {"EMUDAT", REG_EMUDAT},
216
  {0, 0}
217
};
218
 
219
/* Blackfin specific function to handle FD-PIC pointer initializations.  */
220
 
221
static void
222
bfin_pic_ptr (int nbytes)
223
{
224
  expressionS exp;
225
  char *p;
226
 
227
  if (nbytes != 4)
228
    abort ();
229
 
230
#ifdef md_flush_pending_output
231
  md_flush_pending_output ();
232
#endif
233
 
234
  if (is_it_end_of_statement ())
235
    {
236
      demand_empty_rest_of_line ();
237
      return;
238
    }
239
 
240
#ifdef md_cons_align
241
  md_cons_align (nbytes);
242
#endif
243
 
244
  do
245
    {
246
      bfd_reloc_code_real_type reloc_type = BFD_RELOC_BFIN_FUNCDESC;
247
 
248
      if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
249
        {
250
          input_line_pointer += 9;
251
          expression (&exp);
252
          if (*input_line_pointer == ')')
253
            input_line_pointer++;
254
          else
255
            as_bad (_("missing ')'"));
256
        }
257
      else
258
        error ("missing funcdesc in picptr");
259
 
260
      p = frag_more (4);
261
      memset (p, 0, 4);
262
      fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
263
                   reloc_type);
264
    }
265
  while (*input_line_pointer++ == ',');
266
 
267
  input_line_pointer--;                 /* Put terminator back into stream. */
268
  demand_empty_rest_of_line ();
269
}
270
 
271
static void
272
bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
273
{
274
  register int temp;
275
 
276
  temp = get_absolute_expression ();
277
  subseg_set (bss_section, (subsegT) temp);
278
  demand_empty_rest_of_line ();
279
}
280
 
281
const pseudo_typeS md_pseudo_table[] = {
282
  {"align", s_align_bytes, 0},
283
  {"byte2", cons, 2},
284
  {"byte4", cons, 4},
285
  {"picptr", bfin_pic_ptr, 4},
286
  {"code", obj_elf_section, 0},
287
  {"db", cons, 1},
288
  {"dd", cons, 4},
289
  {"dw", cons, 2},
290
  {"p", s_ignore, 0},
291
  {"pdata", s_ignore, 0},
292
  {"var", s_ignore, 0},
293
  {"bss", bfin_s_bss, 0},
294
  {0, 0, 0}
295
};
296
 
297
/* Characters that are used to denote comments and line separators. */
298
const char comment_chars[] = "";
299
const char line_comment_chars[] = "#";
300
const char line_separator_chars[] = ";";
301
 
302
/* Characters that can be used to separate the mantissa from the
303
   exponent in floating point numbers. */
304
const char EXP_CHARS[] = "eE";
305
 
306
/* Characters that mean this number is a floating point constant.
307
   As in 0f12.456 or  0d1.2345e12.  */
308
const char FLT_CHARS[] = "fFdDxX";
309
 
310
/* Define bfin-specific command-line options (there are none). */
311
const char *md_shortopts = "";
312
 
313
#define OPTION_FDPIC            (OPTION_MD_BASE)
314
#define OPTION_NOPIC            (OPTION_MD_BASE + 1)
315
 
316
struct option md_longopts[] =
317
{
318
  { "mfdpic",           no_argument,            NULL, OPTION_FDPIC      },
319
  { "mnopic",           no_argument,            NULL, OPTION_NOPIC      },
320
  { "mno-fdpic",        no_argument,            NULL, OPTION_NOPIC      },
321
  { NULL,               no_argument,            NULL, 0                 },
322
};
323
 
324
size_t md_longopts_size = sizeof (md_longopts);
325
 
326
 
327
int
328
md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
329
{
330
  switch (c)
331
    {
332
    default:
333
      return 0;
334
 
335
    case OPTION_FDPIC:
336
      bfin_flags |= EF_BFIN_FDPIC;
337
      bfin_pic_flag = "-mfdpic";
338
      break;
339
 
340
    case OPTION_NOPIC:
341
      bfin_flags &= ~(EF_BFIN_FDPIC);
342
      bfin_pic_flag = 0;
343
      break;
344
    }
345
 
346
  return 1;
347
}
348
 
349
void
350
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
351
{
352
  fprintf (stream, _(" BFIN specific command line options:\n"));
353
}
354
 
355
/* Perform machine-specific initializations.  */
356
void
357
md_begin ()
358
{
359
  /* Set the ELF flags if desired. */
360
  if (bfin_flags)
361
    bfd_set_private_flags (stdoutput, bfin_flags);
362
 
363
  /* Set the default machine type. */
364
  if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
365
    as_warn (_("Could not set architecture and machine."));
366
 
367
  /* Ensure that lines can begin with '(', for multiple
368
     register stack pops. */
369
  lex_type ['('] = LEX_BEGIN_NAME;
370
 
371
#ifdef OBJ_ELF
372
  record_alignment (text_section, 2);
373
  record_alignment (data_section, 2);
374
  record_alignment (bss_section, 2);
375
#endif
376
 
377
  errorf = stderr;
378
  obstack_init (&mempool);
379
 
380
#ifdef DEBUG
381
  extern int debug_codeselection;
382
  debug_codeselection = 1;
383
#endif 
384
 
385
  last_insn_size = 0;
386
}
387
 
388
/* Perform the main parsing, and assembly of the input here.  Also,
389
   call the required routines for alignment and fixups here.
390
   This is called for every line that contains real assembly code.  */
391
 
392
void
393
md_assemble (char *line)
394
{
395
  char *toP = 0;
396
  extern char *current_inputline;
397
  int size, insn_size;
398
  struct bfin_insn *tmp_insn;
399
  size_t len;
400
  static size_t buffer_len = 0;
401
  parse_state state;
402
 
403
  len = strlen (line);
404
  if (len + 2 > buffer_len)
405
    {
406
      if (buffer_len > 0)
407
        free (current_inputline);
408
      buffer_len = len + 40;
409
      current_inputline = xmalloc (buffer_len);
410
    }
411
  memcpy (current_inputline, line, len);
412
  current_inputline[len] = ';';
413
  current_inputline[len + 1] = '\0';
414
 
415
  state = parse (current_inputline);
416
  if (state == NO_INSN_GENERATED)
417
    return;
418
 
419
  for (insn_size = 0, tmp_insn = insn; tmp_insn; tmp_insn = tmp_insn->next)
420
    if (!tmp_insn->reloc || !tmp_insn->exp->symbol)
421
      insn_size += 2;
422
 
423
  if (insn_size)
424
    toP = frag_more (insn_size);
425
 
426
  last_insn_size = insn_size;
427
 
428
#ifdef DEBUG
429
  printf ("INS:");
430
#endif
431
  while (insn)
432
    {
433
      if (insn->reloc && insn->exp->symbol)
434
        {
435
          char *prev_toP = toP - 2;
436
          switch (insn->reloc)
437
            {
438
            case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
439
            case BFD_RELOC_24_PCREL:
440
            case BFD_RELOC_BFIN_16_LOW:
441
            case BFD_RELOC_BFIN_16_HIGH:
442
              size = 4;
443
              break;
444
            default:
445
              size = 2;
446
            }
447
 
448
          /* Following if condition checks for the arithmetic relocations.
449
             If the case then it doesn't required to generate the code.
450
             It has been assumed that, their ID will be contiguous.  */
451
          if ((BFD_ARELOC_BFIN_PUSH <= insn->reloc
452
               && BFD_ARELOC_BFIN_COMP >= insn->reloc)
453
              || insn->reloc == BFD_RELOC_BFIN_16_IMM)
454
            {
455
              size = 2;
456
            }
457
          if (insn->reloc == BFD_ARELOC_BFIN_CONST
458
              || insn->reloc == BFD_ARELOC_BFIN_PUSH)
459
            size = 4;
460
 
461
          fix_new (frag_now,
462
                   (prev_toP - frag_now->fr_literal),
463
                   size, insn->exp->symbol, insn->exp->value,
464
                   insn->pcrel, insn->reloc);
465
        }
466
      else
467
        {
468
          md_number_to_chars (toP, insn->value, 2);
469
          toP += 2;
470
        }
471
 
472
#ifdef DEBUG
473
      printf (" reloc :");
474
      printf (" %02x%02x", ((unsigned char *) &insn->value)[0],
475
              ((unsigned char *) &insn->value)[1]);
476
      printf ("\n");
477
#endif
478
      insn = insn->next;
479
    }
480
#ifdef OBJ_ELF
481
  dwarf2_emit_insn (insn_size);
482
#endif
483
}
484
 
485
/* Parse one line of instructions, and generate opcode for it.
486
   To parse the line, YACC and LEX are used, because the instruction set
487
   syntax doesn't confirm to the AT&T assembly syntax.
488
   To call a YACC & LEX generated parser, we must provide the input via
489
   a FILE stream, otherwise stdin is used by default.  Below the input
490
   to the function will be put into a temporary file, then the generated
491
   parser uses the temporary file for parsing.  */
492
 
493
static parse_state
494
parse (char *line)
495
{
496
  parse_state state;
497
  YY_BUFFER_STATE buffstate;
498
 
499
  buffstate = yy_scan_string (line);
500
 
501
  /* our lex requires setting the start state to keyword
502
     every line as the first word may be a keyword.
503
     Fixes a bug where we could not have keywords as labels.  */
504
  set_start_state ();
505
 
506
  /* Call yyparse here.  */
507
  state = yyparse ();
508
  if (state == SEMANTIC_ERROR)
509
    {
510
      as_bad (_("Parse failed."));
511
      insn = 0;
512
    }
513
 
514
  yy_delete_buffer (buffstate);
515
  return state;
516
}
517
 
518
/* We need to handle various expressions properly.
519
   Such as, [SP--] = 34, concerned by md_assemble().  */
520
 
521
void
522
md_operand (expressionS * expressionP)
523
{
524
  if (*input_line_pointer == '[')
525
    {
526
      as_tsktsk ("We found a '['!");
527
      input_line_pointer++;
528
      expression (expressionP);
529
    }
530
}
531
 
532
/* Handle undefined symbols. */
533
symbolS *
534
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
535
{
536
  return (symbolS *) 0;
537
}
538
 
539
int
540
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
541
                               segT segment ATTRIBUTE_UNUSED)
542
{
543
  return 0;
544
}
545
 
546
/* Convert from target byte order to host byte order.  */
547
 
548
static int
549
md_chars_to_number (char *val, int n)
550
{
551
  int retval;
552
 
553
  for (retval = 0; n--;)
554
    {
555
      retval <<= 8;
556
      retval |= val[n];
557
    }
558
  return retval;
559
}
560
 
561
void
562
md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
563
{
564
  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
565
 
566
  long value = *valueP;
567
  long newval;
568
 
569
  switch (fixP->fx_r_type)
570
    {
571
    case BFD_RELOC_BFIN_GOT:
572
    case BFD_RELOC_BFIN_GOT17M4:
573
    case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
574
      fixP->fx_no_overflow = 1;
575
      newval = md_chars_to_number (where, 2);
576
      newval |= 0x0 & 0x7f;
577
      md_number_to_chars (where, newval, 2);
578
      break;
579
 
580
    case BFD_RELOC_BFIN_10_PCREL:
581
      if (!value)
582
        break;
583
      if (value < -1024 || value > 1022)
584
        as_bad_where (fixP->fx_file, fixP->fx_line,
585
                      _("pcrel too far BFD_RELOC_BFIN_10"));
586
 
587
      /* 11 bit offset even numbered, so we remove right bit.  */
588
      value = value >> 1;
589
      newval = md_chars_to_number (where, 2);
590
      newval |= value & 0x03ff;
591
      md_number_to_chars (where, newval, 2);
592
      break;
593
 
594
    case BFD_RELOC_BFIN_12_PCREL_JUMP:
595
    case BFD_RELOC_BFIN_12_PCREL_JUMP_S:
596
    case BFD_RELOC_12_PCREL:
597
      if (!value)
598
        break;
599
 
600
      if (value < -4096 || value > 4094)
601
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_12"));
602
      /* 13 bit offset even numbered, so we remove right bit.  */
603
      value = value >> 1;
604
      newval = md_chars_to_number (where, 2);
605
      newval |= value & 0xfff;
606
      md_number_to_chars (where, newval, 2);
607
      break;
608
 
609
    case BFD_RELOC_BFIN_16_LOW:
610
    case BFD_RELOC_BFIN_16_HIGH:
611
      fixP->fx_done = FALSE;
612
      break;
613
 
614
    case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
615
    case BFD_RELOC_BFIN_24_PCREL_CALL_X:
616
    case BFD_RELOC_24_PCREL:
617
      if (!value)
618
        break;
619
 
620
      if (value < -16777216 || value > 16777214)
621
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_24"));
622
 
623
      /* 25 bit offset even numbered, so we remove right bit.  */
624
      value = value >> 1;
625
      value++;
626
 
627
      md_number_to_chars (where - 2, value >> 16, 1);
628
      md_number_to_chars (where, value, 1);
629
      md_number_to_chars (where + 1, value >> 8, 1);
630
      break;
631
 
632
    case BFD_RELOC_BFIN_5_PCREL:        /* LSETUP (a, b) : "a" */
633
      if (!value)
634
        break;
635
      if (value < 4 || value > 30)
636
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_5"));
637
      value = value >> 1;
638
      newval = md_chars_to_number (where, 1);
639
      newval = (newval & 0xf0) | (value & 0xf);
640
      md_number_to_chars (where, newval, 1);
641
      break;
642
 
643
    case BFD_RELOC_BFIN_11_PCREL:       /* LSETUP (a, b) : "b" */
644
      if (!value)
645
        break;
646
      value += 2;
647
      if (value < 4 || value > 2046)
648
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_11_PCREL"));
649
      /* 11 bit unsigned even, so we remove right bit.  */
650
      value = value >> 1;
651
      newval = md_chars_to_number (where, 2);
652
      newval |= value & 0x03ff;
653
      md_number_to_chars (where, newval, 2);
654
      break;
655
 
656
    case BFD_RELOC_8:
657
      if (value < -0x80 || value >= 0x7f)
658
        as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_8"));
659
      md_number_to_chars (where, value, 1);
660
      break;
661
 
662
    case BFD_RELOC_BFIN_16_IMM:
663
    case BFD_RELOC_16:
664
      if (value < -0x8000 || value >= 0x7fff)
665
        as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_16"));
666
      md_number_to_chars (where, value, 2);
667
      break;
668
 
669
    case BFD_RELOC_32:
670
      md_number_to_chars (where, value, 4);
671
      break;
672
 
673
    case BFD_RELOC_BFIN_PLTPC:
674
      md_number_to_chars (where, value, 2);
675
      break;
676
 
677
    case BFD_RELOC_BFIN_FUNCDESC:
678
    case BFD_RELOC_VTABLE_INHERIT:
679
    case BFD_RELOC_VTABLE_ENTRY:
680
      fixP->fx_done = FALSE;
681
      break;
682
 
683
    default:
684
      if ((BFD_ARELOC_BFIN_PUSH > fixP->fx_r_type) || (BFD_ARELOC_BFIN_COMP < fixP->fx_r_type))
685
        {
686
          fprintf (stderr, "Relocation %d not handled in gas." " Contact support.\n", fixP->fx_r_type);
687
          return;
688
        }
689
    }
690
 
691
  if (!fixP->fx_addsy)
692
    fixP->fx_done = TRUE;
693
 
694
}
695
 
696
/* Round up a section size to the appropriate boundary.  */
697
valueT
698
md_section_align (segment, size)
699
     segT segment;
700
     valueT size;
701
{
702
  int boundary = bfd_get_section_alignment (stdoutput, segment);
703
  return ((size + (1 << boundary) - 1) & (-1 << boundary));
704
}
705
 
706
 
707
char *
708
md_atof (int type, char * litP, int * sizeP)
709
{
710
  return ieee_md_atof (type, litP, sizeP, FALSE);
711
}
712
 
713
 
714
/* If while processing a fixup, a reloc really needs to be created
715
   then it is done here.  */
716
 
717
arelent *
718
tc_gen_reloc (seg, fixp)
719
     asection *seg ATTRIBUTE_UNUSED;
720
     fixS *fixp;
721
{
722
  arelent *reloc;
723
 
724
  reloc               = (arelent *) xmalloc (sizeof (arelent));
725
  reloc->sym_ptr_ptr  = (asymbol **) xmalloc (sizeof (asymbol *));
726
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
727
  reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
728
 
729
  reloc->addend = fixp->fx_offset;
730
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
731
 
732
  if (reloc->howto == (reloc_howto_type *) NULL)
733
    {
734
      as_bad_where (fixp->fx_file, fixp->fx_line,
735
                    /* xgettext:c-format.  */
736
                    _("reloc %d not supported by object file format"),
737
                    (int) fixp->fx_r_type);
738
 
739
      xfree (reloc);
740
 
741
      return NULL;
742
    }
743
 
744
  return reloc;
745
}
746
 
747
/*  The location from which a PC relative jump should be calculated,
748
    given a PC relative reloc.  */
749
 
750
long
751
md_pcrel_from_section (fixP, sec)
752
     fixS *fixP;
753
     segT sec;
754
{
755
  if (fixP->fx_addsy != (symbolS *) NULL
756
      && (!S_IS_DEFINED (fixP->fx_addsy)
757
      || S_GET_SEGMENT (fixP->fx_addsy) != sec))
758
    {
759
      /* The symbol is undefined (or is defined but not in this section).
760
         Let the linker figure it out.  */
761
      return 0;
762
    }
763
  return fixP->fx_frag->fr_address + fixP->fx_where;
764
}
765
 
766
/* Return true if the fix can be handled by GAS, false if it must
767
   be passed through to the linker.  */
768
 
769
bfd_boolean
770
bfin_fix_adjustable (fixS *fixP)
771
{
772
  switch (fixP->fx_r_type)
773
    {
774
  /* Adjust_reloc_syms doesn't know about the GOT.  */
775
    case BFD_RELOC_BFIN_GOT:
776
    case BFD_RELOC_BFIN_GOT17M4:
777
    case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
778
    case BFD_RELOC_BFIN_PLTPC:
779
  /* We need the symbol name for the VTABLE entries.  */
780
    case BFD_RELOC_VTABLE_INHERIT:
781
    case BFD_RELOC_VTABLE_ENTRY:
782
      return 0;
783
 
784
    default:
785
      return 1;
786
    }
787
}
788
 
789
 
790
/* Handle the LOOP_BEGIN and LOOP_END statements.
791
   Parse the Loop_Begin/Loop_End and create a label.  */
792
void
793
bfin_start_line_hook ()
794
{
795
  bfd_boolean maybe_begin = FALSE;
796
  bfd_boolean maybe_end = FALSE;
797
 
798
  char *c1, *label_name;
799
  symbolS *line_label;
800
  char *c = input_line_pointer;
801
  int cr_num = 0;
802
 
803
  while (ISSPACE (*c))
804
    {
805
      if (*c == '\n')
806
        cr_num++;
807
      c++;
808
    }
809
 
810
  /* Look for Loop_Begin or Loop_End statements.  */
811
 
812
  if (*c != 'L' && *c != 'l')
813
    return;
814
 
815
  c++;
816
  if (*c != 'O' && *c != 'o')
817
    return;
818
 
819
  c++;
820
  if (*c != 'O' && *c != 'o')
821
    return;
822
 
823
  c++;
824
  if (*c != 'P' && *c != 'p')
825
    return;
826
 
827
  c++;
828
  if (*c != '_')
829
    return;
830
 
831
  c++;
832
  if (*c == 'E' || *c == 'e')
833
    maybe_end = TRUE;
834
  else if (*c == 'B' || *c == 'b')
835
    maybe_begin = TRUE;
836
  else
837
    return;
838
 
839
  if (maybe_end)
840
    {
841
      c++;
842
      if (*c != 'N' && *c != 'n')
843
        return;
844
 
845
      c++;
846
      if (*c != 'D' && *c != 'd')
847
        return;
848
    }
849
 
850
  if (maybe_begin)
851
    {
852
      c++;
853
      if (*c != 'E' && *c != 'e')
854
        return;
855
 
856
      c++;
857
      if (*c != 'G' && *c != 'g')
858
        return;
859
 
860
      c++;
861
      if (*c != 'I' && *c != 'i')
862
        return;
863
 
864
      c++;
865
      if (*c != 'N' && *c != 'n')
866
        return;
867
    }
868
 
869
  c++;
870
  while (ISSPACE (*c)) c++;
871
  c1 = c;
872
  while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
873
 
874
  if (input_line_pointer[-1] == '\n')
875
    bump_line_counters ();
876
 
877
  while (cr_num--)
878
    bump_line_counters ();
879
 
880
  input_line_pointer = c;
881
  if (maybe_end)
882
    {
883
      label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 5);
884
      label_name[0] = 0;
885
      strcat (label_name, "L$L$");
886
      strncat (label_name, c1, c-c1);
887
      strcat (label_name, "__END");
888
    }
889
  else /* maybe_begin.  */
890
    {
891
      label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 5);
892
      label_name[0] = 0;
893
      strcat (label_name, "L$L$");
894
      strncat (label_name, c1, c-c1);
895
      strcat (label_name, "__BEGIN");
896
    }
897
 
898
  line_label = colon (label_name);
899
 
900
  /* Loop_End follows the last instruction in the loop.
901
     Adjust label address.  */
902
  if (maybe_end)
903
    ((struct local_symbol *) line_label)->lsy_value -= last_insn_size;
904
}
905
 
906
/* Special extra functions that help bfin-parse.y perform its job.  */
907
 
908
#include <assert.h>
909
 
910
struct obstack mempool;
911
 
912
INSTR_T
913
conscode (INSTR_T head, INSTR_T tail)
914
{
915
  if (!head)
916
    return tail;
917
  head->next = tail;
918
  return head;
919
}
920
 
921
INSTR_T
922
conctcode (INSTR_T head, INSTR_T tail)
923
{
924
  INSTR_T temp = (head);
925
  if (!head)
926
    return tail;
927
  while (temp->next)
928
    temp = temp->next;
929
  temp->next = tail;
930
 
931
  return head;
932
}
933
 
934
INSTR_T
935
note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
936
{
937
  /* Assert that the symbol is not an operator.  */
938
  assert (symbol->type == Expr_Node_Reloc);
939
 
940
  return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
941
 
942
}
943
 
944
INSTR_T
945
note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
946
{
947
  code->reloc = reloc;
948
  code->exp = mkexpr (0, symbol_find_or_make (symbol));
949
  code->pcrel = pcrel;
950
  return code;
951
}
952
 
953
INSTR_T
954
note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
955
{
956
  code->reloc = reloc;
957
  code->exp = mkexpr (value, symbol_find_or_make (symbol));
958
  code->pcrel = pcrel;
959
  return code;
960
}
961
 
962
INSTR_T
963
gencode (unsigned long x)
964
{
965
  INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
966
  memset (cell, 0, sizeof (struct bfin_insn));
967
  cell->value = (x);
968
  return cell;
969
}
970
 
971
int reloc;
972
int ninsns;
973
int count_insns;
974
 
975
static void *
976
allocate (int n)
977
{
978
  return (void *) obstack_alloc (&mempool, n);
979
}
980
 
981
Expr_Node *
982
Expr_Node_Create (Expr_Node_Type type,
983
                  Expr_Node_Value value,
984
                  Expr_Node *Left_Child,
985
                  Expr_Node *Right_Child)
986
{
987
 
988
 
989
  Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
990
  node->type = type;
991
  node->value = value;
992
  node->Left_Child = Left_Child;
993
  node->Right_Child = Right_Child;
994
  return node;
995
}
996
 
997
static const char *con = ".__constant";
998
static const char *op = ".__operator";
999
static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
1000
INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
1001
 
1002
INSTR_T
1003
Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
1004
{
1005
  /* Top level reloction expression generator VDSP style.
1006
   If the relocation is just by itself, generate one item
1007
   else generate this convoluted expression.  */
1008
 
1009
  INSTR_T note = NULL_CODE;
1010
  INSTR_T note1 = NULL_CODE;
1011
  int pcrel = 1;  /* Is the parent reloc pcrelative?
1012
                  This calculation here and HOWTO should match.  */
1013
 
1014
  if (parent_reloc)
1015
    {
1016
      /*  If it's 32 bit quantity then 16bit code needs to be added.  */
1017
      int value = 0;
1018
 
1019
      if (head->type == Expr_Node_Constant)
1020
        {
1021
          /* If note1 is not null code, we have to generate a right
1022
             aligned value for the constant. Otherwise the reloc is
1023
             a part of the basic command and the yacc file
1024
             generates this.  */
1025
          value = head->value.i_value;
1026
        }
1027
      switch (parent_reloc)
1028
        {
1029
          /*  Some relocations will need to allocate extra words.  */
1030
        case BFD_RELOC_BFIN_16_IMM:
1031
        case BFD_RELOC_BFIN_16_LOW:
1032
        case BFD_RELOC_BFIN_16_HIGH:
1033
          note1 = conscode (gencode (value), NULL_CODE);
1034
          pcrel = 0;
1035
          break;
1036
        case BFD_RELOC_BFIN_PLTPC:
1037
          note1 = conscode (gencode (value), NULL_CODE);
1038
          pcrel = 0;
1039
          break;
1040
        case BFD_RELOC_16:
1041
        case BFD_RELOC_BFIN_GOT:
1042
        case BFD_RELOC_BFIN_GOT17M4:
1043
        case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
1044
          note1 = conscode (gencode (value), NULL_CODE);
1045
          pcrel = 0;
1046
          break;
1047
        case BFD_RELOC_24_PCREL:
1048
        case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
1049
        case BFD_RELOC_BFIN_24_PCREL_CALL_X:
1050
          /* These offsets are even numbered pcrel.  */
1051
          note1 = conscode (gencode (value >> 1), NULL_CODE);
1052
          break;
1053
        default:
1054
          note1 = NULL_CODE;
1055
        }
1056
    }
1057
  if (head->type == Expr_Node_Constant)
1058
    note = note1;
1059
  else if (head->type == Expr_Node_Reloc)
1060
    {
1061
      note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
1062
      if (note1 != NULL_CODE)
1063
        note = conscode (note1, note);
1064
    }
1065
  else if (head->type == Expr_Node_Binop
1066
           && (head->value.op_value == Expr_Op_Type_Add
1067
               || head->value.op_value == Expr_Op_Type_Sub)
1068
           && head->Left_Child->type == Expr_Node_Reloc
1069
           && head->Right_Child->type == Expr_Node_Constant)
1070
    {
1071
      int val = head->Right_Child->value.i_value;
1072
      if (head->value.op_value == Expr_Op_Type_Sub)
1073
        val = -val;
1074
      note = conscode (note_reloc2 (gencode (0), head->Left_Child->value.s_value,
1075
                                    parent_reloc, val, 0),
1076
                       NULL_CODE);
1077
      if (note1 != NULL_CODE)
1078
        note = conscode (note1, note);
1079
    }
1080
  else
1081
    {
1082
      /* Call the recursive function.  */
1083
      note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
1084
      if (note1 != NULL_CODE)
1085
        note = conscode (note1, note);
1086
      note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
1087
    }
1088
  return note;
1089
}
1090
 
1091
static INSTR_T
1092
Expr_Node_Gen_Reloc_R (Expr_Node * head)
1093
{
1094
 
1095
  INSTR_T note = 0;
1096
  INSTR_T note1 = 0;
1097
 
1098
  switch (head->type)
1099
    {
1100
    case Expr_Node_Constant:
1101
      note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
1102
      break;
1103
    case Expr_Node_Reloc:
1104
      note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
1105
      break;
1106
    case Expr_Node_Binop:
1107
      note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
1108
      switch (head->value.op_value)
1109
        {
1110
        case Expr_Op_Type_Add:
1111
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
1112
          break;
1113
        case Expr_Op_Type_Sub:
1114
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
1115
          break;
1116
        case Expr_Op_Type_Mult:
1117
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
1118
          break;
1119
        case Expr_Op_Type_Div:
1120
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
1121
          break;
1122
        case Expr_Op_Type_Mod:
1123
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
1124
          break;
1125
        case Expr_Op_Type_Lshift:
1126
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
1127
          break;
1128
        case Expr_Op_Type_Rshift:
1129
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
1130
          break;
1131
        case Expr_Op_Type_BAND:
1132
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
1133
          break;
1134
        case Expr_Op_Type_BOR:
1135
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
1136
          break;
1137
        case Expr_Op_Type_BXOR:
1138
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
1139
          break;
1140
        case Expr_Op_Type_LAND:
1141
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
1142
          break;
1143
        case Expr_Op_Type_LOR:
1144
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
1145
          break;
1146
        default:
1147
          fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
1148
 
1149
 
1150
        }
1151
      break;
1152
    case Expr_Node_Unop:
1153
      note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
1154
      switch (head->value.op_value)
1155
        {
1156
        case Expr_Op_Type_NEG:
1157
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
1158
          break;
1159
        case Expr_Op_Type_COMP:
1160
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
1161
          break;
1162
        default:
1163
          fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
1164
        }
1165
      break;
1166
    default:
1167
      fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
1168
    }
1169
  return note;
1170
}
1171
 
1172
 
1173
/* Blackfin opcode generation.  */
1174
 
1175
/* These functions are called by the generated parser
1176
   (from bfin-parse.y), the register type classification
1177
   happens in bfin-lex.l.  */
1178
 
1179
#include "bfin-aux.h"
1180
#include "opcode/bfin.h"
1181
 
1182
#define INIT(t)  t c_code = init_##t
1183
#define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
1184
#define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
1185
 
1186
#define HI(x) ((x >> 16) & 0xffff)
1187
#define LO(x) ((x      ) & 0xffff)
1188
 
1189
#define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
1190
 
1191
#define GEN_OPCODE32()  \
1192
        conscode (gencode (HI (c_code.opcode)), \
1193
        conscode (gencode (LO (c_code.opcode)), NULL_CODE))
1194
 
1195
#define GEN_OPCODE16()  \
1196
        conscode (gencode (c_code.opcode), NULL_CODE)
1197
 
1198
 
1199
/*  32 BIT INSTRUCTIONS.  */
1200
 
1201
 
1202
/* DSP32 instruction generation.  */
1203
 
1204
INSTR_T
1205
bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
1206
                   int h01, int h11, int h00, int h10, int op0,
1207
                   REG_T dst, REG_T src0, REG_T src1, int w0)
1208
{
1209
  INIT (DSP32Mac);
1210
 
1211
  ASSIGN (op0);
1212
  ASSIGN (op1);
1213
  ASSIGN (MM);
1214
  ASSIGN (mmod);
1215
  ASSIGN (w0);
1216
  ASSIGN (w1);
1217
  ASSIGN (h01);
1218
  ASSIGN (h11);
1219
  ASSIGN (h00);
1220
  ASSIGN (h10);
1221
  ASSIGN (P);
1222
 
1223
  /* If we have full reg assignments, mask out LSB to encode
1224
  single or simultaneous even/odd register moves.  */
1225
  if (P)
1226
    {
1227
      dst->regno &= 0x06;
1228
    }
1229
 
1230
  ASSIGN_R (dst);
1231
  ASSIGN_R (src0);
1232
  ASSIGN_R (src1);
1233
 
1234
  return GEN_OPCODE32 ();
1235
}
1236
 
1237
INSTR_T
1238
bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
1239
                    int h01, int h11, int h00, int h10, int op0,
1240
                    REG_T dst, REG_T src0, REG_T src1, int w0)
1241
{
1242
  INIT (DSP32Mult);
1243
 
1244
  ASSIGN (op0);
1245
  ASSIGN (op1);
1246
  ASSIGN (MM);
1247
  ASSIGN (mmod);
1248
  ASSIGN (w0);
1249
  ASSIGN (w1);
1250
  ASSIGN (h01);
1251
  ASSIGN (h11);
1252
  ASSIGN (h00);
1253
  ASSIGN (h10);
1254
  ASSIGN (P);
1255
 
1256
  if (P)
1257
    {
1258
      dst->regno &= 0x06;
1259
    }
1260
 
1261
  ASSIGN_R (dst);
1262
  ASSIGN_R (src0);
1263
  ASSIGN_R (src1);
1264
 
1265
  return GEN_OPCODE32 ();
1266
}
1267
 
1268
INSTR_T
1269
bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
1270
              REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
1271
{
1272
  INIT (DSP32Alu);
1273
 
1274
  ASSIGN (HL);
1275
  ASSIGN (aopcde);
1276
  ASSIGN (aop);
1277
  ASSIGN (s);
1278
  ASSIGN (x);
1279
  ASSIGN_R (dst0);
1280
  ASSIGN_R (dst1);
1281
  ASSIGN_R (src0);
1282
  ASSIGN_R (src1);
1283
 
1284
  return GEN_OPCODE32 ();
1285
}
1286
 
1287
INSTR_T
1288
bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
1289
                REG_T src1, int sop, int HLs)
1290
{
1291
  INIT (DSP32Shift);
1292
 
1293
  ASSIGN (sopcde);
1294
  ASSIGN (sop);
1295
  ASSIGN (HLs);
1296
 
1297
  ASSIGN_R (dst0);
1298
  ASSIGN_R (src0);
1299
  ASSIGN_R (src1);
1300
 
1301
  return GEN_OPCODE32 ();
1302
}
1303
 
1304
INSTR_T
1305
bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
1306
                   REG_T src1, int sop, int HLs)
1307
{
1308
  INIT (DSP32ShiftImm);
1309
 
1310
  ASSIGN (sopcde);
1311
  ASSIGN (sop);
1312
  ASSIGN (HLs);
1313
 
1314
  ASSIGN_R (dst0);
1315
  ASSIGN (immag);
1316
  ASSIGN_R (src1);
1317
 
1318
  return GEN_OPCODE32 ();
1319
}
1320
 
1321
/* LOOP SETUP.  */
1322
 
1323
INSTR_T
1324
bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
1325
               Expr_Node * peoffset, REG_T reg)
1326
{
1327
  int soffset, eoffset;
1328
  INIT (LoopSetup);
1329
 
1330
  soffset = (EXPR_VALUE (psoffset) >> 1);
1331
  ASSIGN (soffset);
1332
  eoffset = (EXPR_VALUE (peoffset) >> 1);
1333
  ASSIGN (eoffset);
1334
  ASSIGN (rop);
1335
  ASSIGN_R (c);
1336
  ASSIGN_R (reg);
1337
 
1338
  return
1339
      conscode (gencode (HI (c_code.opcode)),
1340
                conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
1341
                           conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
1342
 
1343
}
1344
 
1345
/*  Call, Link.  */
1346
 
1347
INSTR_T
1348
bfin_gen_calla (Expr_Node * addr, int S)
1349
{
1350
  int val;
1351
  int high_val;
1352
  int reloc = 0;
1353
  INIT (CALLa);
1354
 
1355
  switch(S){
1356
   case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
1357
   case 1 : reloc = BFD_RELOC_24_PCREL; break;
1358
   case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
1359
   default : break;
1360
  }
1361
 
1362
  ASSIGN (S);
1363
 
1364
  val = EXPR_VALUE (addr) >> 1;
1365
  high_val = val >> 16;
1366
 
1367
  return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
1368
                     Expr_Node_Gen_Reloc (addr, reloc));
1369
  }
1370
 
1371
INSTR_T
1372
bfin_gen_linkage (int R, int framesize)
1373
{
1374
  INIT (Linkage);
1375
 
1376
  ASSIGN (R);
1377
  ASSIGN (framesize);
1378
 
1379
  return GEN_OPCODE32 ();
1380
}
1381
 
1382
 
1383
/* Load and Store.  */
1384
 
1385
INSTR_T
1386
bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
1387
{
1388
  int grp, hword;
1389
  unsigned val = EXPR_VALUE (phword);
1390
  INIT (LDIMMhalf);
1391
 
1392
  ASSIGN (H);
1393
  ASSIGN (S);
1394
  ASSIGN (Z);
1395
 
1396
  ASSIGN_R (reg);
1397
  grp = (GROUP (reg));
1398
  ASSIGN (grp);
1399
  if (reloc == 2)
1400
    {
1401
      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
1402
    }
1403
  else if (reloc == 1)
1404
    {
1405
      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, IS_H (*reg) ? BFD_RELOC_BFIN_16_HIGH : BFD_RELOC_BFIN_16_LOW));
1406
    }
1407
  else
1408
    {
1409
      hword = val;
1410
      ASSIGN (hword);
1411
    }
1412
  return GEN_OPCODE32 ();
1413
}
1414
 
1415
INSTR_T
1416
bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
1417
{
1418
  INIT (LDSTidxI);
1419
 
1420
  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
1421
    {
1422
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1423
      return 0;
1424
    }
1425
 
1426
  ASSIGN_R (ptr);
1427
  ASSIGN_R (reg);
1428
  ASSIGN (W);
1429
  ASSIGN (sz);
1430
 
1431
  ASSIGN (Z);
1432
 
1433
  if (poffset->type != Expr_Node_Constant)
1434
    {
1435
      /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
1436
      /* distinguish between R0 = [P5 + symbol@GOT] and
1437
         P5 = [P5 + _current_shared_library_p5_offset_]
1438
      */
1439
      if (poffset->type == Expr_Node_Reloc
1440
          && !strcmp (poffset->value.s_value,
1441
                      "_current_shared_library_p5_offset_"))
1442
        {
1443
          return  conscode (gencode (HI (c_code.opcode)),
1444
                            Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
1445
        }
1446
      else if (poffset->type != Expr_Node_GOT_Reloc)
1447
        abort ();
1448
 
1449
      return conscode (gencode (HI (c_code.opcode)),
1450
                       Expr_Node_Gen_Reloc(poffset->Left_Child,
1451
                                           poffset->value.i_value));
1452
    }
1453
  else
1454
    {
1455
      int value, offset;
1456
      switch (sz)
1457
        {                               // load/store access size
1458
        case 0:                  // 32 bit
1459
          value = EXPR_VALUE (poffset) >> 2;
1460
          break;
1461
        case 1:                 // 16 bit
1462
          value = EXPR_VALUE (poffset) >> 1;
1463
          break;
1464
        case 2:                 // 8 bit
1465
          value = EXPR_VALUE (poffset);
1466
          break;
1467
        default:
1468
          abort ();
1469
        }
1470
 
1471
      offset = (value & 0xffff);
1472
      ASSIGN (offset);
1473
      return GEN_OPCODE32 ();
1474
    }
1475
}
1476
 
1477
 
1478
INSTR_T
1479
bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
1480
{
1481
  INIT (LDST);
1482
 
1483
  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
1484
    {
1485
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1486
      return 0;
1487
    }
1488
 
1489
  ASSIGN_R (ptr);
1490
  ASSIGN_R (reg);
1491
  ASSIGN (aop);
1492
  ASSIGN (sz);
1493
  ASSIGN (Z);
1494
  ASSIGN (W);
1495
 
1496
  return GEN_OPCODE16 ();
1497
}
1498
 
1499
INSTR_T
1500
bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
1501
{
1502
  int offset;
1503
  int value = 0;
1504
  INIT (LDSTii);
1505
 
1506
 
1507
  if (!IS_PREG (*ptr))
1508
    {
1509
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1510
      return 0;
1511
    }
1512
 
1513
  switch (op)
1514
    {
1515
    case 1:
1516
    case 2:
1517
      value = EXPR_VALUE (poffset) >> 1;
1518
      break;
1519
    case 0:
1520
    case 3:
1521
      value = EXPR_VALUE (poffset) >> 2;
1522
      break;
1523
    }
1524
 
1525
  ASSIGN_R (ptr);
1526
  ASSIGN_R (reg);
1527
 
1528
  offset = value;
1529
  ASSIGN (offset);
1530
  ASSIGN (W);
1531
  ASSIGN (op);
1532
 
1533
  return GEN_OPCODE16 ();
1534
}
1535
 
1536
INSTR_T
1537
bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
1538
{
1539
  /* Set bit 4 if it's a Preg.  */
1540
  int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
1541
  int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
1542
  INIT (LDSTiiFP);
1543
  ASSIGN (reg);
1544
  ASSIGN (offset);
1545
  ASSIGN (W);
1546
 
1547
  return GEN_OPCODE16 ();
1548
}
1549
 
1550
INSTR_T
1551
bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
1552
{
1553
  INIT (LDSTpmod);
1554
 
1555
  ASSIGN_R (ptr);
1556
  ASSIGN_R (reg);
1557
  ASSIGN (aop);
1558
  ASSIGN (W);
1559
  ASSIGN_R (idx);
1560
 
1561
  return GEN_OPCODE16 ();
1562
}
1563
 
1564
INSTR_T
1565
bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
1566
{
1567
  INIT (DspLDST);
1568
 
1569
  ASSIGN_R (i);
1570
  ASSIGN_R (reg);
1571
  ASSIGN (aop);
1572
  ASSIGN (W);
1573
  ASSIGN (m);
1574
 
1575
  return GEN_OPCODE16 ();
1576
}
1577
 
1578
INSTR_T
1579
bfin_gen_logi2op (int opc, int src, int dst)
1580
{
1581
  INIT (LOGI2op);
1582
 
1583
  ASSIGN (opc);
1584
  ASSIGN (src);
1585
  ASSIGN (dst);
1586
 
1587
  return GEN_OPCODE16 ();
1588
}
1589
 
1590
INSTR_T
1591
bfin_gen_brcc (int T, int B, Expr_Node * poffset)
1592
{
1593
  int offset;
1594
  INIT (BRCC);
1595
 
1596
  ASSIGN (T);
1597
  ASSIGN (B);
1598
  offset = ((EXPR_VALUE (poffset) >> 1));
1599
  ASSIGN (offset);
1600
  return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
1601
}
1602
 
1603
INSTR_T
1604
bfin_gen_ujump (Expr_Node * poffset)
1605
{
1606
  int offset;
1607
  INIT (UJump);
1608
 
1609
  offset = ((EXPR_VALUE (poffset) >> 1));
1610
  ASSIGN (offset);
1611
 
1612
  return conscode (gencode (c_code.opcode),
1613
                   Expr_Node_Gen_Reloc (
1614
                       poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
1615
}
1616
 
1617
INSTR_T
1618
bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
1619
{
1620
  INIT (ALU2op);
1621
 
1622
  ASSIGN_R (dst);
1623
  ASSIGN_R (src);
1624
  ASSIGN (opc);
1625
 
1626
  return GEN_OPCODE16 ();
1627
}
1628
 
1629
INSTR_T
1630
bfin_gen_compi2opd (REG_T dst, int src, int op)
1631
{
1632
  INIT (COMPI2opD);
1633
 
1634
  ASSIGN_R (dst);
1635
  ASSIGN (src);
1636
  ASSIGN (op);
1637
 
1638
  return GEN_OPCODE16 ();
1639
}
1640
 
1641
INSTR_T
1642
bfin_gen_compi2opp (REG_T dst, int src, int op)
1643
{
1644
  INIT (COMPI2opP);
1645
 
1646
  ASSIGN_R (dst);
1647
  ASSIGN (src);
1648
  ASSIGN (op);
1649
 
1650
  return GEN_OPCODE16 ();
1651
}
1652
 
1653
INSTR_T
1654
bfin_gen_dagmodik (REG_T i, int op)
1655
{
1656
  INIT (DagMODik);
1657
 
1658
  ASSIGN_R (i);
1659
  ASSIGN (op);
1660
 
1661
  return GEN_OPCODE16 ();
1662
}
1663
 
1664
INSTR_T
1665
bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
1666
{
1667
  INIT (DagMODim);
1668
 
1669
  ASSIGN_R (i);
1670
  ASSIGN_R (m);
1671
  ASSIGN (op);
1672
  ASSIGN (br);
1673
 
1674
  return GEN_OPCODE16 ();
1675
}
1676
 
1677
INSTR_T
1678
bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
1679
{
1680
  INIT (PTR2op);
1681
 
1682
  ASSIGN_R (dst);
1683
  ASSIGN_R (src);
1684
  ASSIGN (opc);
1685
 
1686
  return GEN_OPCODE16 ();
1687
}
1688
 
1689
INSTR_T
1690
bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
1691
{
1692
  INIT (COMP3op);
1693
 
1694
  ASSIGN_R (src0);
1695
  ASSIGN_R (src1);
1696
  ASSIGN_R (dst);
1697
  ASSIGN (opc);
1698
 
1699
  return GEN_OPCODE16 ();
1700
}
1701
 
1702
INSTR_T
1703
bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
1704
{
1705
  INIT (CCflag);
1706
 
1707
  ASSIGN_R (x);
1708
  ASSIGN (y);
1709
  ASSIGN (opc);
1710
  ASSIGN (I);
1711
  ASSIGN (G);
1712
 
1713
  return GEN_OPCODE16 ();
1714
}
1715
 
1716
INSTR_T
1717
bfin_gen_ccmv (REG_T src, REG_T dst, int T)
1718
{
1719
  int s, d;
1720
  INIT (CCmv);
1721
 
1722
  ASSIGN_R (src);
1723
  ASSIGN_R (dst);
1724
  s = (GROUP (src));
1725
  ASSIGN (s);
1726
  d = (GROUP (dst));
1727
  ASSIGN (d);
1728
  ASSIGN (T);
1729
 
1730
  return GEN_OPCODE16 ();
1731
}
1732
 
1733
INSTR_T
1734
bfin_gen_cc2stat (int cbit, int op, int D)
1735
{
1736
  INIT (CC2stat);
1737
 
1738
  ASSIGN (cbit);
1739
  ASSIGN (op);
1740
  ASSIGN (D);
1741
 
1742
  return GEN_OPCODE16 ();
1743
}
1744
 
1745
INSTR_T
1746
bfin_gen_regmv (REG_T src, REG_T dst)
1747
{
1748
  int gs, gd;
1749
  INIT (RegMv);
1750
 
1751
  ASSIGN_R (src);
1752
  ASSIGN_R (dst);
1753
 
1754
  gs = (GROUP (src));
1755
  ASSIGN (gs);
1756
  gd = (GROUP (dst));
1757
  ASSIGN (gd);
1758
 
1759
  return GEN_OPCODE16 ();
1760
}
1761
 
1762
INSTR_T
1763
bfin_gen_cc2dreg (int op, REG_T reg)
1764
{
1765
  INIT (CC2dreg);
1766
 
1767
  ASSIGN (op);
1768
  ASSIGN_R (reg);
1769
 
1770
  return GEN_OPCODE16 ();
1771
}
1772
 
1773
INSTR_T
1774
bfin_gen_progctrl (int prgfunc, int poprnd)
1775
{
1776
  INIT (ProgCtrl);
1777
 
1778
  ASSIGN (prgfunc);
1779
  ASSIGN (poprnd);
1780
 
1781
  return GEN_OPCODE16 ();
1782
}
1783
 
1784
INSTR_T
1785
bfin_gen_cactrl (REG_T reg, int a, int op)
1786
{
1787
  INIT (CaCTRL);
1788
 
1789
  ASSIGN_R (reg);
1790
  ASSIGN (a);
1791
  ASSIGN (op);
1792
 
1793
  return GEN_OPCODE16 ();
1794
}
1795
 
1796
INSTR_T
1797
bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
1798
{
1799
  INIT (PushPopMultiple);
1800
 
1801
  ASSIGN (dr);
1802
  ASSIGN (pr);
1803
  ASSIGN (d);
1804
  ASSIGN (p);
1805
  ASSIGN (W);
1806
 
1807
  return GEN_OPCODE16 ();
1808
}
1809
 
1810
INSTR_T
1811
bfin_gen_pushpopreg (REG_T reg, int W)
1812
{
1813
  int grp;
1814
  INIT (PushPopReg);
1815
 
1816
  ASSIGN_R (reg);
1817
  grp = (GROUP (reg));
1818
  ASSIGN (grp);
1819
  ASSIGN (W);
1820
 
1821
  return GEN_OPCODE16 ();
1822
}
1823
 
1824
/* Pseudo Debugging Support.  */
1825
 
1826
INSTR_T
1827
bfin_gen_pseudodbg (int fn, int reg, int grp)
1828
{
1829
  INIT (PseudoDbg);
1830
 
1831
  ASSIGN (fn);
1832
  ASSIGN (reg);
1833
  ASSIGN (grp);
1834
 
1835
  return GEN_OPCODE16 ();
1836
}
1837
 
1838
INSTR_T
1839
bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
1840
{
1841
  INIT (PseudoDbg_Assert);
1842
 
1843
  ASSIGN (dbgop);
1844
  ASSIGN_R (regtest);
1845
  ASSIGN (expected);
1846
 
1847
  return GEN_OPCODE32 ();
1848
}
1849
 
1850
/* Multiple instruction generation.  */
1851
 
1852
INSTR_T
1853
bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
1854
{
1855
  INSTR_T walk;
1856
 
1857
  /* If it's a 0, convert into MNOP. */
1858
  if (dsp32)
1859
    {
1860
      walk = dsp32->next;
1861
      SET_MULTI_INSTRUCTION_BIT (dsp32);
1862
    }
1863
  else
1864
    {
1865
      dsp32 = gencode (0xc803);
1866
      walk = gencode (0x1800);
1867
      dsp32->next = walk;
1868
    }
1869
 
1870
  if (!dsp16_grp1)
1871
    {
1872
      dsp16_grp1 = gencode (0x0000);
1873
    }
1874
 
1875
  if (!dsp16_grp2)
1876
    {
1877
      dsp16_grp2 = gencode (0x0000);
1878
    }
1879
 
1880
  walk->next = dsp16_grp1;
1881
  dsp16_grp1->next = dsp16_grp2;
1882
  dsp16_grp2->next = NULL_CODE;
1883
 
1884
  return dsp32;
1885
}
1886
 
1887
INSTR_T
1888
bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
1889
{
1890
  const char *loopsym;
1891
  char *lbeginsym, *lendsym;
1892
  Expr_Node_Value lbeginval, lendval;
1893
  Expr_Node *lbegin, *lend;
1894
 
1895
  loopsym = expr->value.s_value;
1896
  lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 5);
1897
  lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 5);
1898
 
1899
  lbeginsym[0] = 0;
1900
  lendsym[0] = 0;
1901
 
1902
  strcat (lbeginsym, "L$L$");
1903
  strcat (lbeginsym, loopsym);
1904
  strcat (lbeginsym, "__BEGIN");
1905
 
1906
  strcat (lendsym, "L$L$");
1907
  strcat (lendsym, loopsym);
1908
  strcat (lendsym, "__END");
1909
 
1910
  lbeginval.s_value = lbeginsym;
1911
  lendval.s_value = lendsym;
1912
 
1913
  lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
1914
  lend   = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
1915
  return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
1916
}
1917
 
1918
bfd_boolean
1919
bfin_eol_in_insn (char *line)
1920
{
1921
   /* Allow a new-line to appear in the middle of a multi-issue instruction.  */
1922
 
1923
   char *temp = line;
1924
 
1925
  if (*line != '\n')
1926
    return FALSE;
1927
 
1928
  /* A semi-colon followed by a newline is always the end of a line.  */
1929
  if (line[-1] == ';')
1930
    return FALSE;
1931
 
1932
  if (line[-1] == '|')
1933
    return TRUE;
1934
 
1935
  /* If the || is on the next line, there might be leading whitespace.  */
1936
  temp++;
1937
  while (*temp == ' ' || *temp == '\t') temp++;
1938
 
1939
  if (*temp == '|')
1940
    return TRUE;
1941
 
1942
  return FALSE;
1943
}
1944
 
1945
bfd_boolean
1946
bfin_start_label (char *ptr)
1947
{
1948
  ptr--;
1949
  while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
1950
    ptr--;
1951
 
1952
  ptr++;
1953
  if (*ptr == '(' || *ptr == '[')
1954
    return FALSE;
1955
 
1956
  return TRUE;
1957
}
1958
 
1959
int
1960
bfin_force_relocation (struct fix *fixp)
1961
{
1962
  if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
1963
      || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
1964
    return TRUE;
1965
 
1966
  return generic_force_reloc (fixp);
1967
}

powered by: WebSVN 2.1.0

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