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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 16 khays
/* tc-openrisc.c -- Assembler for the OpenRISC family.
2
   Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2009
3
   Free Software Foundation.
4
   Contributed by Johan Rydberg, jrydberg@opencores.org
5
 
6
   This file is part of GAS, the GNU Assembler.
7
 
8
   GAS is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   GAS is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with GAS; see the file COPYING.  If not, write to
20
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
21
   Boston, MA 02110-1301, USA.  */
22
 
23
#include "as.h"
24
#include "subsegs.h"
25
#include "symcat.h"
26
#include "opcodes/openrisc-desc.h"
27
#include "opcodes/openrisc-opc.h"
28
#include "cgen.h"
29
 
30
/* Structure to hold all of the different components describing
31
   an individual instruction.  */
32
typedef struct openrisc_insn openrisc_insn;
33
 
34
struct openrisc_insn
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
 
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
 
61
#define OPENRISC_SHORTOPTS "m:"
62
const char * md_shortopts = OPENRISC_SHORTOPTS;
63
 
64
struct option md_longopts[] =
65
{
66
  {NULL, no_argument, NULL, 0}
67
};
68
size_t md_longopts_size = sizeof (md_longopts);
69
 
70
unsigned long openrisc_machine = 0; /* default */
71
 
72
int
73
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
74
{
75
  return 0;
76
}
77
 
78
void
79
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
80
{
81
}
82
 
83
static void
84
ignore_pseudo (int val ATTRIBUTE_UNUSED)
85
{
86
  discard_rest_of_line ();
87
}
88
 
89
const char openrisc_comment_chars [] = ";#";
90
 
91
/* The target specific pseudo-ops which we support.  */
92
const pseudo_typeS md_pseudo_table[] =
93
{
94
  { "word",     cons,           4 },
95
  { "proc",     ignore_pseudo,  0 },
96
  { "endproc",  ignore_pseudo,  0 },
97
  { NULL,       NULL,           0 }
98
};
99
 
100
 
101
 
102
void
103
md_begin (void)
104
{
105
  /* Initialize the `cgen' interface.  */
106
 
107
  /* Set the machine number and endian.  */
108
  gas_cgen_cpu_desc = openrisc_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
109
                                              CGEN_CPU_OPEN_ENDIAN,
110
                                              CGEN_ENDIAN_BIG,
111
                                              CGEN_CPU_OPEN_END);
112
  openrisc_cgen_init_asm (gas_cgen_cpu_desc);
113
 
114
  /* This is a callback from cgen to gas to parse operands.  */
115
  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
116
}
117
 
118
void
119
md_assemble (char * str)
120
{
121
  static int last_insn_had_delay_slot = 0;
122
  openrisc_insn insn;
123
  char *    errmsg;
124
 
125
  /* Initialize GAS's cgen interface for a new instruction.  */
126
  gas_cgen_init_parse ();
127
 
128
  insn.insn = openrisc_cgen_assemble_insn
129
    (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
130
 
131
  if (!insn.insn)
132
    {
133
      as_bad ("%s", errmsg);
134
      return;
135
    }
136
 
137
  /* Doesn't really matter what we pass for RELAX_P here.  */
138
  gas_cgen_finish_insn (insn.insn, insn.buffer,
139
                        CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
140
 
141
  last_insn_had_delay_slot
142
    = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
143
}
144
 
145
 
146
/* The syntax in the manual says constants begin with '#'.
147
   We just ignore it.  */
148
 
149
void
150
md_operand (expressionS * expressionP)
151
{
152
  if (* input_line_pointer == '#')
153
    {
154
      input_line_pointer ++;
155
      expression (expressionP);
156
    }
157
}
158
 
159
valueT
160
md_section_align (segT segment, valueT size)
161
{
162
  int align = bfd_get_section_alignment (stdoutput, segment);
163
  return ((size + (1 << align) - 1) & (-1 << align));
164
}
165
 
166
symbolS *
167
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
168
{
169
  return 0;
170
}
171
 
172
 
173
/* Interface to relax_segment.  */
174
 
175
/* FIXME: Look through this.  */
176
 
177
const relax_typeS md_relax_table[] =
178
{
179
/* The fields are:
180
   1) most positive reach of this state,
181
   2) most negative reach of this state,
182
   3) how many bytes this mode will add to the size of the current frag
183
   4) which index into the table to try if we can't fit into this one.  */
184
 
185
  /* The first entry must be unused because an `rlx_more' value of zero ends
186
     each list.  */
187
  {1, 1, 0, 0},
188
 
189
  /* The displacement used by GAS is from the end of the 2 byte insn,
190
     so we subtract 2 from the following.  */
191
  /* 16 bit insn, 8 bit disp -> 10 bit range.
192
     This doesn't handle a branch in the right slot at the border:
193
     the "& -4" isn't taken into account.  It's not important enough to
194
     complicate things over it, so we subtract an extra 2 (or + 2 in -ve
195
     case).  */
196
  {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
197
  /* 32 bit insn, 24 bit disp -> 26 bit range.  */
198
  {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
199
  /* Same thing, but with leading nop for alignment.  */
200
  {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
201
};
202
 
203
/* Return an initial guess of the length by which a fragment must grow to
204
   hold a branch to reach its destination.
205
   Also updates fr_type/fr_subtype as necessary.
206
 
207
   Called just before doing relaxation.
208
   Any symbol that is now undefined will not become defined.
209
   The guess for fr_var is ACTUALLY the growth beyond fr_fix.
210
   Whatever we do to grow fr_fix or fr_var contributes to our returned value.
211
   Although it may not be explicit in the frag, pretend fr_var starts with a
212
 
213
 
214
int
215
md_estimate_size_before_relax (fragS * fragP, segT segment)
216
{
217
  /* The only thing we have to handle here are symbols outside of the
218
     current segment.  They may be undefined or in a different segment in
219
     which case linker scripts may place them anywhere.
220
     However, we can't finish the fragment here and emit the reloc as insn
221
     alignment requirements may move the insn about.  */
222
 
223
  if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
224
    {
225
      /* The symbol is undefined in this segment.
226
         Change the relaxation subtype to the max allowable and leave
227
         all further handling to md_convert_frag.  */
228
      fragP->fr_subtype = 2;
229
 
230
      {
231
        const CGEN_INSN * insn;
232
        int               i;
233
 
234
        /* Update the recorded insn.
235
           Fortunately we don't have to look very far.
236
           FIXME: Change this to record in the instruction the next higher
237
           relaxable insn to use.  */
238
        for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
239
          {
240
            if ((strcmp (CGEN_INSN_MNEMONIC (insn),
241
                         CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
242
                 == 0)
243
                && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
244
              break;
245
          }
246
        if (i == 4)
247
          abort ();
248
 
249
        fragP->fr_cgen.insn = insn;
250
        return 2;
251
      }
252
    }
253
 
254
  return md_relax_table[fragP->fr_subtype].rlx_length;
255
}
256
 
257
/* *fragP has been relaxed to its final size, and now needs to have
258
   the bytes inside it modified to conform to the new size.
259
 
260
   Called after relaxation is finished.
261
   fragP->fr_type == rs_machine_dependent.
262
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
263
 
264
void
265
md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
266
                 segT    sec  ATTRIBUTE_UNUSED,
267
                 fragS * fragP ATTRIBUTE_UNUSED)
268
{
269
  /* FIXME */
270
}
271
 
272
 
273
/* Functions concerning relocs.  */
274
 
275
/* The location from which a PC relative jump should be calculated,
276
   given a PC relative reloc.  */
277
 
278
long
279
md_pcrel_from_section (fixS * fixP, segT sec)
280
{
281
  if (fixP->fx_addsy != (symbolS *) NULL
282
      && (! S_IS_DEFINED (fixP->fx_addsy)
283
          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
284
    /* The symbol is undefined (or is defined but not in this section).
285
       Let the linker figure it out.  */
286
    return 0;
287
 
288
  return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
289
}
290
 
291
 
292
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
293
   Returns BFD_RELOC_NONE if no reloc type can be found.
294
   *FIXP may be modified if desired.  */
295
 
296
bfd_reloc_code_real_type
297
md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
298
                      const CGEN_OPERAND * operand,
299
                      fixS *               fixP)
300
{
301
  bfd_reloc_code_real_type type;
302
 
303
  switch (operand->type)
304
    {
305
    case OPENRISC_OPERAND_ABS_26:
306
      fixP->fx_pcrel = 0;
307
      type = BFD_RELOC_OPENRISC_ABS_26;
308
      goto emit;
309
    case OPENRISC_OPERAND_DISP_26:
310
      fixP->fx_pcrel = 1;
311
      type = BFD_RELOC_OPENRISC_REL_26;
312
      goto emit;
313
 
314
    case OPENRISC_OPERAND_HI16:
315
      type = BFD_RELOC_HI16;
316
      goto emit;
317
 
318
    case OPENRISC_OPERAND_LO16:
319
      type = BFD_RELOC_LO16;
320
      goto emit;
321
 
322
    emit:
323
      return type;
324
 
325
    default : /* avoid -Wall warning */
326
      break;
327
    }
328
 
329
  return BFD_RELOC_NONE;
330
}
331
 
332
/* Write a value out to the object file, using the appropriate endianness.  */
333
 
334
void
335
md_number_to_chars (char * buf, valueT val, int n)
336
{
337
  number_to_chars_bigendian (buf, val, n);
338
}
339
 
340
/* Turn a string in input_line_pointer into a floating point constant of type
341
   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
342
   emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
343
*/
344
 
345
/* Equal to MAX_PRECISION in atof-ieee.c */
346
#define MAX_LITTLENUMS 6
347
 
348
char *
349
md_atof (int type, char * litP, int *  sizeP)
350
{
351
  return ieee_md_atof (type, litP, sizeP, TRUE);
352
}
353
 
354
bfd_boolean
355
openrisc_fix_adjustable (fixS * fixP)
356
{
357
  /* We need the symbol name for the VTABLE entries.  */
358
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
359
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
360
    return 0;
361
 
362
  return 1;
363
}

powered by: WebSVN 2.1.0

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