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

Subversion Repositories open8_urisc

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

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

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

powered by: WebSVN 2.1.0

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