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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 38 julius
/* tc-ip2k.c -- Assembler for the Scenix IP2xxx.
2
   Copyright (C) 2000, 2002, 2003, 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
19
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20
   Boston, MA 02110-1301, USA.  */
21
 
22
#include "as.h"
23
#include "subsegs.h"     
24
#include "symcat.h"
25
#include "opcodes/ip2k-desc.h"
26
#include "opcodes/ip2k-opc.h"
27
#include "cgen.h"
28
#include "elf/common.h"
29
#include "elf/ip2k.h"
30
#include "libbfd.h"
31
 
32
/* Structure to hold all of the different components describing
33
   an individual instruction.  */
34
typedef struct
35
{
36
  const CGEN_INSN *     insn;
37
  const CGEN_INSN *     orig_insn;
38
  CGEN_FIELDS           fields;
39
#if CGEN_INT_INSN_P
40
  CGEN_INSN_INT         buffer [1];
41
#define INSN_VALUE(buf) (*(buf))
42
#else
43
  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
44
#define INSN_VALUE(buf) (buf)
45
#endif
46
  char *                addr;
47
  fragS *               frag;
48
  int                   num_fixups;
49
  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
50
  int                   indices [MAX_OPERAND_INSTANCES];
51
}
52
ip2k_insn;
53
 
54
const char comment_chars[]        = ";";
55
const char line_comment_chars[]   = "#";
56
const char line_separator_chars[] = "";
57
const char EXP_CHARS[]            = "eE";
58
const char FLT_CHARS[]            = "dD";
59
 
60
/* Flag to detect when switching to code section where insn alignment is
61
   implied.  */
62
static int force_code_align = 0;
63
 
64
/* Mach selected from command line.  */
65
static int ip2k_mach = 0;
66
static unsigned ip2k_mach_bitmask = 0;
67
 
68
 
69
static void
70
ip2k_elf_section_rtn (int i)
71
{
72
  obj_elf_section(i);
73
 
74
  if (force_code_align)
75
    {
76
      /* The s_align_ptwo function expects that we are just after a .align
77
         directive and it will either try and read the align value or stop
78
         if end of line so we must fake it out so it thinks we are at the
79
         end of the line.  */
80
      char *old_input_line_pointer = input_line_pointer;
81
      input_line_pointer = "\n";
82
      s_align_ptwo (1);
83
      force_code_align = 0;
84
      /* Restore.  */
85
      input_line_pointer = old_input_line_pointer;
86
    }
87
}
88
 
89
static void
90
ip2k_elf_section_text (int i)
91
{
92
  char *old_input_line_pointer;
93
  obj_elf_text(i);
94
 
95
  /* the s_align_ptwo function expects that we are just after a .align
96
     directive and it will either try and read the align value or stop if
97
     end of line so we must fake it out so it thinks we are at the end of
98
     the line.  */
99
  old_input_line_pointer = input_line_pointer;
100
  input_line_pointer = "\n";
101
  s_align_ptwo (1);
102
  force_code_align = 0;
103
  /* Restore.  */
104
  input_line_pointer = old_input_line_pointer;
105
}
106
 
107
/* The target specific pseudo-ops which we support.  */
108
const pseudo_typeS md_pseudo_table[] =
109
{
110
    { "text",   ip2k_elf_section_text,  0 },
111
    { "sect",   ip2k_elf_section_rtn,   0 },
112
    { NULL,     NULL,                   0 }
113
};
114
 
115
 
116
 
117
enum options
118
{
119
  OPTION_CPU_IP2022 = OPTION_MD_BASE,
120
  OPTION_CPU_IP2022EXT
121
};
122
 
123
struct option md_longopts[] =
124
{
125
  { "mip2022",     no_argument, NULL, OPTION_CPU_IP2022 },
126
  { "mip2022ext",  no_argument, NULL, OPTION_CPU_IP2022EXT },
127
  { NULL,           no_argument, NULL, 0 },
128
};
129
size_t md_longopts_size = sizeof (md_longopts);
130
 
131
const char * md_shortopts = "";
132
 
133
int
134
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
135
{
136
  switch (c)
137
    {
138
    case OPTION_CPU_IP2022:
139
      ip2k_mach = bfd_mach_ip2022;
140
      ip2k_mach_bitmask = 1 << MACH_IP2022;
141
      break;
142
 
143
    case OPTION_CPU_IP2022EXT:
144
      ip2k_mach = bfd_mach_ip2022ext;
145
      ip2k_mach_bitmask = 1 << MACH_IP2022EXT;
146
      break;
147
 
148
    default:
149
      return 0;
150
    }
151
 
152
  return 1;
153
}
154
 
155
void
156
md_show_usage (FILE * stream)
157
{
158
  fprintf (stream, _("IP2K specific command line options:\n"));
159
  fprintf (stream, _("  -mip2022               restrict to IP2022 insns \n"));
160
  fprintf (stream, _("  -mip2022ext            permit extended IP2022 insn\n"));
161
}
162
 
163
 
164
void
165
md_begin (void)
166
{
167
  /* Initialize the `cgen' interface.  */
168
 
169
  /* Set the machine number and endian.  */
170
  gas_cgen_cpu_desc = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
171
                                          ip2k_mach_bitmask,
172
                                          CGEN_CPU_OPEN_ENDIAN,
173
                                          CGEN_ENDIAN_BIG,
174
                                          CGEN_CPU_OPEN_END);
175
  ip2k_cgen_init_asm (gas_cgen_cpu_desc);
176
 
177
  /* This is a callback from cgen to gas to parse operands.  */
178
  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
179
 
180
  /* Set the machine type.  */
181
  bfd_default_set_arch_mach (stdoutput, bfd_arch_ip2k, ip2k_mach);
182
}
183
 
184
 
185
void
186
md_assemble (char * str)
187
{
188
  ip2k_insn insn;
189
  char * errmsg;
190
 
191
  /* Initialize GAS's cgen interface for a new instruction.  */
192
  gas_cgen_init_parse ();
193
 
194
  insn.insn = ip2k_cgen_assemble_insn
195
      (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
196
 
197
  if (!insn.insn)
198
    {
199
      as_bad ("%s", errmsg);
200
      return;
201
    }
202
 
203
  /* Check for special relocation required by SKIP instructions.  */
204
  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SKIPA))
205
    /* Unconditional skip has a 1-bit relocation of the current pc, so
206
       that we emit either sb pcl.0 or snb pcl.0 depending on whether
207
       the PCL (pc + 2) >> 1 is odd or even.  */
208
    {
209
      enum cgen_parse_operand_result result_type;
210
      bfd_vma value;
211
      const char *curpc_plus_2 = ".+2";
212
      const char *err;
213
 
214
      err = cgen_parse_address (gas_cgen_cpu_desc, & curpc_plus_2,
215
                                IP2K_OPERAND_ADDR16CJP,
216
                                BFD_RELOC_IP2K_PC_SKIP,
217
                                & result_type, & value);
218
      if (err)
219
        {
220
          as_bad ("%s", err);
221
          return;
222
        }
223
    }
224
 
225
  /* Doesn't really matter what we pass for RELAX_P here.  */
226
  gas_cgen_finish_insn (insn.insn, insn.buffer,
227
                        CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
228
}
229
 
230
valueT
231
md_section_align (segT segment, valueT size)
232
{
233
  int align = bfd_get_section_alignment (stdoutput, segment);
234
 
235
  return ((size + (1 << align) - 1) & (-1 << align));
236
}
237
 
238
 
239
symbolS *
240
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
241
{
242
    return 0;
243
}
244
 
245
int
246
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
247
                               segT    segment ATTRIBUTE_UNUSED)
248
{
249
  as_fatal (_("relaxation not supported\n"));
250
  return 1;
251
}
252
 
253
 
254
/* *fragP has been relaxed to its final size, and now needs to have
255
   the bytes inside it modified to conform to the new size.
256
 
257
   Called after relaxation is finished.
258
   fragP->fr_type == rs_machine_dependent.
259
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
260
 
261
void
262
md_convert_frag (bfd   * abfd  ATTRIBUTE_UNUSED,
263
                 segT    sec   ATTRIBUTE_UNUSED,
264
                 fragS * fragP ATTRIBUTE_UNUSED)
265
{
266
}
267
 
268
 
269
/* Functions concerning relocs.  */
270
 
271
long
272
md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
273
{
274
  abort ();
275
}
276
 
277
 
278
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
279
   Returns BFD_RELOC_NONE if no reloc type can be found.
280
   *FIXP may be modified if desired.  */
281
 
282
bfd_reloc_code_real_type
283
md_cgen_lookup_reloc (const CGEN_INSN *    insn     ATTRIBUTE_UNUSED,
284
                      const CGEN_OPERAND * operand,
285
                      fixS *               fixP     ATTRIBUTE_UNUSED)
286
{
287
  bfd_reloc_code_real_type result;
288
 
289
  result = BFD_RELOC_NONE;
290
 
291
  switch (operand->type)
292
    {
293
    case IP2K_OPERAND_FR:
294
    case IP2K_OPERAND_ADDR16L:
295
    case IP2K_OPERAND_ADDR16H:
296
    case IP2K_OPERAND_LIT8:
297
      /* These may have been processed at parse time.  */
298
      if (fixP->fx_cgen.opinfo != 0)
299
        result = fixP->fx_cgen.opinfo;
300
      fixP->fx_no_overflow = 1;
301
      break;
302
 
303
    case IP2K_OPERAND_ADDR16CJP:
304
      result = fixP->fx_cgen.opinfo;
305
      if (result == 0 || result == BFD_RELOC_NONE)
306
        result = BFD_RELOC_IP2K_ADDR16CJP;
307
      fixP->fx_no_overflow = 1;
308
      break;
309
 
310
    case IP2K_OPERAND_ADDR16P:
311
      result = BFD_RELOC_IP2K_PAGE3;
312
      fixP->fx_no_overflow = 1;
313
      break;
314
 
315
    default:
316
      result = BFD_RELOC_NONE;
317
      break;
318
    }
319
 
320
  return result;
321
}
322
 
323
 
324
/* Write a value out to the object file, using the appropriate endianness.  */
325
 
326
void
327
md_number_to_chars (char * buf, valueT val, int n)
328
{
329
  number_to_chars_bigendian (buf, val, n);
330
}
331
 
332
char *
333
md_atof (int type, char * litP, int *  sizeP)
334
{
335
  return ieee_md_atof (type, litP, sizeP, TRUE);
336
}
337
 
338
 
339
/* See whether we need to force a relocation into the output file.
340
   Force most of them, since the linker's bfd relocation engine
341
   understands range limits better than gas' cgen fixup engine.
342
   Consider the case of a fixup intermediate value being larger than
343
   the instruction it will be eventually encoded within.  */
344
 
345
int
346
ip2k_force_relocation (fixS * fix)
347
{
348
  switch (fix->fx_r_type)
349
    {
350
    case BFD_RELOC_IP2K_FR9:
351
    case BFD_RELOC_IP2K_FR_OFFSET:
352
    case BFD_RELOC_IP2K_BANK:
353
    case BFD_RELOC_IP2K_ADDR16CJP:
354
    case BFD_RELOC_IP2K_PAGE3:
355
    case BFD_RELOC_IP2K_LO8DATA:
356
    case BFD_RELOC_IP2K_HI8DATA:
357
    case BFD_RELOC_IP2K_EX8DATA:
358
    case BFD_RELOC_IP2K_LO8INSN:
359
    case BFD_RELOC_IP2K_HI8INSN:
360
    case BFD_RELOC_IP2K_PC_SKIP:
361
    case BFD_RELOC_IP2K_TEXT:
362
      return 1;
363
 
364
    case BFD_RELOC_16:
365
      if (fix->fx_subsy && S_IS_DEFINED (fix->fx_subsy)
366
          && fix->fx_addsy && S_IS_DEFINED (fix->fx_addsy)
367
          && (S_GET_SEGMENT (fix->fx_addsy)->flags & SEC_CODE))
368
        {
369
          fix->fx_r_type = BFD_RELOC_IP2K_TEXT;
370
          return 0;
371
        }
372
      break;
373
 
374
    default:
375
      break;
376
    }
377
 
378
  return generic_force_reloc (fix);
379
}
380
 
381
void
382
ip2k_apply_fix (fixS *fixP, valueT *valueP, segT seg)
383
{
384
  if (fixP->fx_r_type == BFD_RELOC_IP2K_TEXT
385
      && ! fixP->fx_addsy
386
      && ! fixP->fx_subsy)
387
    {
388
      *valueP = ((int)(* valueP)) / 2;
389
      fixP->fx_r_type = BFD_RELOC_16;
390
    }
391
  else if (fixP->fx_r_type == BFD_RELOC_UNUSED + IP2K_OPERAND_FR)
392
    {
393
      /* Must be careful when we are fixing up an FR.  We could be
394
         fixing up an offset to (SP) or (DP) in which case we don't
395
         want to step on the top 2 bits of the FR operand.  The
396
         gas_cgen_md_apply_fix doesn't know any better and overwrites
397
         the entire operand.  We counter this by adding the bits
398
         to the new value.  */
399
      char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
400
 
401
      /* Canonical name, since used a lot.  */
402
      CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
403
      CGEN_INSN_INT insn_value
404
        = cgen_get_insn_value (cd, (unsigned char *) where,
405
                               CGEN_INSN_BITSIZE (fixP->fx_cgen.insn));
406
      /* Preserve (DP) or (SP) specification.  */
407
      *valueP += (insn_value & 0x180);
408
    }
409
 
410
  gas_cgen_md_apply_fix (fixP, valueP, seg);
411
}
412
 
413
int
414
ip2k_elf_section_flags (int flags,
415
                        int attr ATTRIBUTE_UNUSED,
416
                        int type ATTRIBUTE_UNUSED)
417
{
418
  /* This is used to detect when the section changes to an executable section.
419
     This function is called by the elf section processing.  When we note an
420
     executable section specifier we set an internal flag to denote when
421
     word alignment should be forced.  */
422
  if (flags & SEC_CODE)
423
    force_code_align = 1;
424
 
425
  return flags;
426
}
427
 

powered by: WebSVN 2.1.0

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