gas: avoid spurious failures in non-ELF targets in the SPARC testsuite.
[deliverable/binutils-gdb.git] / gas / config / tc-mt.c
CommitLineData
d031aafb 1/* tc-mt.c -- Assembler for the Morpho Technologies mt .
6f2750fe 2 Copyright (C) 2005-2016 Free Software Foundation, Inc.
a0defb2e
AH
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
ec2655a6 8 the Free Software Foundation; either version 3, or (at your option)
a0defb2e
AH
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
a0defb2e
AH
21#include "as.h"
22#include "dwarf2dbg.h"
3739860c 23#include "subsegs.h"
a0defb2e 24#include "symcat.h"
d031aafb
NS
25#include "opcodes/mt-desc.h"
26#include "opcodes/mt-opc.h"
a0defb2e
AH
27#include "cgen.h"
28#include "elf/common.h"
4970f871 29#include "elf/mt.h"
a0defb2e
AH
30
31/* Structure to hold all of the different components
32 describing an individual instruction. */
33typedef struct
34{
35 const CGEN_INSN * insn;
36 const CGEN_INSN * orig_insn;
37 CGEN_FIELDS fields;
38#if CGEN_INT_INSN_P
39 CGEN_INSN_INT buffer [1];
40#define INSN_VALUE(buf) (*(buf))
41#else
42 unsigned char buffer [CGEN_MAX_INSN_SIZE];
43#define INSN_VALUE(buf) (buf)
44#endif
45 char * addr;
46 fragS * frag;
47 int num_fixups;
48 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
49 int indices [MAX_OPERAND_INSTANCES];
50}
d031aafb 51mt_insn;
a0defb2e
AH
52
53
54const char comment_chars[] = ";";
55const char line_comment_chars[] = "#";
3739860c 56const char line_separator_chars[] = "";
a0defb2e
AH
57const char EXP_CHARS[] = "eE";
58const char FLT_CHARS[] = "dD";
59
60/* The target specific pseudo-ops which we support. */
61const pseudo_typeS md_pseudo_table[] =
62{
3739860c 63 { "word", cons, 4 },
a0defb2e
AH
64 { NULL, NULL, 0 }
65};
66
67\f
68
69static int no_scheduling_restrictions = 0;
70
3739860c 71struct option md_longopts[] =
a0defb2e
AH
72{
73#define OPTION_NO_SCHED_REST (OPTION_MD_BASE)
74 { "nosched", no_argument, NULL, OPTION_NO_SCHED_REST },
75#define OPTION_MARCH (OPTION_MD_BASE + 1)
76 { "march", required_argument, NULL, OPTION_MARCH},
77 { NULL, no_argument, NULL, 0 },
78};
79size_t md_longopts_size = sizeof (md_longopts);
80
81const char * md_shortopts = "";
82
83/* Mach selected from command line. */
d031aafb
NS
84static int mt_mach = bfd_mach_ms1;
85static unsigned mt_mach_bitmask = 1 << MACH_MS1;
a0defb2e
AH
86
87/* Flags to set in the elf header */
d031aafb 88static flagword mt_flags = EF_MT_CPU_MRISC;
a0defb2e
AH
89
90/* The architecture to use. */
d031aafb 91enum mt_architectures
a0defb2e
AH
92 {
93 ms1_64_001,
94 ms1_16_002,
6f84a2a6
NS
95 ms1_16_003,
96 ms2
a0defb2e
AH
97 };
98
d031aafb 99/* MT architecture we are using for this output file. */
f07efa0b 100static enum mt_architectures mt_arch = ms1_16_002;
a0defb2e
AH
101
102int
17b9d67d 103md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg)
a0defb2e
AH
104{
105 switch (c)
106 {
107 case OPTION_MARCH:
f07efa0b 108 if (strcmp (arg, "ms1-64-001") == 0)
a0defb2e 109 {
d031aafb
NS
110 mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC;
111 mt_mach = bfd_mach_ms1;
112 mt_mach_bitmask = 1 << MACH_MS1;
113 mt_arch = ms1_64_001;
a0defb2e 114 }
f07efa0b 115 else if (strcmp (arg, "ms1-16-002") == 0)
a0defb2e 116 {
d031aafb
NS
117 mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC;
118 mt_mach = bfd_mach_ms1;
119 mt_mach_bitmask = 1 << MACH_MS1;
120 mt_arch = ms1_16_002;
a0defb2e 121 }
f07efa0b 122 else if (strcmp (arg, "ms1-16-003") == 0)
a0defb2e 123 {
d031aafb
NS
124 mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC2;
125 mt_mach = bfd_mach_mrisc2;
126 mt_mach_bitmask = 1 << MACH_MS1_003;
127 mt_arch = ms1_16_003;
a0defb2e 128 }
f07efa0b 129 else if (strcmp (arg, "ms2") == 0)
6f84a2a6 130 {
d031aafb
NS
131 mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MS2;
132 mt_mach = bfd_mach_mrisc2;
133 mt_mach_bitmask = 1 << MACH_MS2;
134 mt_arch = ms2;
6f84a2a6 135 }
a0defb2e
AH
136 case OPTION_NO_SCHED_REST:
137 no_scheduling_restrictions = 1;
138 break;
139 default:
140 return 0;
141 }
142
143 return 1;
144}
145
146
147void
148md_show_usage (FILE * stream)
149{
d031aafb 150 fprintf (stream, _("MT specific command line options:\n"));
f07efa0b
NS
151 fprintf (stream, _(" -march=ms1-64-001 allow ms1-64-001 instructions\n"));
152 fprintf (stream, _(" -march=ms1-16-002 allow ms1-16-002 instructions (default)\n"));
153 fprintf (stream, _(" -march=ms1-16-003 allow ms1-16-003 instructions\n"));
6f84a2a6 154 fprintf (stream, _(" -march=ms2 allow ms2 instructions \n"));
f07efa0b 155 fprintf (stream, _(" -nosched disable scheduling restrictions\n"));
a0defb2e
AH
156}
157
158\f
159void
160md_begin (void)
161{
162 /* Initialize the `cgen' interface. */
3739860c 163
a0defb2e 164 /* Set the machine number and endian. */
d031aafb
NS
165 gas_cgen_cpu_desc = mt_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, mt_mach_bitmask,
166 CGEN_CPU_OPEN_ENDIAN,
167 CGEN_ENDIAN_BIG,
168 CGEN_CPU_OPEN_END);
169 mt_cgen_init_asm (gas_cgen_cpu_desc);
a0defb2e
AH
170
171 /* This is a callback from cgen to gas to parse operands. */
172 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
173
174 /* Set the ELF flags if desired. */
d031aafb
NS
175 if (mt_flags)
176 bfd_set_private_flags (stdoutput, mt_flags);
a0defb2e
AH
177
178 /* Set the machine type. */
d031aafb 179 bfd_default_set_arch_mach (stdoutput, bfd_arch_mt, mt_mach);
a0defb2e
AH
180}
181
182void
183md_assemble (char * str)
184{
185 static long delayed_load_register = 0;
6f84a2a6 186 static long prev_delayed_load_register = 0;
a0defb2e
AH
187 static int last_insn_had_delay_slot = 0;
188 static int last_insn_in_noncond_delay_slot = 0;
189 static int last_insn_has_load_delay = 0;
190 static int last_insn_was_memory_access = 0;
191 static int last_insn_was_io_insn = 0;
192 static int last_insn_was_arithmetic_or_logic = 0;
193 static int last_insn_was_branch_insn = 0;
194 static int last_insn_was_conditional_branch_insn = 0;
195
d031aafb 196 mt_insn insn;
a0defb2e
AH
197 char * errmsg;
198
199 /* Initialize GAS's cgen interface for a new instruction. */
200 gas_cgen_init_parse ();
201
d031aafb 202 insn.insn = mt_cgen_assemble_insn
a0defb2e
AH
203 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
204
205 if (!insn.insn)
206 {
207 as_bad ("%s", errmsg);
208 return;
209 }
210
211 /* Doesn't really matter what we pass for RELAX_P here. */
212 gas_cgen_finish_insn (insn.insn, insn.buffer,
213 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
214
215
216 /* Handle Scheduling Restrictions. */
217 if (!no_scheduling_restrictions)
218 {
219 /* Detect consecutive Memory Accesses. */
220 if (last_insn_was_memory_access
221 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS)
d031aafb 222 && mt_mach == ms1_64_001)
a0defb2e
AH
223 as_warn (_("instruction %s may not follow another memory access instruction."),
224 CGEN_INSN_NAME (insn.insn));
225
226 /* Detect consecutive I/O Instructions. */
227 else if (last_insn_was_io_insn
228 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN))
229 as_warn (_("instruction %s may not follow another I/O instruction."),
230 CGEN_INSN_NAME (insn.insn));
231
232 /* Detect consecutive branch instructions. */
233 else if (last_insn_was_branch_insn
234 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN))
235 as_warn (_("%s may not occupy the delay slot of another branch insn."),
236 CGEN_INSN_NAME (insn.insn));
237
238 /* Detect data dependencies on delayed loads: memory and input insns. */
239 if (last_insn_has_load_delay && delayed_load_register)
240 {
241 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
242 && insn.fields.f_sr1 == delayed_load_register)
243 as_warn (_("operand references R%ld of previous load."),
244 insn.fields.f_sr1);
245
246 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
247 && insn.fields.f_sr2 == delayed_load_register)
248 as_warn (_("operand references R%ld of previous load."),
249 insn.fields.f_sr2);
250 }
251
6f84a2a6 252 /* Detect JAL/RETI hazard */
d031aafb 253 if (mt_mach == ms2
6f84a2a6
NS
254 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_JAL_HAZARD))
255 {
256 if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
257 && insn.fields.f_sr1 == delayed_load_register)
258 || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
259 && insn.fields.f_sr2 == delayed_load_register))
9fd07943 260 as_warn (_("operand references R%ld of previous instruction."),
6f84a2a6
NS
261 delayed_load_register);
262 else if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
263 && insn.fields.f_sr1 == prev_delayed_load_register)
264 || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
265 && insn.fields.f_sr2 == prev_delayed_load_register))
9fd07943 266 as_warn (_("operand references R%ld of instruction before previous."),
6f84a2a6
NS
267 prev_delayed_load_register);
268 }
3739860c 269
a0defb2e
AH
270 /* Detect data dependency between conditional branch instruction
271 and an immediately preceding arithmetic or logical instruction. */
272 if (last_insn_was_arithmetic_or_logic
273 && !last_insn_in_noncond_delay_slot
274 && (delayed_load_register != 0)
275 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
d031aafb 276 && mt_arch == ms1_64_001)
a0defb2e
AH
277 {
278 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
279 && insn.fields.f_sr1 == delayed_load_register)
280 as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
281 insn.fields.f_sr1);
282
283 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
284 && insn.fields.f_sr2 == delayed_load_register)
285 as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
286 insn.fields.f_sr2);
287 }
288 }
289
290 /* Keep track of details of this insn for processing next insn. */
291 last_insn_in_noncond_delay_slot = last_insn_was_branch_insn
292 && !last_insn_was_conditional_branch_insn;
293
294 last_insn_had_delay_slot =
295 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
87975d2a 296 (void) last_insn_had_delay_slot;
a0defb2e
AH
297
298 last_insn_has_load_delay =
299 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
300
301 last_insn_was_memory_access =
302 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS);
303
304 last_insn_was_io_insn =
305 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN);
306
307 last_insn_was_arithmetic_or_logic =
308 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_AL_INSN);
309
310 last_insn_was_branch_insn =
311 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN);
3739860c 312
a0defb2e
AH
313 last_insn_was_conditional_branch_insn =
314 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
315 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2);
3739860c 316
6f84a2a6 317 prev_delayed_load_register = delayed_load_register;
3739860c 318
a0defb2e 319 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDR))
3739860c 320 delayed_load_register = insn.fields.f_dr;
a0defb2e 321 else if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDRRR))
3739860c 322 delayed_load_register = insn.fields.f_drrr;
a0defb2e 323 else /* Insns has no destination register. */
3739860c 324 delayed_load_register = 0;
a0defb2e
AH
325
326 /* Generate dwarf2 line numbers. */
3739860c 327 dwarf2_emit_insn (4);
a0defb2e
AH
328}
329
330valueT
331md_section_align (segT segment, valueT size)
332{
333 int align = bfd_get_section_alignment (stdoutput, segment);
334
8d3842cd 335 return ((size + (1 << align) - 1) & -(1 << align));
a0defb2e
AH
336}
337
338symbolS *
339md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
340{
341 return NULL;
342}
343\f
344int
345md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
346 segT segment ATTRIBUTE_UNUSED)
347{
348 as_fatal (_("md_estimate_size_before_relax\n"));
349 return 1;
3739860c 350}
a0defb2e
AH
351
352/* *fragP has been relaxed to its final size, and now needs to have
353 the bytes inside it modified to conform to the new size.
354
355 Called after relaxation is finished.
356 fragP->fr_type == rs_machine_dependent.
357 fragP->fr_subtype is the subtype of what the address relaxed to. */
358
359void
360md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
361 segT sec ATTRIBUTE_UNUSED,
362 fragS * fragP ATTRIBUTE_UNUSED)
363{
364}
365
366\f
367/* Functions concerning relocs. */
368
369long
370md_pcrel_from_section (fixS *fixP, segT sec)
371{
372 if (fixP->fx_addsy != (symbolS *) NULL
373 && (!S_IS_DEFINED (fixP->fx_addsy)
374 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
375 /* The symbol is undefined (or is defined but not in this section).
376 Let the linker figure it out. */
377 return 0;
378
379 /* Return the address of the opcode - cgen adjusts for opcode size
380 itself, to be consistent with the disassembler, which must do
381 so. */
382 return fixP->fx_where + fixP->fx_frag->fr_address;
383}
384
385
386/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
387 Returns BFD_RELOC_NONE if no reloc type can be found.
388 *FIXP may be modified if desired. */
389
390bfd_reloc_code_real_type
391md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED,
392 const CGEN_OPERAND * operand,
393 fixS * fixP ATTRIBUTE_UNUSED)
394{
395 bfd_reloc_code_real_type result;
396
397 result = BFD_RELOC_NONE;
398
399 switch (operand->type)
400 {
d031aafb 401 case MT_OPERAND_IMM16O:
a0defb2e
AH
402 result = BFD_RELOC_16_PCREL;
403 fixP->fx_pcrel = 1;
404 /* fixP->fx_no_overflow = 1; */
405 break;
d031aafb
NS
406 case MT_OPERAND_IMM16:
407 case MT_OPERAND_IMM16Z:
a0defb2e
AH
408 /* These may have been processed at parse time. */
409 if (fixP->fx_cgen.opinfo != 0)
410 result = fixP->fx_cgen.opinfo;
411 fixP->fx_no_overflow = 1;
412 break;
d031aafb
NS
413 case MT_OPERAND_LOOPSIZE:
414 result = BFD_RELOC_MT_PCINSN8;
6f84a2a6
NS
415 fixP->fx_pcrel = 1;
416 /* Adjust for the delay slot, which is not part of the loop */
417 fixP->fx_offset -= 8;
418 break;
a0defb2e
AH
419 default:
420 result = BFD_RELOC_NONE;
421 break;
422 }
423
424 return result;
425}
426
427/* Write a value out to the object file, using the appropriate endianness. */
428
429void
430md_number_to_chars (char * buf, valueT val, int n)
431{
432 number_to_chars_bigendian (buf, val, n);
433}
434
6d4af3c2 435const char *
499ac353 436md_atof (int type, char * litP, int * sizeP)
a0defb2e 437{
499ac353 438 return ieee_md_atof (type, litP, sizeP, FALSE);
a0defb2e
AH
439}
440
441/* See whether we need to force a relocation into the output file. */
442
443int
d031aafb 444mt_force_relocation (fixS * fixp ATTRIBUTE_UNUSED)
a0defb2e
AH
445{
446 return 0;
447}
448
449void
d031aafb 450mt_apply_fix (fixS *fixP, valueT *valueP, segT seg)
a0defb2e
AH
451{
452 if ((fixP->fx_pcrel != 0) && (fixP->fx_r_type == BFD_RELOC_32))
453 fixP->fx_r_type = BFD_RELOC_32_PCREL;
454
455 gas_cgen_md_apply_fix (fixP, valueP, seg);
456}
457
458bfd_boolean
d031aafb 459mt_fix_adjustable (fixS * fixP)
a0defb2e 460{
a0defb2e
AH
461 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
462 {
463 const CGEN_INSN *insn = NULL;
464 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
465 const CGEN_OPERAND *operand;
466
467 operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
87975d2a 468 md_cgen_lookup_reloc (insn, operand, fixP);
a0defb2e 469 }
a0defb2e
AH
470
471 if (fixP->fx_addsy == NULL)
472 return TRUE;
3739860c 473
a0defb2e
AH
474 /* Prevent all adjustments to global symbols. */
475 if (S_IS_EXTERNAL (fixP->fx_addsy))
476 return FALSE;
3739860c 477
a0defb2e
AH
478 if (S_IS_WEAK (fixP->fx_addsy))
479 return FALSE;
3739860c 480
a0defb2e
AH
481 return 1;
482}
This page took 0.536811 seconds and 4 git commands to generate.