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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 16 khays
/* tc-iq2000.c -- Assembler for the Sitera IQ2000.
2
   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010
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
19
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20
   Boston, MA 02110-1301, USA.  */
21
 
22
#include "as.h"
23
#include "safe-ctype.h"
24
#include "subsegs.h"
25
#include "symcat.h"
26
#include "opcodes/iq2000-desc.h"
27
#include "opcodes/iq2000-opc.h"
28
#include "cgen.h"
29
#include "elf/common.h"
30
#include "elf/iq2000.h"
31
#include "libbfd.h"
32
#include "sb.h"
33
#include "macro.h"
34
 
35
/* Structure to hold all of the different components describing
36
   an individual instruction.  */
37
typedef struct
38
{
39
  const CGEN_INSN *     insn;
40
  const CGEN_INSN *     orig_insn;
41
  CGEN_FIELDS           fields;
42
#if CGEN_INT_INSN_P
43
  CGEN_INSN_INT         buffer [1];
44
#define INSN_VALUE(buf) (*(buf))
45
#else
46
  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
47
#define INSN_VALUE(buf) (buf)
48
#endif
49
  char *                addr;
50
  fragS *               frag;
51
  int                   num_fixups;
52
  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
53
  int                   indices [MAX_OPERAND_INSTANCES];
54
}
55
iq2000_insn;
56
 
57
const char comment_chars[]        = "#";
58
const char line_comment_chars[]   = "#";
59
const char line_separator_chars[] = ";";
60
const char EXP_CHARS[]            = "eE";
61
const char FLT_CHARS[]            = "dD";
62
 
63
/* Default machine.  */
64
#define DEFAULT_MACHINE bfd_mach_iq2000
65
#define DEFAULT_FLAGS   EF_IQ2000_CPU_IQ2000
66
 
67
static unsigned long iq2000_mach = bfd_mach_iq2000;
68
static int cpu_mach = (1 << MACH_IQ2000);
69
 
70
/* Flags to set in the elf header.  */
71
static flagword iq2000_flags = DEFAULT_FLAGS;
72
 
73
typedef struct proc
74
{
75
  symbolS *isym;
76
  unsigned long reg_mask;
77
  unsigned long reg_offset;
78
  unsigned long fpreg_mask;
79
  unsigned long fpreg_offset;
80
  unsigned long frame_offset;
81
  unsigned long frame_reg;
82
  unsigned long pc_reg;
83
} procS;
84
 
85
static procS cur_proc;
86
static procS *cur_proc_ptr;
87
static int numprocs;
88
 
89
/* Relocations against symbols are done in two
90
   parts, with a HI relocation and a LO relocation.  Each relocation
91
   has only 16 bits of space to store an addend.  This means that in
92
   order for the linker to handle carries correctly, it must be able
93
   to locate both the HI and the LO relocation.  This means that the
94
   relocations must appear in order in the relocation table.
95
 
96
   In order to implement this, we keep track of each unmatched HI
97
   relocation.  We then sort them so that they immediately precede the
98
   corresponding LO relocation.  */
99
 
100
struct iq2000_hi_fixup
101
{
102
  struct iq2000_hi_fixup * next;  /* Next HI fixup.  */
103
  fixS *                  fixp;   /* This fixup.  */
104
  segT                    seg;    /* The section this fixup is in.  */
105
};
106
 
107
/* The list of unmatched HI relocs.  */
108
static struct iq2000_hi_fixup * iq2000_hi_fixup_list;
109
 
110
/* Macro hash table, which we will add to.  */
111
extern struct hash_control *macro_hash;
112
 
113
const char *md_shortopts = "";
114
struct option md_longopts[] =
115
{
116
  {NULL, no_argument, NULL, 0}
117
};
118
size_t md_longopts_size = sizeof (md_longopts);
119
 
120
int
121
md_parse_option (int c ATTRIBUTE_UNUSED,
122
                 char * arg ATTRIBUTE_UNUSED)
123
{
124
  return 0;
125
}
126
 
127
void
128
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
129
{
130
}
131
 
132
/* Automatically enter conditional branch macros.  */
133
 
134
typedef struct
135
{
136
  const char * mnemonic;
137
  const char ** expansion;
138
  const char ** args;
139
} iq2000_macro_defs_s;
140
 
141
static const char * abs_args[] = { "rd", "rs", "scratch=%1", NULL };
142
static const char * abs_expn   = "\n sra \\rd,\\rs,31\n xor \\scratch,\\rd,\\rs\n sub \\rd,\\scratch,\\rd\n";
143
static const char * la_expn    = "\n lui \\reg,%hi(\\label)\n ori \\reg,\\reg,%lo(\\label)\n";
144
static const char * la_args[]  = { "reg", "label", NULL };
145
static const char * bxx_args[] = { "rs", "rt", "label", "scratch=%1", NULL };
146
static const char * bge_expn   = "\n slt \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
147
static const char * bgeu_expn  = "\n sltu \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
148
static const char * bgt_expn   = "\n slt \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
149
static const char * bgtu_expn  = "\n sltu \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
150
static const char * ble_expn   = "\n slt \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
151
static const char * bleu_expn  = "\n sltu \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
152
static const char * blt_expn   = "\n slt \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
153
static const char * bltu_expn  = "\n sltu \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
154
static const char * sxx_args[] = { "rd", "rs", "rt", NULL };
155
static const char * sge_expn   = "\n slt \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
156
static const char * sgeu_expn  = "\n sltu \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
157
static const char * sle_expn   = "\n slt \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
158
static const char * sleu_expn  = "\n sltu \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
159
static const char * sgt_expn   = "\n slt \\rd,\\rt,\\rs\n";
160
static const char * sgtu_expn  = "\n sltu \\rd,\\rt,\\rs\n";
161
static const char * sne_expn   = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n";
162
static const char * seq_expn   = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n xori \\rd,\\rd,1\n";
163
static const char * ai32_args[] = { "rt", "rs", "imm", NULL };
164
static const char * andi32_expn = "\n\
165
 .if (\\imm & 0xffff0000 == 0xffff0000)\n\
166
 andoi \\rt,\\rs,%lo(\\imm)\n\
167
 .elseif (\\imm & 0x0000ffff == 0x0000ffff)\n\
168
 andoui \\rt,\\rs,%uhi(\\imm)\n\
169
 .elseif (\\imm & 0xffff0000 == 0x00000000)\n\
170
 andi \\rt,\\rs,%lo(\\imm)\n\
171
 .else\n\
172
 andoui \\rt,\\rs,%uhi(\\imm)\n\
173
 andoi \\rt,\\rt,%lo(\\imm)\n\
174
 .endif\n";
175
static const char * ori32_expn  = "\n\
176
 .if (\\imm & 0xffff == 0)\n\
177
 orui \\rt,\\rs,%uhi(\\imm)\n\
178
 .elseif (\\imm & 0xffff0000 == 0)\n\
179
 ori \\rt,\\rs,%lo(\\imm)\n\
180
 .else\n\
181
 orui \\rt,\\rs,%uhi(\\imm)\n\
182
 ori \\rt,\\rt,%lo(\\imm)\n\
183
 .endif\n";
184
 
185
static const char * neg_args[] = { "rd", "rs", NULL };
186
static const char * neg_expn   = "\n sub \\rd,%0,\\rs\n";
187
static const char * negu_expn  = "\n subu \\rd,%0,\\rs\n";
188
static const char * li_args[]  = { "rt", "imm", NULL };
189
static const char * li_expn    = "\n\
190
 .if (\\imm & 0xffff0000 == 0x0)\n\
191
 ori \\rt,%0,\\imm\n\
192
 .elseif (\\imm & 0xffff0000 == 0xffff0000)\n\
193
 addi \\rt,%0,\\imm\n\
194
 .elseif (\\imm & 0x0000ffff == 0)\n\
195
 lui \\rt,%uhi(\\imm)\n\
196
 .else\n\
197
 lui \\rt,%uhi(\\imm)\n\
198
 ori \\rt,\\rt,%lo(\\imm)\n\
199
 .endif\n";
200
 
201
static iq2000_macro_defs_s iq2000_macro_defs[] =
202
{
203
  {"abs",   (const char **) & abs_expn,   (const char **) & abs_args},
204
  {"la",    (const char **) & la_expn,    (const char **) & la_args},
205
  {"bge",   (const char **) & bge_expn,   (const char **) & bxx_args},
206
  {"bgeu",  (const char **) & bgeu_expn,  (const char **) & bxx_args},
207
  {"bgt",   (const char **) & bgt_expn,   (const char **) & bxx_args},
208
  {"bgtu",  (const char **) & bgtu_expn,  (const char **) & bxx_args},
209
  {"ble",   (const char **) & ble_expn,   (const char **) & bxx_args},
210
  {"bleu",  (const char **) & bleu_expn,  (const char **) & bxx_args},
211
  {"blt",   (const char **) & blt_expn,   (const char **) & bxx_args},
212
  {"bltu",  (const char **) & bltu_expn,  (const char **) & bxx_args},
213
  {"sge",   (const char **) & sge_expn,   (const char **) & sxx_args},
214
  {"sgeu",  (const char **) & sgeu_expn,  (const char **) & sxx_args},
215
  {"sle",   (const char **) & sle_expn,   (const char **) & sxx_args},
216
  {"sleu",  (const char **) & sleu_expn,  (const char **) & sxx_args},
217
  {"sgt",   (const char **) & sgt_expn,   (const char **) & sxx_args},
218
  {"sgtu",  (const char **) & sgtu_expn,  (const char **) & sxx_args},
219
  {"seq",   (const char **) & seq_expn,   (const char **) & sxx_args},
220
  {"sne",   (const char **) & sne_expn,   (const char **) & sxx_args},
221
  {"neg",   (const char **) & neg_expn,   (const char **) & neg_args},
222
  {"negu",  (const char **) & negu_expn,  (const char **) & neg_args},
223
  {"li",    (const char **) & li_expn,    (const char **) & li_args},
224
  {"ori32", (const char **) & ori32_expn, (const char **) & ai32_args},
225
  {"andi32",(const char **) & andi32_expn,(const char **) & ai32_args},
226
};
227
 
228
static void
229
iq2000_add_macro (const char *  name,
230
                  const char *  semantics,
231
                  const char ** arguments)
232
{
233
  macro_entry *macro;
234
  sb macro_name;
235
  const char *namestr;
236
 
237
  macro = xmalloc (sizeof (macro_entry));
238
  sb_new (& macro->sub);
239
  sb_new (& macro_name);
240
 
241
  macro->formal_count = 0;
242
  macro->formals = 0;
243
 
244
  sb_add_string (& macro->sub, semantics);
245
 
246
  if (arguments != NULL)
247
    {
248
      formal_entry ** p = &macro->formals;
249
 
250
      macro->formal_count = 0;
251
      macro->formal_hash = hash_new ();
252
 
253
      while (*arguments != NULL)
254
        {
255
          formal_entry *formal;
256
 
257
          formal = xmalloc (sizeof (formal_entry));
258
 
259
          sb_new (& formal->name);
260
          sb_new (& formal->def);
261
          sb_new (& formal->actual);
262
 
263
          /* chlm: Added the following to allow defaulted args.  */
264
          if (strchr (*arguments,'='))
265
            {
266
              char * tt_args = strdup (*arguments);
267
              char * tt_dflt = strchr (tt_args,'=');
268
 
269
              *tt_dflt = 0;
270
              sb_add_string (& formal->name, tt_args);
271
              sb_add_string (& formal->def,  tt_dflt + 1);
272
            }
273
          else
274
            sb_add_string (& formal->name, *arguments);
275
 
276
          /* Add to macro's hash table.  */
277
          hash_jam (macro->formal_hash, sb_terminate (& formal->name), formal);
278
 
279
          formal->index = macro->formal_count;
280
          macro->formal_count++;
281
          *p = formal;
282
          p = & formal->next;
283
          *p = NULL;
284
          ++arguments;
285
        }
286
    }
287
 
288
  sb_add_string (&macro_name, name);
289
  namestr = sb_terminate (&macro_name);
290
  hash_jam (macro_hash, namestr, macro);
291
 
292
  macro_defined = 1;
293
}
294
 
295
static void
296
iq2000_load_macros (void)
297
{
298
  int i;
299
  int mcnt = ARRAY_SIZE (iq2000_macro_defs);
300
 
301
  for (i = 0; i < mcnt; i++)
302
    iq2000_add_macro (iq2000_macro_defs[i].mnemonic,
303
                      *iq2000_macro_defs[i].expansion,
304
                      iq2000_macro_defs[i].args);
305
}
306
 
307
void
308
md_begin (void)
309
{
310
  /* Initialize the `cgen' interface.  */
311
 
312
  /* Set the machine number and endian.  */
313
  gas_cgen_cpu_desc = iq2000_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
314
                                           CGEN_CPU_OPEN_ENDIAN,
315
                                           CGEN_ENDIAN_BIG,
316
                                           CGEN_CPU_OPEN_END);
317
  iq2000_cgen_init_asm (gas_cgen_cpu_desc);
318
 
319
  /* This is a callback from cgen to gas to parse operands.  */
320
  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
321
 
322
  /* Set the ELF flags if desired.  */
323
  if (iq2000_flags)
324
    bfd_set_private_flags (stdoutput, iq2000_flags);
325
 
326
  /* Set the machine type */
327
  bfd_default_set_arch_mach (stdoutput, bfd_arch_iq2000, iq2000_mach);
328
 
329
  iq2000_load_macros ();
330
}
331
 
332
void
333
md_assemble (char * str)
334
{
335
  static long delayed_load_register = 0;
336
  static int last_insn_had_delay_slot = 0;
337
  static int last_insn_has_load_delay = 0;
338
  static int last_insn_unconditional_jump = 0;
339
  static int last_insn_was_ldw = 0;
340
 
341
  iq2000_insn insn;
342
  char * errmsg;
343
 
344
  /* Initialize GAS's cgen interface for a new instruction.  */
345
  gas_cgen_init_parse ();
346
 
347
  insn.insn = iq2000_cgen_assemble_insn
348
      (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
349
 
350
  if (!insn.insn)
351
    {
352
      as_bad ("%s", errmsg);
353
      return;
354
    }
355
 
356
  /* Doesn't really matter what we pass for RELAX_P here.  */
357
  gas_cgen_finish_insn (insn.insn, insn.buffer,
358
                        CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
359
 
360
  /* We need to generate an error if there's a yielding instruction in the delay
361
     slot of a control flow modifying instruction (jump (yes), load (no))  */
362
  if ((last_insn_had_delay_slot && !last_insn_has_load_delay) &&
363
      CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_YIELD_INSN))
364
      as_bad (_("the yielding instruction %s may not be in a delay slot."),
365
              CGEN_INSN_NAME (insn.insn));
366
 
367
  /* Warn about odd numbered base registers for paired-register
368
     instructions like LDW.  On iq2000, result is always rt.  */
369
  if (iq2000_mach == bfd_mach_iq2000
370
      && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_EVEN_REG_NUM)
371
      && (insn.fields.f_rt % 2))
372
    as_bad (_("Register number (R%ld) for double word access must be even."),
373
            insn.fields.f_rt);
374
 
375
  /* Warn about insns that reference the target of a previous load.  */
376
  /* NOTE: R0 is a special case and is not subject to load delays (except for ldw).  */
377
  if (delayed_load_register && (last_insn_has_load_delay || last_insn_was_ldw))
378
    {
379
      if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD) &&
380
          insn.fields.f_rd == delayed_load_register)
381
        as_warn (_("operand references R%ld of previous load."),
382
                 insn.fields.f_rd);
383
 
384
      if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS) &&
385
          insn.fields.f_rs == delayed_load_register)
386
        as_warn (_("operand references R%ld of previous load."),
387
                 insn.fields.f_rs);
388
 
389
      if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT) &&
390
          insn.fields.f_rt == delayed_load_register)
391
        as_warn (_("operand references R%ld of previous load."),
392
                 insn.fields.f_rt);
393
 
394
      if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_R31) &&
395
          delayed_load_register == 31)
396
        as_warn (_("instruction implicitly accesses R31 of previous load."));
397
    }
398
 
399
  /* Warn about insns that reference the (target + 1) of a previous ldw.  */
400
  if (last_insn_was_ldw)
401
    {
402
      if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD)
403
           && insn.fields.f_rd == delayed_load_register + 1)
404
       || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS)
405
           && insn.fields.f_rs == delayed_load_register + 1)
406
       || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT)
407
           && insn.fields.f_rt == delayed_load_register + 1))
408
        as_warn (_("operand references R%ld of previous load."),
409
                delayed_load_register + 1);
410
    }
411
 
412
  last_insn_had_delay_slot =
413
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
414
 
415
  last_insn_has_load_delay =
416
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
417
 
418
  if (last_insn_unconditional_jump)
419
    last_insn_has_load_delay = last_insn_unconditional_jump = 0;
420
  else if (! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "j")
421
           || ! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "jal"))
422
           last_insn_unconditional_jump = 1;
423
 
424
  /* The meaning of EVEN_REG_NUM was overloaded to also imply LDW.  Since
425
     that's not true for IQ10, let's make the above logic specific to LDW.  */
426
  last_insn_was_ldw = ! strcmp ("ldw", CGEN_INSN_NAME (insn.insn));
427
 
428
  /* The assumption here is that the target of a load is always rt.  */
429
  delayed_load_register = insn.fields.f_rt;
430
}
431
 
432
valueT
433
md_section_align (segT segment, valueT size)
434
{
435
  int align = bfd_get_section_alignment (stdoutput, segment);
436
  return ((size + (1 << align) - 1) & (-1 << align));
437
}
438
 
439
symbolS *
440
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
441
{
442
    return 0;
443
}
444
 
445
/* Interface to relax_segment.  */
446
 
447
/* Return an initial guess of the length by which a fragment must grow to
448
   hold a branch to reach its destination.
449
   Also updates fr_type/fr_subtype as necessary.
450
 
451
   Called just before doing relaxation.
452
   Any symbol that is now undefined will not become defined.
453
   The guess for fr_var is ACTUALLY the growth beyond fr_fix.
454
   Whatever we do to grow fr_fix or fr_var contributes to our returned value.
455
   Although it may not be explicit in the frag, pretend fr_var starts with a
456
 
457
 
458
int
459
md_estimate_size_before_relax (fragS * fragP,
460
                               segT    segment ATTRIBUTE_UNUSED)
461
{
462
  int    old_fr_fix = fragP->fr_fix;
463
 
464
  /* The only thing we have to handle here are symbols outside of the
465
     current segment.  They may be undefined or in a different segment in
466
     which case linker scripts may place them anywhere.
467
     However, we can't finish the fragment here and emit the reloc as insn
468
     alignment requirements may move the insn about.  */
469
 
470
  return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
471
}
472
 
473
/* *fragP has been relaxed to its final size, and now needs to have
474
   the bytes inside it modified to conform to the new size.
475
 
476
   Called after relaxation is finished.
477
   fragP->fr_type == rs_machine_dependent.
478
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
479
 
480
void
481
md_convert_frag (bfd   * abfd  ATTRIBUTE_UNUSED,
482
                 segT    sec   ATTRIBUTE_UNUSED,
483
                 fragS * fragP ATTRIBUTE_UNUSED)
484
{
485
}
486
 
487
 
488
/* Functions concerning relocs.  */
489
 
490
long
491
md_pcrel_from_section (fixS * fixP, segT sec)
492
{
493
  if (fixP->fx_addsy != (symbolS *) NULL
494
      && (! S_IS_DEFINED (fixP->fx_addsy)
495
          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
496
    {
497
      /* The symbol is undefined (or is defined but not in this section).
498
         Let the linker figure it out.  */
499
      return 0;
500
    }
501
 
502
  /* Return the address of the delay slot.  */
503
  return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
504
}
505
 
506
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
507
   Returns BFD_RELOC_NONE if no reloc type can be found.
508
   *FIXP may be modified if desired.  */
509
 
510
bfd_reloc_code_real_type
511
md_cgen_lookup_reloc (const CGEN_INSN *    insn     ATTRIBUTE_UNUSED,
512
                      const CGEN_OPERAND * operand,
513
                      fixS *               fixP     ATTRIBUTE_UNUSED)
514
{
515
  switch (operand->type)
516
    {
517
    case IQ2000_OPERAND_OFFSET:      return BFD_RELOC_16_PCREL_S2;
518
    case IQ2000_OPERAND_JMPTARG:     return BFD_RELOC_IQ2000_OFFSET_16;
519
    case IQ2000_OPERAND_JMPTARGQ10:  return BFD_RELOC_NONE;
520
    case IQ2000_OPERAND_HI16:        return BFD_RELOC_HI16;
521
    case IQ2000_OPERAND_LO16:        return BFD_RELOC_LO16;
522
    default: break;
523
    }
524
 
525
  return BFD_RELOC_NONE;
526
}
527
 
528
/* Record a HI16 reloc for later matching with its LO16 cousin.  */
529
 
530
static void
531
iq2000_record_hi16 (int    reloc_type,
532
                    fixS * fixP,
533
                    segT   seg ATTRIBUTE_UNUSED)
534
{
535
  struct iq2000_hi_fixup * hi_fixup;
536
 
537
  gas_assert (reloc_type == BFD_RELOC_HI16);
538
 
539
  hi_fixup = xmalloc (sizeof * hi_fixup);
540
  hi_fixup->fixp = fixP;
541
  hi_fixup->seg  = now_seg;
542
  hi_fixup->next = iq2000_hi_fixup_list;
543
 
544
  iq2000_hi_fixup_list = hi_fixup;
545
}
546
 
547
/* Called while parsing an instruction to create a fixup.
548
   We need to check for HI16 relocs and queue them up for later sorting.  */
549
 
550
fixS *
551
iq2000_cgen_record_fixup_exp (fragS *              frag,
552
                              int                  where,
553
                              const CGEN_INSN *    insn,
554
                              int                  length,
555
                              const CGEN_OPERAND * operand,
556
                              int                  opinfo,
557
                              expressionS *        exp)
558
{
559
  fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
560
                                           operand, opinfo, exp);
561
 
562
  if (operand->type == IQ2000_OPERAND_HI16
563
      /* If low/high was used, it is recorded in `opinfo'.  */
564
      && (fixP->fx_cgen.opinfo == BFD_RELOC_HI16
565
          || fixP->fx_cgen.opinfo == BFD_RELOC_LO16))
566
    iq2000_record_hi16 (fixP->fx_cgen.opinfo, fixP, now_seg);
567
 
568
  return fixP;
569
}
570
 
571
/* Return BFD reloc type from opinfo field in a fixS.
572
   It's tricky using fx_r_type in iq2000_frob_file because the values
573
   are BFD_RELOC_UNUSED + operand number.  */
574
#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
575
 
576
/* Sort any unmatched HI16 relocs so that they immediately precede
577
   the corresponding LO16 reloc.  This is called before md_apply_fix and
578
   tc_gen_reloc.  */
579
 
580
void
581
iq2000_frob_file (void)
582
{
583
  struct iq2000_hi_fixup * l;
584
 
585
  for (l = iq2000_hi_fixup_list; l != NULL; l = l->next)
586
    {
587
      segment_info_type * seginfo;
588
      int                 pass;
589
 
590
      gas_assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
591
              || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
592
 
593
      /* Check quickly whether the next fixup happens to be a matching low.  */
594
      if (l->fixp->fx_next != NULL
595
          && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
596
          && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
597
          && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
598
        continue;
599
 
600
      /* Look through the fixups for this segment for a matching
601
         `low'.  When we find one, move the high just in front of it.
602
         We do this in two passes.  In the first pass, we try to find
603
         a unique `low'.  In the second pass, we permit multiple
604
         high's relocs for a single `low'.  */
605
      seginfo = seg_info (l->seg);
606
      for (pass = 0; pass < 2; pass++)
607
        {
608
          fixS * f;
609
          fixS * prev;
610
 
611
          prev = NULL;
612
          for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
613
            {
614
              /* Check whether this is a `low' fixup which matches l->fixp.  */
615
              if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
616
                  && f->fx_addsy == l->fixp->fx_addsy
617
                  && f->fx_offset == l->fixp->fx_offset
618
                  && (pass == 1
619
                      || prev == NULL
620
                      || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
621
                      || prev->fx_addsy != f->fx_addsy
622
                      || prev->fx_offset !=  f->fx_offset))
623
                {
624
                  fixS ** pf;
625
 
626
                  /* Move l->fixp before f.  */
627
                  for (pf = &seginfo->fix_root;
628
                       * pf != l->fixp;
629
                       pf = & (* pf)->fx_next)
630
                    gas_assert (* pf != NULL);
631
 
632
                  * pf = l->fixp->fx_next;
633
 
634
                  l->fixp->fx_next = f;
635
                  if (prev == NULL)
636
                    seginfo->fix_root = l->fixp;
637
                  else
638
                    prev->fx_next = l->fixp;
639
 
640
                  break;
641
                }
642
 
643
              prev = f;
644
            }
645
 
646
          if (f != NULL)
647
            break;
648
 
649
          if (pass == 1)
650
            as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
651
                           _("Unmatched high relocation"));
652
        }
653
    }
654
}
655
 
656
/* See whether we need to force a relocation into the output file.  */
657
 
658
int
659
iq2000_force_relocation (fixS * fix)
660
{
661
  if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
662
      || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
663
    return 1;
664
 
665
  return 0;
666
}
667
 
668
/* Handle the .set pseudo-op.  */
669
 
670
static void
671
s_iq2000_set (int x ATTRIBUTE_UNUSED)
672
{
673
  static const char * ignored_arguments [] =
674
    {
675
      "reorder",
676
      "noreorder",
677
      "at",
678
      "noat",
679
      "macro",
680
      "nomacro",
681
      "move",
682
      "novolatile",
683
      "nomove",
684
      "volatile",
685
      "bopt",
686
      "nobopt",
687
      NULL
688
    };
689
  const char ** ignored;
690
  char *name = input_line_pointer, ch;
691
  char *save_ILP = input_line_pointer;
692
 
693
  while (!is_end_of_line[(unsigned char) *input_line_pointer])
694
    input_line_pointer++;
695
  ch = *input_line_pointer;
696
  *input_line_pointer = '\0';
697
 
698
  for (ignored = ignored_arguments; * ignored; ignored ++)
699
    if (strcmp (* ignored, name) == 0)
700
      break;
701
  if (* ignored == NULL)
702
    {
703
      /* We'd like to be able to use .set symbol, expn */
704
      input_line_pointer = save_ILP;
705
      s_set (0);
706
      return;
707
    }
708
  *input_line_pointer = ch;
709
  demand_empty_rest_of_line ();
710
}
711
 
712
/* Write a value out to the object file, using the appropriate endianness.  */
713
 
714
void
715
md_number_to_chars (char * buf, valueT val, int n)
716
{
717
  number_to_chars_bigendian (buf, val, n);
718
}
719
 
720
void
721
md_operand (expressionS * exp)
722
{
723
  /* In case of a syntax error, escape back to try next syntax combo.  */
724
  if (exp->X_op == O_absent)
725
    gas_cgen_md_operand (exp);
726
}
727
 
728
char *
729
md_atof (int type, char * litP, int * sizeP)
730
{
731
  return ieee_md_atof (type, litP, sizeP, TRUE);
732
}
733
 
734
bfd_boolean
735
iq2000_fix_adjustable (fixS * fixP)
736
{
737
  bfd_reloc_code_real_type reloc_type;
738
 
739
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
740
    {
741
      const CGEN_INSN *insn = NULL;
742
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
743
      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
744
 
745
      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
746
    }
747
  else
748
    reloc_type = fixP->fx_r_type;
749
 
750
  if (fixP->fx_addsy == NULL)
751
    return TRUE;
752
 
753
  /* Prevent all adjustments to global symbols.  */
754
  if (S_IS_EXTERNAL (fixP->fx_addsy))
755
    return FALSE;
756
 
757
  if (S_IS_WEAK (fixP->fx_addsy))
758
    return FALSE;
759
 
760
  /* We need the symbol name for the VTABLE entries.  */
761
  if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
762
      || reloc_type == BFD_RELOC_VTABLE_ENTRY)
763
    return FALSE;
764
 
765
  return TRUE;
766
}
767
 
768
static void
769
s_change_sec (int sec)
770
{
771
#ifdef OBJ_ELF
772
  /* The ELF backend needs to know that we are changing sections, so
773
     that .previous works correctly.  We could do something like check
774
     for a obj_section_change_hook macro, but that might be confusing
775
     as it would not be appropriate to use it in the section changing
776
     functions in read.c, since obj-elf.c intercepts those.  FIXME:
777
     This should be cleaner, somehow.  */
778
  obj_elf_section_change_hook ();
779
#endif
780
 
781
  switch (sec)
782
    {
783
    case 't':
784
      s_text (0);
785
      break;
786
    case 'd':
787
    case 'r':
788
      s_data (0);
789
      break;
790
    }
791
}
792
 
793
static symbolS *
794
get_symbol (void)
795
{
796
  int c;
797
  char *name;
798
  symbolS *p;
799
 
800
  name = input_line_pointer;
801
  c = get_symbol_end ();
802
  p = (symbolS *) symbol_find_or_make (name);
803
  *input_line_pointer = c;
804
  return p;
805
}
806
 
807
/* The .end directive.  */
808
 
809
static void
810
s_iq2000_end (int x ATTRIBUTE_UNUSED)
811
{
812
  symbolS *p;
813
  int maybe_text;
814
 
815
  if (!is_end_of_line[(unsigned char) *input_line_pointer])
816
    {
817
      p = get_symbol ();
818
      demand_empty_rest_of_line ();
819
    }
820
  else
821
    p = NULL;
822
 
823
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
824
    maybe_text = 1;
825
  else
826
    maybe_text = 0;
827
 
828
  if (!maybe_text)
829
    as_warn (_(".end not in text section"));
830
 
831
  if (!cur_proc_ptr)
832
    {
833
      as_warn (_(".end directive without a preceding .ent directive."));
834
      demand_empty_rest_of_line ();
835
      return;
836
    }
837
 
838
  if (p != NULL)
839
    {
840
      gas_assert (S_GET_NAME (p));
841
      if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
842
        as_warn (_(".end symbol does not match .ent symbol."));
843
    }
844
  else
845
    as_warn (_(".end directive missing or unknown symbol"));
846
 
847
  cur_proc_ptr = NULL;
848
}
849
 
850
static int
851
get_number (void)
852
{
853
  int negative = 0;
854
  long val = 0;
855
 
856
  if (*input_line_pointer == '-')
857
    {
858
      ++input_line_pointer;
859
      negative = 1;
860
    }
861
 
862
  if (! ISDIGIT (*input_line_pointer))
863
    as_bad (_("Expected simple number."));
864
 
865
  if (input_line_pointer[0] == '0')
866
    {
867
      if (input_line_pointer[1] == 'x')
868
        {
869
          input_line_pointer += 2;
870
          while (ISXDIGIT (*input_line_pointer))
871
            {
872
              val <<= 4;
873
              val |= hex_value (*input_line_pointer++);
874
            }
875
          return negative ? -val : val;
876
        }
877
      else
878
        {
879
          ++input_line_pointer;
880
 
881
          while (ISDIGIT (*input_line_pointer))
882
            {
883
              val <<= 3;
884
              val |= *input_line_pointer++ - '0';
885
            }
886
          return negative ? -val : val;
887
        }
888
    }
889
 
890
  if (! ISDIGIT (*input_line_pointer))
891
    {
892
      printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
893
              *input_line_pointer, *input_line_pointer);
894
      as_warn (_("Invalid number"));
895
      return -1;
896
    }
897
 
898
  while (ISDIGIT (*input_line_pointer))
899
    {
900
      val *= 10;
901
      val += *input_line_pointer++ - '0';
902
    }
903
 
904
  return negative ? -val : val;
905
}
906
 
907
/* The .aent and .ent directives.  */
908
 
909
static void
910
s_iq2000_ent (int aent)
911
{
912
  symbolS *symbolP;
913
  int maybe_text;
914
 
915
  symbolP = get_symbol ();
916
  if (*input_line_pointer == ',')
917
    input_line_pointer++;
918
  SKIP_WHITESPACE ();
919
  if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
920
    get_number ();
921
 
922
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
923
    maybe_text = 1;
924
  else
925
    maybe_text = 0;
926
 
927
  if (!maybe_text)
928
    as_warn (_(".ent or .aent not in text section."));
929
 
930
  if (!aent && cur_proc_ptr)
931
    as_warn (_("missing `.end'"));
932
 
933
  if (!aent)
934
    {
935
      cur_proc_ptr = &cur_proc;
936
      memset (cur_proc_ptr, '\0', sizeof (procS));
937
 
938
      cur_proc_ptr->isym = symbolP;
939
 
940
      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
941
 
942
      numprocs++;
943
    }
944
 
945
  demand_empty_rest_of_line ();
946
}
947
 
948
/* The .frame directive. If the mdebug section is present (IRIX 5 native)
949
   then ecoff.c (ecoff_directive_frame) is used. For embedded targets,
950
   s_iq2000_frame is used so that we can set the PDR information correctly.
951
   We can't use the ecoff routines because they make reference to the ecoff
952
   symbol table (in the mdebug section).  */
953
 
954
static void
955
s_iq2000_frame (int ignore)
956
{
957
  s_ignore (ignore);
958
}
959
 
960
/* The .fmask and .mask directives. If the mdebug section is present
961
   (IRIX 5 native) then ecoff.c (ecoff_directive_mask) is used. For
962
   embedded targets, s_iq2000_mask is used so that we can set the PDR
963
   information correctly. We can't use the ecoff routines because they
964
   make reference to the ecoff symbol table (in the mdebug section).  */
965
 
966
static void
967
s_iq2000_mask (int reg_type)
968
{
969
  s_ignore (reg_type);
970
}
971
 
972
/* The target specific pseudo-ops which we support.  */
973
const pseudo_typeS md_pseudo_table[] =
974
{
975
    { "align",  s_align_bytes,           0 },
976
    { "word",   cons,                    4 },
977
    { "rdata",  s_change_sec,           'r'},
978
    { "sdata",  s_change_sec,           's'},
979
    { "set",    s_iq2000_set,            0 },
980
    { "ent",    s_iq2000_ent,            0 },
981
    { "end",    s_iq2000_end,            0 },
982
    { "frame",  s_iq2000_frame,          0 },
983
    { "fmask",  s_iq2000_mask,          'F'},
984
    { "mask",   s_iq2000_mask,          'R'},
985
    { "dword",  cons,                    8 },
986
    { "half",   cons,                    2 },
987
    { NULL,     NULL,                    0 }
988
};

powered by: WebSVN 2.1.0

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