1/* tc-or1k.c -- Assembler for the OpenRISC family.
2   Copyright (C) 2001-2022 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 bool 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_section_alignment (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
278const char *
279md_atof (int type, char * litP, int *  sizeP)
280{
281  return ieee_md_atof (type, litP, sizeP, true);
282}
283
284bool
285or1k_fix_adjustable (fixS * fixP)
286{
287  /* We need the symbol name for the VTABLE entries.  */
288  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
289      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
290    return false;
291
292  return true;
293}
294
295#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
296
297arelent *
298tc_gen_reloc (asection * section, fixS * fixp)
299{
300  arelent *reloc;
301  bfd_reloc_code_real_type code;
302
303  reloc = XNEW (arelent);
304
305  reloc->sym_ptr_ptr = XNEW (asymbol *);
306  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
307  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
308
309  if (fixp->fx_pcrel)
310    {
311      if (section->use_rela_p)
312        fixp->fx_offset -= md_pcrel_from_section (fixp, section);
313      else
314        fixp->fx_offset = reloc->address;
315    }
316  reloc->addend = fixp->fx_offset;
317
318  code = fixp->fx_r_type;
319  switch (code)
320    {
321    case BFD_RELOC_16:
322      if (fixp->fx_pcrel)
323        code = BFD_RELOC_16_PCREL;
324      break;
325
326    case BFD_RELOC_32:
327      if (fixp->fx_pcrel)
328        code = BFD_RELOC_32_PCREL;
329      break;
330
331    case BFD_RELOC_64:
332      if (fixp->fx_pcrel)
333        code = BFD_RELOC_64_PCREL;
334      break;
335
336    default:
337      break;
338    }
339
340  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
341  if (reloc->howto == NULL)
342    {
343      as_bad_where (fixp->fx_file, fixp->fx_line,
344                    _
345                    ("cannot represent %s relocation in this object file format"),
346                    bfd_get_reloc_code_name (code));
347      return NULL;
348    }
349
350  return reloc;
351}
352
353void
354or1k_apply_fix (struct fix *f, valueT *t, segT s)
355{
356  gas_cgen_md_apply_fix (f, t, s);
357
358  switch (f->fx_r_type)
359    {
360    case BFD_RELOC_OR1K_TLS_GD_HI16:
361    case BFD_RELOC_OR1K_TLS_GD_LO16:
362    case BFD_RELOC_OR1K_TLS_GD_PG21:
363    case BFD_RELOC_OR1K_TLS_GD_LO13:
364    case BFD_RELOC_OR1K_TLS_LDM_HI16:
365    case BFD_RELOC_OR1K_TLS_LDM_LO16:
366    case BFD_RELOC_OR1K_TLS_LDM_PG21:
367    case BFD_RELOC_OR1K_TLS_LDM_LO13:
368    case BFD_RELOC_OR1K_TLS_LDO_HI16:
369    case BFD_RELOC_OR1K_TLS_LDO_LO16:
370    case BFD_RELOC_OR1K_TLS_IE_HI16:
371    case BFD_RELOC_OR1K_TLS_IE_LO16:
372    case BFD_RELOC_OR1K_TLS_IE_PG21:
373    case BFD_RELOC_OR1K_TLS_IE_LO13:
374    case BFD_RELOC_OR1K_TLS_LE_HI16:
375    case BFD_RELOC_OR1K_TLS_LE_LO16:
376      S_SET_THREAD_LOCAL (f->fx_addsy);
377      break;
378    default:
379      break;
380    }
381}
382
383void
384or1k_elf_final_processing (void)
385{
386  if (nodelay)
387    elf_elfheader (stdoutput)->e_flags |= EF_OR1K_NODELAY;
388}
389
390/* Standard calling conventions leave the CFA at SP on entry.  */
391
392void
393or1k_cfi_frame_initial_instructions (void)
394{
395    cfi_add_CFA_def_cfa_register (1);
396}
397
398