1/* tc-or1k.c -- Assembler for the OpenRISC family.
2   Copyright (C) 2001-2017 Free Software Foundation, Inc.
3   Contributed for OR32 by Johan Rydberg, jrydberg@opencores.org
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 this program; if not, see <http://www.gnu.org/licenses/> */
19#include "as.h"
20#include "safe-ctype.h"
21#include "subsegs.h"
22#include "symcat.h"
23#include "opcodes/or1k-desc.h"
24#include "opcodes/or1k-opc.h"
25#include "cgen.h"
26#include "elf/or1k.h"
27#include "dw2gencfi.h"
28
29/* Structure to hold all of the different components describing
30   an individual instruction.  */
31
32typedef struct
33{
34  const CGEN_INSN *     insn;
35  const CGEN_INSN *     orig_insn;
36  CGEN_FIELDS           fields;
37#if CGEN_INT_INSN_P
38  CGEN_INSN_INT         buffer [1];
39#define INSN_VALUE(buf) (*(buf))
40#else
41  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
42#define INSN_VALUE(buf) (buf)
43#endif
44  char *                addr;
45  fragS *               frag;
46  int                   num_fixups;
47  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
48  int                   indices [MAX_OPERAND_INSTANCES];
49}
50or1k_insn;
51
52const char comment_chars[]        = "#";
53const char line_comment_chars[]   = "#";
54const char line_separator_chars[] = ";";
55const char EXP_CHARS[]            = "eE";
56const char FLT_CHARS[]            = "dD";
57
58#define OR1K_SHORTOPTS "m:"
59const char * md_shortopts = OR1K_SHORTOPTS;
60
61struct option md_longopts[] =
62{
63  {NULL, no_argument, NULL, 0}
64};
65size_t md_longopts_size = sizeof (md_longopts);
66
67unsigned long or1k_machine = 0; /* default */
68
69int
70md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
71{
72  return 0;
73}
74
75void
76md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
77{
78}
79
80static void
81ignore_pseudo (int val ATTRIBUTE_UNUSED)
82{
83  discard_rest_of_line ();
84}
85
86static bfd_boolean nodelay = FALSE;
87static void
88s_nodelay (int val ATTRIBUTE_UNUSED)
89{
90  nodelay = TRUE;
91}
92
93const char or1k_comment_chars [] = ";#";
94
95/* The target specific pseudo-ops which we support.  */
96const pseudo_typeS md_pseudo_table[] =
97{
98  { "align",    s_align_bytes,  0 },
99  { "word",     cons,           4 },
100  { "proc",     ignore_pseudo,  0 },
101  { "endproc",  ignore_pseudo,  0 },
102  { "nodelay",  s_nodelay,      0 },
103  { NULL,       NULL,           0 }
104};
105
106
107void
108md_begin (void)
109{
110  /* Initialize the `cgen' interface.  */
111
112  /* Set the machine number and endian.  */
113  gas_cgen_cpu_desc = or1k_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
114                                              CGEN_CPU_OPEN_ENDIAN,
115                                              CGEN_ENDIAN_BIG,
116                                              CGEN_CPU_OPEN_END);
117  or1k_cgen_init_asm (gas_cgen_cpu_desc);
118
119  /* This is a callback from cgen to gas to parse operands.  */
120  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
121}
122
123void
124md_assemble (char * str)
125{
126  static int last_insn_had_delay_slot = 0;
127  or1k_insn insn;
128  char *    errmsg;
129
130  /* Initialize GAS's cgen interface for a new instruction.  */
131  gas_cgen_init_parse ();
132
133  insn.insn = or1k_cgen_assemble_insn
134    (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
135
136  if (!insn.insn)
137    {
138      as_bad ("%s", errmsg);
139      return;
140    }
141
142  /* Doesn't really matter what we pass for RELAX_P here.  */
143  gas_cgen_finish_insn (insn.insn, insn.buffer,
144                        CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
145
146  last_insn_had_delay_slot
147    = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
148  (void) last_insn_had_delay_slot;
149}
150
151
152/* The syntax in the manual says constants begin with '#'.
153   We just ignore it.  */
154
155void
156md_operand (expressionS * expressionP)
157{
158  if (* input_line_pointer == '#')
159    {
160      input_line_pointer ++;
161      expression (expressionP);
162    }
163}
164
165valueT
166md_section_align (segT segment, valueT size)
167{
168  int align = bfd_get_section_alignment (stdoutput, segment);
169  return ((size + (1 << align) - 1) & -(1 << align));
170}
171
172symbolS *
173md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
174{
175  return 0;
176}
177
178
179/* Interface to relax_segment.  */
180
181const relax_typeS md_relax_table[] =
182{
183/* The fields are:
184   1) most positive reach of this state,
185   2) most negative reach of this state,
186   3) how many bytes this mode will add to the size of the current frag
187   4) which index into the table to try if we can't fit into this one.  */
188
189  /* The first entry must be unused because an `rlx_more' value of zero ends
190     each list.  */
191  {1, 1, 0, 0},
192
193  /* The displacement used by GAS is from the end of the 4 byte insn,
194     so we subtract 4 from the following.  */
195  {(((1 << 25) - 1) << 2) - 4, -(1 << 25) - 4, 0, 0},
196};
197
198int
199md_estimate_size_before_relax (fragS * fragP, segT segment ATTRIBUTE_UNUSED)
200{
201  return md_relax_table[fragP->fr_subtype].rlx_length;
202}
203
204/* *fragP has been relaxed to its final size, and now needs to have
205   the bytes inside it modified to conform to the new size.
206
207   Called after relaxation is finished.
208   fragP->fr_type == rs_machine_dependent.
209   fragP->fr_subtype is the subtype of what the address relaxed to.  */
210
211void
212md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
213                 segT    sec  ATTRIBUTE_UNUSED,
214                 fragS * fragP ATTRIBUTE_UNUSED)
215{
216  /* FIXME */
217}
218
219
220/* Functions concerning relocs.  */
221
222/* The location from which a PC relative jump should be calculated,
223   given a PC relative reloc.  */
224
225long
226md_pcrel_from_section (fixS * fixP, segT sec)
227{
228  if (fixP->fx_addsy != (symbolS *) NULL
229      && (! S_IS_DEFINED (fixP->fx_addsy)
230          || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
231          || S_IS_EXTERNAL (fixP->fx_addsy)
232          || S_IS_WEAK (fixP->fx_addsy)))
233    {
234        /* The symbol is undefined (or is defined but not in this section).
235         Let the linker figure it out.  */
236      return 0;
237    }
238
239  return fixP->fx_frag->fr_address + fixP->fx_where;
240}
241
242
243/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
244   Returns BFD_RELOC_NONE if no reloc type can be found.
245   *FIXP may be modified if desired.  */
246
247bfd_reloc_code_real_type
248md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
249                      const CGEN_OPERAND * operand,
250                      fixS *               fixP)
251{
252  if (fixP->fx_cgen.opinfo)
253    return fixP->fx_cgen.opinfo;
254
255  switch (operand->type)
256    {
257    case OR1K_OPERAND_DISP26:
258      fixP->fx_pcrel = 1;
259      return BFD_RELOC_OR1K_REL_26;
260
261    default: /* avoid -Wall warning */
262      return BFD_RELOC_NONE;
263    }
264}
265
266/* Write a value out to the object file, using the appropriate endianness.  */
267
268void
269md_number_to_chars (char * buf, valueT val, int n)
270{
271  number_to_chars_bigendian (buf, val, n);
272}
273
274/* Turn a string in input_line_pointer into a floating point constant of type
275   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
276   emitted is stored in *sizeP .  An error message is returned, or NULL on OK.  */
277
278/* Equal to MAX_PRECISION in atof-ieee.c.  */
279#define MAX_LITTLENUMS 6
280
281const char *
282md_atof (int type, char * litP, int *  sizeP)
283{
284  return ieee_md_atof (type, litP, sizeP, TRUE);
285}
286
287bfd_boolean
288or1k_fix_adjustable (fixS * fixP)
289{
290  /* We need the symbol name for the VTABLE entries.  */
291  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
292      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
293    return FALSE;
294
295  return TRUE;
296}
297
298#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
299
300arelent *
301tc_gen_reloc (asection * section, fixS * fixp)
302{
303  arelent *reloc;
304  bfd_reloc_code_real_type code;
305
306  reloc = XNEW (arelent);
307
308  reloc->sym_ptr_ptr = XNEW (asymbol *);
309  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
310  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
311
312  if (fixp->fx_pcrel)
313    {
314      if (section->use_rela_p)
315        fixp->fx_offset -= md_pcrel_from_section (fixp, section);
316      else
317        fixp->fx_offset = reloc->address;
318    }
319  reloc->addend = fixp->fx_offset;
320
321  code = fixp->fx_r_type;
322  switch (code)
323    {
324    case BFD_RELOC_16:
325      if (fixp->fx_pcrel)
326        code = BFD_RELOC_16_PCREL;
327      break;
328
329    case BFD_RELOC_32:
330      if (fixp->fx_pcrel)
331        code = BFD_RELOC_32_PCREL;
332      break;
333
334    case BFD_RELOC_64:
335      if (fixp->fx_pcrel)
336        code = BFD_RELOC_64_PCREL;
337      break;
338
339    default:
340      break;
341    }
342
343  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
344  if (reloc->howto == NULL)
345    {
346      as_bad_where (fixp->fx_file, fixp->fx_line,
347                    _
348                    ("cannot represent %s relocation in this object file format"),
349                    bfd_get_reloc_code_name (code));
350      return NULL;
351    }
352
353  return reloc;
354}
355
356void
357or1k_apply_fix (struct fix *f, valueT *t, segT s)
358{
359  gas_cgen_md_apply_fix (f, t, s);
360
361  switch (f->fx_r_type)
362    {
363    case BFD_RELOC_OR1K_TLS_GD_HI16:
364    case BFD_RELOC_OR1K_TLS_GD_LO16:
365    case BFD_RELOC_OR1K_TLS_LDM_HI16:
366    case BFD_RELOC_OR1K_TLS_LDM_LO16:
367    case BFD_RELOC_OR1K_TLS_LDO_HI16:
368    case BFD_RELOC_OR1K_TLS_LDO_LO16:
369    case BFD_RELOC_OR1K_TLS_IE_HI16:
370    case BFD_RELOC_OR1K_TLS_IE_LO16:
371    case BFD_RELOC_OR1K_TLS_LE_HI16:
372    case BFD_RELOC_OR1K_TLS_LE_LO16:
373      S_SET_THREAD_LOCAL (f->fx_addsy);
374      break;
375    default:
376      break;
377    }
378}
379
380void
381or1k_elf_final_processing (void)
382{
383  if (nodelay)
384    elf_elfheader (stdoutput)->e_flags |= EF_OR1K_NODELAY;
385}
386
387/* Standard calling conventions leave the CFA at SP on entry.  */
388
389void
390or1k_cfi_frame_initial_instructions (void)
391{
392    cfi_add_CFA_def_cfa_register (1);
393}
394
395