xref: /netbsd-src/external/gpl3/binutils.old/dist/gas/config/tc-m32c.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
116dce513Schristos /* tc-m32c.c -- Assembler for the Renesas M32C.
2*e992f068Schristos    Copyright (C) 2005-2022 Free Software Foundation, Inc.
316dce513Schristos    Contributed by RedHat.
416dce513Schristos 
516dce513Schristos    This file is part of GAS, the GNU Assembler.
616dce513Schristos 
716dce513Schristos    GAS is free software; you can redistribute it and/or modify
816dce513Schristos    it under the terms of the GNU General Public License as published by
916dce513Schristos    the Free Software Foundation; either version 3, or (at your option)
1016dce513Schristos    any later version.
1116dce513Schristos 
1216dce513Schristos    GAS is distributed in the hope that it will be useful,
1316dce513Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1416dce513Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1516dce513Schristos    GNU General Public License for more details.
1616dce513Schristos 
1716dce513Schristos    You should have received a copy of the GNU General Public License
18ede78133Schristos    along with this program; if not, write to the Free Software
19ede78133Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20ede78133Schristos    MA 02110-1301, USA.  */
2116dce513Schristos 
2216dce513Schristos #include "as.h"
2316dce513Schristos #include "subsegs.h"
2416dce513Schristos #include "symcat.h"
2516dce513Schristos #include "opcodes/m32c-desc.h"
2616dce513Schristos #include "opcodes/m32c-opc.h"
2716dce513Schristos #include "cgen.h"
2816dce513Schristos #include "elf/common.h"
2916dce513Schristos #include "elf/m32c.h"
3016dce513Schristos #include "safe-ctype.h"
3116dce513Schristos 
3216dce513Schristos /* Structure to hold all of the different components
3316dce513Schristos    describing an individual instruction.  */
3416dce513Schristos typedef struct
3516dce513Schristos {
3616dce513Schristos   const CGEN_INSN *	insn;
3716dce513Schristos   const CGEN_INSN *	orig_insn;
3816dce513Schristos   CGEN_FIELDS		fields;
3916dce513Schristos #if CGEN_INT_INSN_P
4016dce513Schristos   CGEN_INSN_INT         buffer [1];
4116dce513Schristos #define INSN_VALUE(buf) (*(buf))
4216dce513Schristos #else
4316dce513Schristos   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
4416dce513Schristos #define INSN_VALUE(buf) (buf)
4516dce513Schristos #endif
4616dce513Schristos   char *		addr;
4716dce513Schristos   fragS *		frag;
4816dce513Schristos   int                   num_fixups;
4916dce513Schristos   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
5016dce513Schristos   int                   indices [MAX_OPERAND_INSTANCES];
5116dce513Schristos }
5216dce513Schristos m32c_insn;
5316dce513Schristos 
5416dce513Schristos #define rl_for(_insn) (CGEN_ATTR_CGEN_INSN_RL_TYPE_VALUE (&((_insn).insn->base->attrs)))
5516dce513Schristos #define relaxable(_insn) (CGEN_ATTR_CGEN_INSN_RELAXABLE_VALUE (&((_insn).insn->base->attrs)))
5616dce513Schristos 
5716dce513Schristos const char comment_chars[]        = ";";
5816dce513Schristos const char line_comment_chars[]   = "#";
5916dce513Schristos const char line_separator_chars[] = "|";
6016dce513Schristos const char EXP_CHARS[]            = "eE";
6116dce513Schristos const char FLT_CHARS[]            = "dD";
6216dce513Schristos 
6316dce513Schristos #define M32C_SHORTOPTS ""
6416dce513Schristos const char * md_shortopts = M32C_SHORTOPTS;
6516dce513Schristos 
6616dce513Schristos /* assembler options */
6716dce513Schristos #define OPTION_CPU_M16C	       (OPTION_MD_BASE)
6816dce513Schristos #define OPTION_CPU_M32C        (OPTION_MD_BASE + 1)
6916dce513Schristos #define OPTION_LINKRELAX       (OPTION_MD_BASE + 2)
7016dce513Schristos #define OPTION_H_TICK_HEX      (OPTION_MD_BASE + 3)
7116dce513Schristos 
7216dce513Schristos struct option md_longopts[] =
7316dce513Schristos {
7416dce513Schristos   { "m16c",       no_argument,	      NULL, OPTION_CPU_M16C   },
7516dce513Schristos   { "m32c",       no_argument,	      NULL, OPTION_CPU_M32C   },
7616dce513Schristos   { "relax",      no_argument,	      NULL, OPTION_LINKRELAX   },
7716dce513Schristos   { "h-tick-hex", no_argument,	      NULL, OPTION_H_TICK_HEX  },
7816dce513Schristos   {NULL, no_argument, NULL, 0}
7916dce513Schristos };
8016dce513Schristos size_t md_longopts_size = sizeof (md_longopts);
8116dce513Schristos 
8216dce513Schristos /* Default machine */
8316dce513Schristos 
8416dce513Schristos #define DEFAULT_MACHINE bfd_mach_m16c
8516dce513Schristos #define DEFAULT_FLAGS	EF_M32C_CPU_M16C
8616dce513Schristos 
8716dce513Schristos static unsigned long m32c_mach = bfd_mach_m16c;
8816dce513Schristos static int cpu_mach = (1 << MACH_M16C);
8916dce513Schristos static int m32c_relax = 0;
9016dce513Schristos 
9116dce513Schristos /* Flags to set in the elf header */
9216dce513Schristos static flagword m32c_flags = DEFAULT_FLAGS;
9316dce513Schristos 
9416dce513Schristos static char default_isa = 1 << (7 - ISA_M16C);
9516dce513Schristos static CGEN_BITSET m32c_isa = {1, & default_isa};
9616dce513Schristos 
9716dce513Schristos static void
set_isa(enum isa_attr isa_num)9816dce513Schristos set_isa (enum isa_attr isa_num)
9916dce513Schristos {
10016dce513Schristos   cgen_bitset_set (& m32c_isa, isa_num);
10116dce513Schristos }
10216dce513Schristos 
10316dce513Schristos static void s_bss (int);
10416dce513Schristos 
10516dce513Schristos int
md_parse_option(int c,const char * arg ATTRIBUTE_UNUSED)10616dce513Schristos md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
10716dce513Schristos {
10816dce513Schristos   switch (c)
10916dce513Schristos     {
11016dce513Schristos     case OPTION_CPU_M16C:
11116dce513Schristos       m32c_flags = (m32c_flags & ~EF_M32C_CPU_MASK) | EF_M32C_CPU_M16C;
11216dce513Schristos       m32c_mach = bfd_mach_m16c;
11316dce513Schristos       cpu_mach = (1 << MACH_M16C);
11416dce513Schristos       set_isa (ISA_M16C);
11516dce513Schristos       break;
11616dce513Schristos 
11716dce513Schristos     case OPTION_CPU_M32C:
11816dce513Schristos       m32c_flags = (m32c_flags & ~EF_M32C_CPU_MASK) | EF_M32C_CPU_M32C;
11916dce513Schristos       m32c_mach = bfd_mach_m32c;
12016dce513Schristos       cpu_mach = (1 << MACH_M32C);
12116dce513Schristos       set_isa (ISA_M32C);
12216dce513Schristos       break;
12316dce513Schristos 
12416dce513Schristos     case OPTION_LINKRELAX:
12516dce513Schristos       m32c_relax = 1;
12616dce513Schristos       break;
12716dce513Schristos 
12816dce513Schristos     case OPTION_H_TICK_HEX:
12916dce513Schristos       enable_h_tick_hex = 1;
13016dce513Schristos       break;
13116dce513Schristos 
13216dce513Schristos     default:
13316dce513Schristos       return 0;
13416dce513Schristos     }
13516dce513Schristos   return 1;
13616dce513Schristos }
13716dce513Schristos 
13816dce513Schristos void
md_show_usage(FILE * stream)13916dce513Schristos md_show_usage (FILE * stream)
14016dce513Schristos {
14116dce513Schristos   fprintf (stream, _(" M32C specific command line options:\n"));
14216dce513Schristos }
14316dce513Schristos 
14416dce513Schristos static void
s_bss(int ignore ATTRIBUTE_UNUSED)14516dce513Schristos s_bss (int ignore ATTRIBUTE_UNUSED)
14616dce513Schristos {
14716dce513Schristos   int temp;
14816dce513Schristos 
14916dce513Schristos   temp = get_absolute_expression ();
15016dce513Schristos   subseg_set (bss_section, (subsegT) temp);
15116dce513Schristos   demand_empty_rest_of_line ();
15216dce513Schristos }
15316dce513Schristos 
15416dce513Schristos /* The target specific pseudo-ops which we support.  */
15516dce513Schristos const pseudo_typeS md_pseudo_table[] =
15616dce513Schristos {
15716dce513Schristos   { "bss",	s_bss, 		0},
15816dce513Schristos   { "3byte",	cons,		3 },
15916dce513Schristos   { "word",	cons,		4 },
16016dce513Schristos   { NULL, 	NULL, 		0 }
16116dce513Schristos };
16216dce513Schristos 
16316dce513Schristos 
16416dce513Schristos void
md_begin(void)16516dce513Schristos md_begin (void)
16616dce513Schristos {
16716dce513Schristos   /* Initialize the `cgen' interface.  */
16816dce513Schristos 
16916dce513Schristos   /* Set the machine number and endian.  */
17016dce513Schristos   gas_cgen_cpu_desc = m32c_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
17116dce513Schristos 					  CGEN_CPU_OPEN_ENDIAN,
17216dce513Schristos 					  CGEN_ENDIAN_BIG,
17316dce513Schristos 					  CGEN_CPU_OPEN_ISAS, & m32c_isa,
17416dce513Schristos 					  CGEN_CPU_OPEN_END);
17516dce513Schristos 
17616dce513Schristos   m32c_cgen_init_asm (gas_cgen_cpu_desc);
17716dce513Schristos 
17816dce513Schristos   /* This is a callback from cgen to gas to parse operands.  */
17916dce513Schristos   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
18016dce513Schristos 
18116dce513Schristos   /* Set the ELF flags if desired. */
18216dce513Schristos   if (m32c_flags)
18316dce513Schristos     bfd_set_private_flags (stdoutput, m32c_flags);
18416dce513Schristos 
18516dce513Schristos   /* Set the machine type */
18616dce513Schristos   bfd_default_set_arch_mach (stdoutput, bfd_arch_m32c, m32c_mach);
18716dce513Schristos }
18816dce513Schristos 
18916dce513Schristos void
m32c_start_line_hook(void)19016dce513Schristos m32c_start_line_hook (void)
19116dce513Schristos {
19216dce513Schristos #if 0 /* not necessary....handled in the .cpu file */
19316dce513Schristos   char *s = input_line_pointer;
19416dce513Schristos   char *sg;
19516dce513Schristos 
19616dce513Schristos   for (s = input_line_pointer ; s && s[0] != '\n'; s++)
19716dce513Schristos     {
19816dce513Schristos       if (s[0] == ':')
19916dce513Schristos 	{
20016dce513Schristos 	  /* Remove :g suffix.  Squeeze out blanks.  */
20116dce513Schristos 	  if (s[1] == 'g')
20216dce513Schristos 	    {
20316dce513Schristos 	      for (sg = s - 1; sg && sg >= input_line_pointer; sg--)
20416dce513Schristos 		{
20516dce513Schristos 		  sg[2] = sg[0];
20616dce513Schristos 		}
20716dce513Schristos 	      sg[1] = ' ';
20816dce513Schristos 	      sg[2] = ' ';
20916dce513Schristos 	      input_line_pointer += 2;
21016dce513Schristos 	    }
21116dce513Schristos 	}
21216dce513Schristos     }
21316dce513Schristos #endif
21416dce513Schristos }
21516dce513Schristos 
21616dce513Schristos /* Process [[indirect-operands]] in instruction str.  */
21716dce513Schristos 
218*e992f068Schristos static bool
m32c_indirect_operand(char * str)21916dce513Schristos m32c_indirect_operand (char *str)
22016dce513Schristos {
22116dce513Schristos   char *new_str;
22216dce513Schristos   char *s;
22316dce513Schristos   char *ns;
22416dce513Schristos   int ns_len;
22516dce513Schristos   char *ns_end;
22616dce513Schristos   enum indirect_type {none, relative, absolute} ;
22716dce513Schristos   enum indirect_type indirection [3] = { none, none, none };
22816dce513Schristos   int brace_n [3] = { 0, 0, 0 };
22916dce513Schristos   int operand;
23016dce513Schristos 
23116dce513Schristos   s = str;
23216dce513Schristos   operand = 1;
23316dce513Schristos   for (s = str; *s; s++)
23416dce513Schristos     {
23516dce513Schristos       if (s[0] == ',')
23616dce513Schristos 	operand = 2;
23716dce513Schristos       /* [abs] where abs is not a0 or a1  */
23816dce513Schristos       if (s[1] == '[' && ! (s[2] == 'a' && (s[3] == '0' || s[3] == '1'))
23916dce513Schristos 	  && (ISBLANK (s[0]) || s[0] == ','))
24016dce513Schristos 	indirection[operand] = absolute;
24116dce513Schristos       if (s[0] == ']' && s[1] == ']')
24216dce513Schristos 	indirection[operand] = relative;
24316dce513Schristos       if (s[0] == '[' && s[1] == '[')
24416dce513Schristos 	indirection[operand] = relative;
24516dce513Schristos     }
24616dce513Schristos 
24716dce513Schristos   if (indirection[1] == none && indirection[2] == none)
248*e992f068Schristos     return false;
24916dce513Schristos 
25016dce513Schristos   operand = 1;
25116dce513Schristos   ns_len = strlen (str);
25216dce513Schristos   new_str = XNEWVEC (char, ns_len);
25316dce513Schristos   ns = new_str;
25416dce513Schristos   ns_end = ns + ns_len;
25516dce513Schristos 
25616dce513Schristos   for (s = str; *s; s++)
25716dce513Schristos     {
25816dce513Schristos       if (s[0] == ',')
25916dce513Schristos 	operand = 2;
26016dce513Schristos 
26116dce513Schristos       if (s[0] == '[' && ! brace_n[operand])
26216dce513Schristos 	{
26316dce513Schristos 	  brace_n[operand] += 1;
26416dce513Schristos 	  /* Squeeze [[ to [ if this is an indirect operand.  */
26516dce513Schristos 	  if (indirection[operand] != none)
26616dce513Schristos 	    continue;
26716dce513Schristos 	}
26816dce513Schristos 
26916dce513Schristos       else if (s[0] == '[' && brace_n[operand])
27016dce513Schristos 	{
27116dce513Schristos 	  brace_n[operand] += 1;
27216dce513Schristos 	}
27316dce513Schristos       else if (s[0] == ']' && s[1] == ']' && indirection[operand] == relative)
27416dce513Schristos 	{
27516dce513Schristos 	  s += 1;		/* skip one ].  */
27616dce513Schristos 	  brace_n[operand] -= 2; /* allow for 2 [.  */
27716dce513Schristos 	}
27816dce513Schristos       else if (s[0] == ']' && indirection[operand] == absolute)
27916dce513Schristos 	{
28016dce513Schristos 	  brace_n[operand] -= 1;
28116dce513Schristos 	  continue;		/* skip closing ].  */
28216dce513Schristos 	}
28316dce513Schristos       else if (s[0] == ']')
28416dce513Schristos 	{
28516dce513Schristos 	  brace_n[operand] -= 1;
28616dce513Schristos 	}
28716dce513Schristos       *ns = s[0];
28816dce513Schristos       ns += 1;
28916dce513Schristos       if (ns >= ns_end)
290*e992f068Schristos 	return false;
29116dce513Schristos       if (s[0] == 0)
29216dce513Schristos 	break;
29316dce513Schristos     }
29416dce513Schristos   *ns = '\0';
29516dce513Schristos   for (operand = 1; operand <= 2; operand++)
29616dce513Schristos     if (brace_n[operand])
29716dce513Schristos       {
29816dce513Schristos 	fprintf (stderr, "Unmatched [[operand-%d]] %d\n", operand, brace_n[operand]);
29916dce513Schristos       }
30016dce513Schristos 
30116dce513Schristos   if (indirection[1] != none && indirection[2] != none)
30216dce513Schristos     md_assemble ((char *) "src-dest-indirect");
30316dce513Schristos   else if (indirection[1] != none)
30416dce513Schristos     md_assemble ((char *) "src-indirect");
30516dce513Schristos   else if (indirection[2] != none)
30616dce513Schristos     md_assemble ((char *) "dest-indirect");
30716dce513Schristos 
30816dce513Schristos   md_assemble (new_str);
30916dce513Schristos   free (new_str);
310*e992f068Schristos   return true;
31116dce513Schristos }
31216dce513Schristos 
31316dce513Schristos void
md_assemble(char * str)31416dce513Schristos md_assemble (char * str)
31516dce513Schristos {
31616dce513Schristos   static int last_insn_had_delay_slot = 0;
31716dce513Schristos   m32c_insn insn;
31816dce513Schristos   char *    errmsg;
31916dce513Schristos   finished_insnS results;
32016dce513Schristos   int rl_type;
321012573ebSchristos   int insn_size;
32216dce513Schristos 
32316dce513Schristos   if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str))
32416dce513Schristos     return;
32516dce513Schristos 
32616dce513Schristos   /* Initialize GAS's cgen interface for a new instruction.  */
32716dce513Schristos   gas_cgen_init_parse ();
32816dce513Schristos 
32916dce513Schristos   insn.insn = m32c_cgen_assemble_insn
33016dce513Schristos     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
33116dce513Schristos 
33216dce513Schristos   if (!insn.insn)
33316dce513Schristos     {
33416dce513Schristos       as_bad ("%s", errmsg);
33516dce513Schristos       return;
33616dce513Schristos     }
33716dce513Schristos 
33816dce513Schristos   results.num_fixups = 0;
33916dce513Schristos   /* Doesn't really matter what we pass for RELAX_P here.  */
34016dce513Schristos   gas_cgen_finish_insn (insn.insn, insn.buffer,
34116dce513Schristos 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, &results);
34216dce513Schristos 
34316dce513Schristos   last_insn_had_delay_slot
34416dce513Schristos     = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
34516dce513Schristos   (void) last_insn_had_delay_slot;
34616dce513Schristos   insn_size = CGEN_INSN_BITSIZE(insn.insn);
34716dce513Schristos 
34816dce513Schristos   rl_type = rl_for (insn);
34916dce513Schristos 
35016dce513Schristos   /* We have to mark all the jumps, because we need to adjust them
35116dce513Schristos      when we delete bytes, but we only need to mark the displacements
35216dce513Schristos      if they're symbolic - if they're not, we've already picked the
35316dce513Schristos      shortest opcode by now.  The linker, however, will still have to
35416dce513Schristos      check any operands to see if they're the displacement type, since
35516dce513Schristos      we don't know (nor record) *which* operands are relaxable.  */
35616dce513Schristos   if (m32c_relax
35716dce513Schristos       && rl_type != RL_TYPE_NONE
35816dce513Schristos       && (rl_type == RL_TYPE_JUMP || results.num_fixups)
35916dce513Schristos       && !relaxable (insn))
36016dce513Schristos     {
36116dce513Schristos       int reloc = 0;
36216dce513Schristos       int addend = results.num_fixups + 16 * insn_size/8;
36316dce513Schristos 
36416dce513Schristos       switch (rl_for (insn))
36516dce513Schristos 	{
36616dce513Schristos 	case RL_TYPE_JUMP:  reloc = BFD_RELOC_M32C_RL_JUMP;  break;
36716dce513Schristos 	case RL_TYPE_1ADDR: reloc = BFD_RELOC_M32C_RL_1ADDR; break;
36816dce513Schristos 	case RL_TYPE_2ADDR: reloc = BFD_RELOC_M32C_RL_2ADDR; break;
36916dce513Schristos 	}
37016dce513Schristos       if (insn.insn->base->num == M32C_INSN_JMP16_S
37116dce513Schristos 	  || insn.insn->base->num == M32C_INSN_JMP32_S)
37216dce513Schristos 	addend = 0x10;
37316dce513Schristos 
37416dce513Schristos       fix_new (results.frag,
37516dce513Schristos 	       results.addr - results.frag->fr_literal,
37616dce513Schristos 	       0, abs_section_sym, addend, 0,
37716dce513Schristos 	       reloc);
37816dce513Schristos     }
37916dce513Schristos }
38016dce513Schristos 
38116dce513Schristos /* The syntax in the manual says constants begin with '#'.
38216dce513Schristos    We just ignore it.  */
38316dce513Schristos 
38416dce513Schristos void
md_operand(expressionS * exp)38516dce513Schristos md_operand (expressionS * exp)
38616dce513Schristos {
38716dce513Schristos   /* In case of a syntax error, escape back to try next syntax combo. */
38816dce513Schristos   if (exp->X_op == O_absent)
38916dce513Schristos     gas_cgen_md_operand (exp);
39016dce513Schristos }
39116dce513Schristos 
39216dce513Schristos valueT
md_section_align(segT segment,valueT size)39316dce513Schristos md_section_align (segT segment, valueT size)
39416dce513Schristos {
395012573ebSchristos   int align = bfd_section_alignment (segment);
39616dce513Schristos   return ((size + (1 << align) - 1) & -(1 << align));
39716dce513Schristos }
39816dce513Schristos 
39916dce513Schristos symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)40016dce513Schristos md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
40116dce513Schristos {
40216dce513Schristos   return 0;
40316dce513Schristos }
40416dce513Schristos 
40516dce513Schristos const relax_typeS md_relax_table[] =
40616dce513Schristos {
40716dce513Schristos   /* The fields are:
40816dce513Schristos      1) most positive reach of this state,
40916dce513Schristos      2) most negative reach of this state,
41016dce513Schristos      3) how many bytes this mode will have in the variable part of the frag
41116dce513Schristos      4) which index into the table to try if we can't fit into this one.  */
41216dce513Schristos 
41316dce513Schristos   /* 0 */ {     0,      0, 0,  0 }, /* unused */
41416dce513Schristos   /* 1 */ {     0,      0, 0,  0 }, /* marker for "don't know yet" */
41516dce513Schristos 
41616dce513Schristos   /* 2 */ {   127,   -128, 2,  3 }, /* jcnd16_5.b */
41716dce513Schristos   /* 3 */ { 32767, -32768, 5,  4 }, /* jcnd16_5.w */
41816dce513Schristos   /* 4 */ {     0,      0, 6,  0 }, /* jcnd16_5.a */
41916dce513Schristos 
42016dce513Schristos   /* 5 */ {   127,   -128, 2,  6 }, /* jcnd16.b */
42116dce513Schristos   /* 6 */ { 32767, -32768, 5,  7 }, /* jcnd16.w */
42216dce513Schristos   /* 7 */ {     0,      0, 6,  0 }, /* jcnd16.a */
42316dce513Schristos 
42416dce513Schristos   /* 8 */ {     8,      1, 1,  9 }, /* jmp16.s */
42516dce513Schristos   /* 9 */ {   127,   -128, 2, 10 }, /* jmp16.b */
42616dce513Schristos  /* 10 */ { 32767, -32768, 3, 11 }, /* jmp16.w */
42716dce513Schristos  /* 11 */ {     0,      0, 4,  0 }, /* jmp16.a */
42816dce513Schristos 
42916dce513Schristos  /* 12 */ {   127,   -128, 2, 13 }, /* jcnd32.b */
43016dce513Schristos  /* 13 */ { 32767, -32768, 5, 14 }, /* jcnd32.w */
43116dce513Schristos  /* 14 */ {     0,      0, 6,  0 }, /* jcnd32.a */
43216dce513Schristos 
43316dce513Schristos  /* 15 */ {     8,      1, 1, 16 }, /* jmp32.s */
43416dce513Schristos  /* 16 */ {   127,   -128, 2, 17 }, /* jmp32.b */
43516dce513Schristos  /* 17 */ { 32767, -32768, 3, 18 }, /* jmp32.w */
43616dce513Schristos  /* 18 */ {     0,      0, 4,  0 }, /* jmp32.a */
43716dce513Schristos 
43816dce513Schristos  /* 19 */ { 32767, -32768, 3, 20 }, /* jsr16.w */
43916dce513Schristos  /* 20 */ {     0,      0, 4,  0 }, /* jsr16.a */
44016dce513Schristos  /* 21 */ { 32767, -32768, 3, 11 }, /* jsr32.w */
44116dce513Schristos  /* 22 */ {     0,      0, 4,  0 }, /* jsr32.a */
44216dce513Schristos 
44316dce513Schristos  /* 23 */ {     0,      0, 3,  0 }, /* adjnz pc8 */
44416dce513Schristos  /* 24 */ {     0,      0, 4,  0 }, /* adjnz disp8 pc8 */
44516dce513Schristos  /* 25 */ {     0,      0, 5,  0 }, /* adjnz disp16 pc8 */
44616dce513Schristos  /* 26 */ {     0,      0, 6,  0 }  /* adjnz disp24 pc8 */
44716dce513Schristos };
44816dce513Schristos 
44916dce513Schristos enum {
45016dce513Schristos   M32C_MACRO_JCND16_5_W,
45116dce513Schristos   M32C_MACRO_JCND16_5_A,
45216dce513Schristos   M32C_MACRO_JCND16_W,
45316dce513Schristos   M32C_MACRO_JCND16_A,
45416dce513Schristos   M32C_MACRO_JCND32_W,
45516dce513Schristos   M32C_MACRO_JCND32_A,
45616dce513Schristos   /* the digit is the array index of the pcrel byte */
45716dce513Schristos   M32C_MACRO_ADJNZ_2,
45816dce513Schristos   M32C_MACRO_ADJNZ_3,
45916dce513Schristos   M32C_MACRO_ADJNZ_4,
46016dce513Schristos   M32C_MACRO_ADJNZ_5,
46116dce513Schristos };
46216dce513Schristos 
46316dce513Schristos static struct {
46416dce513Schristos   int insn;
46516dce513Schristos   int bytes;
46616dce513Schristos   int insn_for_extern;
46716dce513Schristos   int pcrel_aim_offset;
46816dce513Schristos } subtype_mappings[] = {
46916dce513Schristos   /* 0 */ { 0, 0, 0, 0 },
47016dce513Schristos   /* 1 */ { 0, 0, 0, 0 },
47116dce513Schristos 
47216dce513Schristos   /* 2 */ {  M32C_INSN_JCND16_5,    2, -M32C_MACRO_JCND16_5_A, 1 },
47316dce513Schristos   /* 3 */ { -M32C_MACRO_JCND16_5_W, 5, -M32C_MACRO_JCND16_5_A, 4 },
47416dce513Schristos   /* 4 */ { -M32C_MACRO_JCND16_5_A, 6, -M32C_MACRO_JCND16_5_A, 0 },
47516dce513Schristos 
47616dce513Schristos   /* 5 */ {  M32C_INSN_JCND16,      3, -M32C_MACRO_JCND16_A,   1 },
47716dce513Schristos   /* 6 */ { -M32C_MACRO_JCND16_W,   6, -M32C_MACRO_JCND16_A,   4 },
47816dce513Schristos   /* 7 */ { -M32C_MACRO_JCND16_A,   7, -M32C_MACRO_JCND16_A,   0 },
47916dce513Schristos 
48016dce513Schristos   /* 8 */ {  M32C_INSN_JMP16_S,     1, M32C_INSN_JMP16_A,     0 },
48116dce513Schristos   /* 9 */ {  M32C_INSN_JMP16_B,     2, M32C_INSN_JMP16_A,     1 },
48216dce513Schristos  /* 10 */ {  M32C_INSN_JMP16_W,     3, M32C_INSN_JMP16_A,     2 },
48316dce513Schristos  /* 11 */ {  M32C_INSN_JMP16_A,     4, M32C_INSN_JMP16_A,     0 },
48416dce513Schristos 
48516dce513Schristos  /* 12 */ {  M32C_INSN_JCND32,      2, -M32C_MACRO_JCND32_A,   1 },
48616dce513Schristos  /* 13 */ { -M32C_MACRO_JCND32_W,   5, -M32C_MACRO_JCND32_A,   4 },
48716dce513Schristos  /* 14 */ { -M32C_MACRO_JCND32_A,   6, -M32C_MACRO_JCND32_A,   0 },
48816dce513Schristos 
48916dce513Schristos  /* 15 */ {  M32C_INSN_JMP32_S,     1, M32C_INSN_JMP32_A,     0 },
49016dce513Schristos  /* 16 */ {  M32C_INSN_JMP32_B,     2, M32C_INSN_JMP32_A,     1 },
49116dce513Schristos  /* 17 */ {  M32C_INSN_JMP32_W,     3, M32C_INSN_JMP32_A,     2 },
49216dce513Schristos  /* 18 */ {  M32C_INSN_JMP32_A,     4, M32C_INSN_JMP32_A,     0 },
49316dce513Schristos 
49416dce513Schristos  /* 19 */ {  M32C_INSN_JSR16_W,     3, M32C_INSN_JSR16_A,     2 },
49516dce513Schristos  /* 20 */ {  M32C_INSN_JSR16_A,     4, M32C_INSN_JSR16_A,     0 },
49616dce513Schristos  /* 21 */ {  M32C_INSN_JSR32_W,     3, M32C_INSN_JSR32_A,     2 },
49716dce513Schristos  /* 22 */ {  M32C_INSN_JSR32_A,     4, M32C_INSN_JSR32_A,     0 },
49816dce513Schristos 
49916dce513Schristos  /* 23 */ { -M32C_MACRO_ADJNZ_2,    3, -M32C_MACRO_ADJNZ_2,    0 },
50016dce513Schristos  /* 24 */ { -M32C_MACRO_ADJNZ_3,    4, -M32C_MACRO_ADJNZ_3,    0 },
50116dce513Schristos  /* 25 */ { -M32C_MACRO_ADJNZ_4,    5, -M32C_MACRO_ADJNZ_4,    0 },
50216dce513Schristos  /* 26 */ { -M32C_MACRO_ADJNZ_5,    6, -M32C_MACRO_ADJNZ_5,    0 }
50316dce513Schristos };
50416dce513Schristos #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
50516dce513Schristos 
50616dce513Schristos void
m32c_prepare_relax_scan(fragS * fragP,offsetT * aim,relax_substateT this_state)50716dce513Schristos m32c_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
50816dce513Schristos {
50916dce513Schristos   symbolS *symbolP = fragP->fr_symbol;
51016dce513Schristos   if (symbolP && !S_IS_DEFINED (symbolP))
51116dce513Schristos     *aim = 0;
51216dce513Schristos   /* Adjust for m32c pcrel not being relative to the next opcode.  */
51316dce513Schristos   *aim += subtype_mappings[this_state].pcrel_aim_offset;
51416dce513Schristos }
51516dce513Schristos 
51616dce513Schristos static int
insn_to_subtype(int inum,const CGEN_INSN * insn)51716dce513Schristos insn_to_subtype (int inum, const CGEN_INSN *insn)
51816dce513Schristos {
51916dce513Schristos   unsigned int i;
52016dce513Schristos 
52116dce513Schristos   if (insn
522*e992f068Schristos       && (startswith (insn->base->mnemonic, "adjnz")
523*e992f068Schristos 	  || startswith (insn->base->mnemonic, "sbjnz")))
52416dce513Schristos     {
52516dce513Schristos       i = 23 + insn->base->bitsize/8 - 3;
52616dce513Schristos       /*printf("mapping %d used for %s\n", i, insn->base->mnemonic);*/
52716dce513Schristos       return i;
52816dce513Schristos     }
52916dce513Schristos 
53016dce513Schristos   for (i=0; i<NUM_MAPPINGS; i++)
53116dce513Schristos     if (inum == subtype_mappings[i].insn)
53216dce513Schristos       {
53316dce513Schristos 	/*printf("mapping %d used\n", i);*/
53416dce513Schristos 	return i;
53516dce513Schristos       }
53616dce513Schristos   abort ();
53716dce513Schristos }
53816dce513Schristos 
53916dce513Schristos /* Return an initial guess of the length by which a fragment must grow to
54016dce513Schristos    hold a branch to reach its destination.
54116dce513Schristos    Also updates fr_type/fr_subtype as necessary.
54216dce513Schristos 
54316dce513Schristos    Called just before doing relaxation.
54416dce513Schristos    Any symbol that is now undefined will not become defined.
54516dce513Schristos    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
54616dce513Schristos    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
54716dce513Schristos    Although it may not be explicit in the frag, pretend fr_var starts with a
54816dce513Schristos    0 value.  */
54916dce513Schristos 
55016dce513Schristos int
md_estimate_size_before_relax(fragS * fragP,segT segment ATTRIBUTE_UNUSED)55116dce513Schristos md_estimate_size_before_relax (fragS * fragP, segT segment ATTRIBUTE_UNUSED)
55216dce513Schristos {
55316dce513Schristos   int where = fragP->fr_opcode - fragP->fr_literal;
55416dce513Schristos 
55516dce513Schristos   if (fragP->fr_subtype == 1)
55616dce513Schristos     fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num, fragP->fr_cgen.insn);
55716dce513Schristos 
55816dce513Schristos   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
55916dce513Schristos     {
56016dce513Schristos       int new_insn;
56116dce513Schristos 
56216dce513Schristos       new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
56316dce513Schristos       fragP->fr_subtype = insn_to_subtype (new_insn, 0);
56416dce513Schristos     }
56516dce513Schristos 
56616dce513Schristos   if (fragP->fr_cgen.insn->base
56716dce513Schristos       && fragP->fr_cgen.insn->base->num
56816dce513Schristos          != subtype_mappings[fragP->fr_subtype].insn
56916dce513Schristos       && subtype_mappings[fragP->fr_subtype].insn > 0)
57016dce513Schristos     {
57116dce513Schristos       int new_insn= subtype_mappings[fragP->fr_subtype].insn;
57216dce513Schristos       if (new_insn >= 0)
57316dce513Schristos 	{
57416dce513Schristos 	  fragP->fr_cgen.insn = (fragP->fr_cgen.insn
57516dce513Schristos 				 - fragP->fr_cgen.insn->base->num
57616dce513Schristos 				 + new_insn);
57716dce513Schristos 	}
57816dce513Schristos     }
57916dce513Schristos 
58016dce513Schristos   return subtype_mappings[fragP->fr_subtype].bytes - (fragP->fr_fix - where);
58116dce513Schristos }
58216dce513Schristos 
58316dce513Schristos /* *fragP has been relaxed to its final size, and now needs to have
58416dce513Schristos    the bytes inside it modified to conform to the new size.
58516dce513Schristos 
58616dce513Schristos    Called after relaxation is finished.
58716dce513Schristos    fragP->fr_type == rs_machine_dependent.
58816dce513Schristos    fragP->fr_subtype is the subtype of what the address relaxed to.  */
58916dce513Schristos 
59016dce513Schristos static int
target_address_for(fragS * frag)59116dce513Schristos target_address_for (fragS *frag)
59216dce513Schristos {
59316dce513Schristos   int rv = frag->fr_offset;
59416dce513Schristos   symbolS *sym = frag->fr_symbol;
59516dce513Schristos 
59616dce513Schristos   if (sym)
59716dce513Schristos     rv += S_GET_VALUE (sym);
59816dce513Schristos 
59916dce513Schristos   /*printf("target_address_for returns %d\n", rv);*/
60016dce513Schristos   return rv;
60116dce513Schristos }
60216dce513Schristos 
60316dce513Schristos void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)60416dce513Schristos md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
60516dce513Schristos 		 segT    sec ATTRIBUTE_UNUSED,
60616dce513Schristos 		 fragS * fragP ATTRIBUTE_UNUSED)
60716dce513Schristos {
60816dce513Schristos   int addend;
60916dce513Schristos   int operand;
61016dce513Schristos   int where = fragP->fr_opcode - fragP->fr_literal;
61116dce513Schristos   int rl_where = fragP->fr_opcode - fragP->fr_literal;
61216dce513Schristos   unsigned char *op = (unsigned char *)fragP->fr_opcode;
61316dce513Schristos   int rl_addend = 0;
61416dce513Schristos 
61516dce513Schristos   addend = target_address_for (fragP) - (fragP->fr_address + where);
61616dce513Schristos 
61716dce513Schristos   fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes;
61816dce513Schristos 
61916dce513Schristos   switch (subtype_mappings[fragP->fr_subtype].insn)
62016dce513Schristos     {
62116dce513Schristos     case M32C_INSN_JCND16_5:
62216dce513Schristos       op[1] = addend - 1;
62316dce513Schristos       operand = M32C_OPERAND_LAB_8_8;
62416dce513Schristos       rl_addend = 0x21;
62516dce513Schristos       break;
62616dce513Schristos 
62716dce513Schristos     case -M32C_MACRO_JCND16_5_W:
62816dce513Schristos       op[0] ^= 0x04;
62916dce513Schristos       op[1] = 4;
63016dce513Schristos       op[2] = 0xf4;
63116dce513Schristos       op[3] = addend - 3;
63216dce513Schristos       op[4] = (addend - 3) >> 8;
63316dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
63416dce513Schristos       where += 2;
63516dce513Schristos       rl_addend = 0x51;
63616dce513Schristos       break;
63716dce513Schristos 
63816dce513Schristos     case -M32C_MACRO_JCND16_5_A:
63916dce513Schristos       op[0] ^= 0x04;
64016dce513Schristos       op[1] = 5;
64116dce513Schristos       op[2] = 0xfc;
64216dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
64316dce513Schristos       where += 2;
64416dce513Schristos       rl_addend = 0x61;
64516dce513Schristos       break;
64616dce513Schristos 
64716dce513Schristos 
64816dce513Schristos     case M32C_INSN_JCND16:
64916dce513Schristos       op[2] = addend - 2;
65016dce513Schristos       operand = M32C_OPERAND_LAB_16_8;
65116dce513Schristos       rl_addend = 0x31;
65216dce513Schristos       break;
65316dce513Schristos 
65416dce513Schristos     case -M32C_MACRO_JCND16_W:
65516dce513Schristos       op[1] ^= 0x04;
65616dce513Schristos       op[2] = 4;
65716dce513Schristos       op[3] = 0xf4;
65816dce513Schristos       op[4] = addend - 4;
65916dce513Schristos       op[5] = (addend - 4) >> 8;
66016dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
66116dce513Schristos       where += 3;
66216dce513Schristos       rl_addend = 0x61;
66316dce513Schristos       break;
66416dce513Schristos 
66516dce513Schristos     case -M32C_MACRO_JCND16_A:
66616dce513Schristos       op[1] ^= 0x04;
66716dce513Schristos       op[2] = 5;
66816dce513Schristos       op[3] = 0xfc;
66916dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
67016dce513Schristos       where += 3;
67116dce513Schristos       rl_addend = 0x71;
67216dce513Schristos       break;
67316dce513Schristos 
67416dce513Schristos     case M32C_INSN_JMP16_S:
67516dce513Schristos       op[0] = 0x60 | ((addend-2) & 0x07);
67616dce513Schristos       operand = M32C_OPERAND_LAB_5_3;
67716dce513Schristos       rl_addend = 0x10;
67816dce513Schristos       break;
67916dce513Schristos 
68016dce513Schristos     case M32C_INSN_JMP16_B:
68116dce513Schristos       op[0] = 0xfe;
68216dce513Schristos       op[1] = addend - 1;
68316dce513Schristos       operand = M32C_OPERAND_LAB_8_8;
68416dce513Schristos       rl_addend = 0x21;
68516dce513Schristos       break;
68616dce513Schristos 
68716dce513Schristos     case M32C_INSN_JMP16_W:
68816dce513Schristos       op[0] = 0xf4;
68916dce513Schristos       op[1] = addend - 1;
69016dce513Schristos       op[2] = (addend - 1) >> 8;
69116dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
69216dce513Schristos       rl_addend = 0x31;
69316dce513Schristos       break;
69416dce513Schristos 
69516dce513Schristos     case M32C_INSN_JMP16_A:
69616dce513Schristos       op[0] = 0xfc;
69716dce513Schristos       op[1] = 0;
69816dce513Schristos       op[2] = 0;
69916dce513Schristos       op[3] = 0;
70016dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
70116dce513Schristos       rl_addend = 0x41;
70216dce513Schristos       break;
70316dce513Schristos 
70416dce513Schristos     case M32C_INSN_JCND32:
70516dce513Schristos       op[1] = addend - 1;
70616dce513Schristos       operand = M32C_OPERAND_LAB_8_8;
70716dce513Schristos       rl_addend = 0x21;
70816dce513Schristos       break;
70916dce513Schristos 
71016dce513Schristos     case -M32C_MACRO_JCND32_W:
71116dce513Schristos       op[0] ^= 0x40;
71216dce513Schristos       op[1] = 4;
71316dce513Schristos       op[2] = 0xce;
71416dce513Schristos       op[3] = addend - 3;
71516dce513Schristos       op[4] = (addend - 3) >> 8;
71616dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
71716dce513Schristos       where += 2;
71816dce513Schristos       rl_addend = 0x51;
71916dce513Schristos       break;
72016dce513Schristos 
72116dce513Schristos     case -M32C_MACRO_JCND32_A:
72216dce513Schristos       op[0] ^= 0x40;
72316dce513Schristos       op[1] = 5;
72416dce513Schristos       op[2] = 0xcc;
72516dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
72616dce513Schristos       where += 2;
72716dce513Schristos       rl_addend = 0x61;
72816dce513Schristos       break;
72916dce513Schristos 
73016dce513Schristos     case M32C_INSN_JMP32_S:
73116dce513Schristos       addend = ((addend-2) & 0x07);
73216dce513Schristos       op[0] = 0x4a | (addend & 0x01) | ((addend << 3) & 0x30);
73316dce513Schristos       operand = M32C_OPERAND_LAB32_JMP_S;
73416dce513Schristos       rl_addend = 0x10;
73516dce513Schristos       break;
73616dce513Schristos 
73716dce513Schristos     case M32C_INSN_JMP32_B:
73816dce513Schristos       op[0] = 0xbb;
73916dce513Schristos       op[1] = addend - 1;
74016dce513Schristos       operand = M32C_OPERAND_LAB_8_8;
74116dce513Schristos       rl_addend = 0x21;
74216dce513Schristos       break;
74316dce513Schristos 
74416dce513Schristos     case M32C_INSN_JMP32_W:
74516dce513Schristos       op[0] = 0xce;
74616dce513Schristos       op[1] = addend - 1;
74716dce513Schristos       op[2] = (addend - 1) >> 8;
74816dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
74916dce513Schristos       rl_addend = 0x31;
75016dce513Schristos       break;
75116dce513Schristos 
75216dce513Schristos     case M32C_INSN_JMP32_A:
75316dce513Schristos       op[0] = 0xcc;
75416dce513Schristos       op[1] = 0;
75516dce513Schristos       op[2] = 0;
75616dce513Schristos       op[3] = 0;
75716dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
75816dce513Schristos       rl_addend = 0x41;
75916dce513Schristos       break;
76016dce513Schristos 
76116dce513Schristos 
76216dce513Schristos     case M32C_INSN_JSR16_W:
76316dce513Schristos       op[0] = 0xf5;
76416dce513Schristos       op[1] = addend - 1;
76516dce513Schristos       op[2] = (addend - 1) >> 8;
76616dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
76716dce513Schristos       rl_addend = 0x31;
76816dce513Schristos       break;
76916dce513Schristos 
77016dce513Schristos     case M32C_INSN_JSR16_A:
77116dce513Schristos       op[0] = 0xfd;
77216dce513Schristos       op[1] = 0;
77316dce513Schristos       op[2] = 0;
77416dce513Schristos       op[3] = 0;
77516dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
77616dce513Schristos       rl_addend = 0x41;
77716dce513Schristos       break;
77816dce513Schristos 
77916dce513Schristos     case M32C_INSN_JSR32_W:
78016dce513Schristos       op[0] = 0xcf;
78116dce513Schristos       op[1] = addend - 1;
78216dce513Schristos       op[2] = (addend - 1) >> 8;
78316dce513Schristos       operand = M32C_OPERAND_LAB_8_16;
78416dce513Schristos       rl_addend = 0x31;
78516dce513Schristos       break;
78616dce513Schristos 
78716dce513Schristos     case M32C_INSN_JSR32_A:
78816dce513Schristos       op[0] = 0xcd;
78916dce513Schristos       op[1] = 0;
79016dce513Schristos       op[2] = 0;
79116dce513Schristos       op[3] = 0;
79216dce513Schristos       operand = M32C_OPERAND_LAB_8_24;
79316dce513Schristos       rl_addend = 0x41;
79416dce513Schristos       break;
79516dce513Schristos 
79616dce513Schristos     case -M32C_MACRO_ADJNZ_2:
79716dce513Schristos       rl_addend = 0x31;
79816dce513Schristos       op[2] = addend - 2;
79916dce513Schristos       operand = M32C_OPERAND_LAB_16_8;
80016dce513Schristos       break;
80116dce513Schristos     case -M32C_MACRO_ADJNZ_3:
80216dce513Schristos       rl_addend = 0x41;
80316dce513Schristos       op[3] = addend - 2;
80416dce513Schristos       operand = M32C_OPERAND_LAB_24_8;
80516dce513Schristos       break;
80616dce513Schristos     case -M32C_MACRO_ADJNZ_4:
80716dce513Schristos       rl_addend = 0x51;
80816dce513Schristos       op[4] = addend - 2;
80916dce513Schristos       operand = M32C_OPERAND_LAB_32_8;
81016dce513Schristos       break;
81116dce513Schristos     case -M32C_MACRO_ADJNZ_5:
81216dce513Schristos       rl_addend = 0x61;
81316dce513Schristos       op[5] = addend - 2;
81416dce513Schristos       operand = M32C_OPERAND_LAB_40_8;
81516dce513Schristos       break;
81616dce513Schristos 
81716dce513Schristos     default:
81816dce513Schristos       printf("\nHey!  Need more opcode converters! missing: %d %s\n\n",
81916dce513Schristos 	     fragP->fr_subtype,
82016dce513Schristos 	     fragP->fr_cgen.insn->base->name);
82116dce513Schristos       abort();
82216dce513Schristos     }
82316dce513Schristos 
82416dce513Schristos   if (m32c_relax)
82516dce513Schristos     {
82616dce513Schristos       if (operand != M32C_OPERAND_LAB_8_24)
82716dce513Schristos 	fragP->fr_offset = (fragP->fr_address + where);
82816dce513Schristos 
82916dce513Schristos       fix_new (fragP,
83016dce513Schristos 	       rl_where,
83116dce513Schristos 	       0, abs_section_sym, rl_addend, 0,
83216dce513Schristos 	       BFD_RELOC_M32C_RL_JUMP);
83316dce513Schristos     }
83416dce513Schristos 
83516dce513Schristos   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
83616dce513Schristos       || operand == M32C_OPERAND_LAB_8_24
83716dce513Schristos       || (m32c_relax && (operand != M32C_OPERAND_LAB_5_3
83816dce513Schristos 			 && operand != M32C_OPERAND_LAB32_JMP_S)))
83916dce513Schristos     {
84016dce513Schristos       gas_assert (fragP->fr_cgen.insn != 0);
84116dce513Schristos       gas_cgen_record_fixup (fragP,
84216dce513Schristos 			     where,
84316dce513Schristos 			     fragP->fr_cgen.insn,
84416dce513Schristos 			     (fragP->fr_fix - where) * 8,
84516dce513Schristos 			     cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
84616dce513Schristos 							 operand),
84716dce513Schristos 			     fragP->fr_cgen.opinfo,
84816dce513Schristos 			     fragP->fr_symbol,
84916dce513Schristos 			     fragP->fr_offset);
85016dce513Schristos     }
85116dce513Schristos }
85216dce513Schristos 
85316dce513Schristos /* Functions concerning relocs.  */
85416dce513Schristos 
85516dce513Schristos /* The location from which a PC relative jump should be calculated,
85616dce513Schristos    given a PC relative reloc.  */
85716dce513Schristos 
85816dce513Schristos long
md_pcrel_from_section(fixS * fixP,segT sec)85916dce513Schristos md_pcrel_from_section (fixS * fixP, segT sec)
86016dce513Schristos {
86116dce513Schristos   if (fixP->fx_addsy != (symbolS *) NULL
86216dce513Schristos       && (! S_IS_DEFINED (fixP->fx_addsy)
86316dce513Schristos 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
86416dce513Schristos     /* The symbol is undefined (or is defined but not in this section).
86516dce513Schristos        Let the linker figure it out.  */
86616dce513Schristos     return 0;
86716dce513Schristos 
86816dce513Schristos   return (fixP->fx_frag->fr_address + fixP->fx_where);
86916dce513Schristos }
87016dce513Schristos 
87116dce513Schristos /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
87216dce513Schristos    Returns BFD_RELOC_NONE if no reloc type can be found.
87316dce513Schristos    *FIXP may be modified if desired.  */
87416dce513Schristos 
87516dce513Schristos bfd_reloc_code_real_type
md_cgen_lookup_reloc(const CGEN_INSN * insn ATTRIBUTE_UNUSED,const CGEN_OPERAND * operand,fixS * fixP ATTRIBUTE_UNUSED)87616dce513Schristos md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
87716dce513Schristos 		      const CGEN_OPERAND * operand,
87816dce513Schristos 		      fixS *               fixP ATTRIBUTE_UNUSED)
87916dce513Schristos {
88016dce513Schristos   static const struct op_reloc {
88116dce513Schristos     /* A CGEN operand type that can be a relocatable expression.  */
88216dce513Schristos     CGEN_OPERAND_TYPE operand;
88316dce513Schristos 
88416dce513Schristos     /* The appropriate BFD reloc type to use for that.  */
88516dce513Schristos     bfd_reloc_code_real_type reloc;
88616dce513Schristos 
88716dce513Schristos     /* The offset from the start of the instruction to the field to be
88816dce513Schristos        relocated, in bytes.  */
88916dce513Schristos     int offset;
89016dce513Schristos   } op_reloc_table[] = {
89116dce513Schristos 
89216dce513Schristos     /* PC-REL relocs for 8-bit fields.  */
89316dce513Schristos     { M32C_OPERAND_LAB_8_8,    BFD_RELOC_8_PCREL, 1 },
89416dce513Schristos     { M32C_OPERAND_LAB_16_8,   BFD_RELOC_8_PCREL, 2 },
89516dce513Schristos     { M32C_OPERAND_LAB_24_8,   BFD_RELOC_8_PCREL, 3 },
89616dce513Schristos     { M32C_OPERAND_LAB_32_8,   BFD_RELOC_8_PCREL, 4 },
89716dce513Schristos     { M32C_OPERAND_LAB_40_8,   BFD_RELOC_8_PCREL, 5 },
89816dce513Schristos 
89916dce513Schristos     /* PC-REL relocs for 16-bit fields.  */
90016dce513Schristos     { M32C_OPERAND_LAB_8_16,   BFD_RELOC_16_PCREL, 1 },
90116dce513Schristos 
90216dce513Schristos     /* Absolute relocs for 8-bit fields.  */
90316dce513Schristos     { M32C_OPERAND_IMM_8_QI,   BFD_RELOC_8, 1 },
90416dce513Schristos     { M32C_OPERAND_IMM_16_QI,  BFD_RELOC_8, 2 },
90516dce513Schristos     { M32C_OPERAND_IMM_24_QI,  BFD_RELOC_8, 3 },
90616dce513Schristos     { M32C_OPERAND_IMM_32_QI,  BFD_RELOC_8, 4 },
90716dce513Schristos     { M32C_OPERAND_IMM_40_QI,  BFD_RELOC_8, 5 },
90816dce513Schristos     { M32C_OPERAND_IMM_48_QI,  BFD_RELOC_8, 6 },
90916dce513Schristos     { M32C_OPERAND_IMM_56_QI,  BFD_RELOC_8, 7 },
91016dce513Schristos     { M32C_OPERAND_DSP_8_S8,   BFD_RELOC_8, 1 },
91116dce513Schristos     { M32C_OPERAND_DSP_16_S8,  BFD_RELOC_8, 2 },
91216dce513Schristos     { M32C_OPERAND_DSP_24_S8,  BFD_RELOC_8, 3 },
91316dce513Schristos     { M32C_OPERAND_DSP_32_S8,  BFD_RELOC_8, 4 },
91416dce513Schristos     { M32C_OPERAND_DSP_40_S8,  BFD_RELOC_8, 5 },
91516dce513Schristos     { M32C_OPERAND_DSP_48_S8,  BFD_RELOC_8, 6 },
91616dce513Schristos     { M32C_OPERAND_DSP_8_U8,   BFD_RELOC_8, 1 },
91716dce513Schristos     { M32C_OPERAND_DSP_16_U8,  BFD_RELOC_8, 2 },
91816dce513Schristos     { M32C_OPERAND_DSP_24_U8,  BFD_RELOC_8, 3 },
91916dce513Schristos     { M32C_OPERAND_DSP_32_U8,  BFD_RELOC_8, 4 },
92016dce513Schristos     { M32C_OPERAND_DSP_40_U8,  BFD_RELOC_8, 5 },
92116dce513Schristos     { M32C_OPERAND_DSP_48_U8,  BFD_RELOC_8, 6 },
92216dce513Schristos     { M32C_OPERAND_BITBASE32_16_S11_UNPREFIXED, BFD_RELOC_8, 2 },
92316dce513Schristos     { M32C_OPERAND_BITBASE32_16_U11_UNPREFIXED, BFD_RELOC_8, 2 },
92416dce513Schristos     { M32C_OPERAND_BITBASE32_24_S11_PREFIXED, BFD_RELOC_8, 3 },
92516dce513Schristos     { M32C_OPERAND_BITBASE32_24_U11_PREFIXED, BFD_RELOC_8, 3 },
92616dce513Schristos 
92716dce513Schristos     /* Absolute relocs for 16-bit fields.  */
92816dce513Schristos     { M32C_OPERAND_IMM_8_HI,   BFD_RELOC_16, 1 },
92916dce513Schristos     { M32C_OPERAND_IMM_16_HI,  BFD_RELOC_16, 2 },
93016dce513Schristos     { M32C_OPERAND_IMM_24_HI,  BFD_RELOC_16, 3 },
93116dce513Schristos     { M32C_OPERAND_IMM_32_HI,  BFD_RELOC_16, 4 },
93216dce513Schristos     { M32C_OPERAND_IMM_40_HI,  BFD_RELOC_16, 5 },
93316dce513Schristos     { M32C_OPERAND_IMM_48_HI,  BFD_RELOC_16, 6 },
93416dce513Schristos     { M32C_OPERAND_IMM_56_HI,  BFD_RELOC_16, 7 },
93516dce513Schristos     { M32C_OPERAND_IMM_64_HI,  BFD_RELOC_16, 8 },
93616dce513Schristos     { M32C_OPERAND_DSP_16_S16, BFD_RELOC_16, 2 },
93716dce513Schristos     { M32C_OPERAND_DSP_24_S16, BFD_RELOC_16, 3 },
93816dce513Schristos     { M32C_OPERAND_DSP_32_S16, BFD_RELOC_16, 4 },
93916dce513Schristos     { M32C_OPERAND_DSP_40_S16, BFD_RELOC_16, 5 },
94016dce513Schristos     { M32C_OPERAND_DSP_8_U16,  BFD_RELOC_16, 1 },
94116dce513Schristos     { M32C_OPERAND_DSP_16_U16, BFD_RELOC_16, 2 },
94216dce513Schristos     { M32C_OPERAND_DSP_24_U16, BFD_RELOC_16, 3 },
94316dce513Schristos     { M32C_OPERAND_DSP_32_U16, BFD_RELOC_16, 4 },
94416dce513Schristos     { M32C_OPERAND_DSP_40_U16, BFD_RELOC_16, 5 },
94516dce513Schristos     { M32C_OPERAND_DSP_48_U16, BFD_RELOC_16, 6 },
94616dce513Schristos     { M32C_OPERAND_BITBASE32_16_S19_UNPREFIXED, BFD_RELOC_16, 2 },
94716dce513Schristos     { M32C_OPERAND_BITBASE32_16_U19_UNPREFIXED, BFD_RELOC_16, 2 },
94816dce513Schristos     { M32C_OPERAND_BITBASE32_24_S19_PREFIXED, BFD_RELOC_16, 3 },
94916dce513Schristos     { M32C_OPERAND_BITBASE32_24_U19_PREFIXED, BFD_RELOC_16, 3 },
95016dce513Schristos 
95116dce513Schristos     /* Absolute relocs for 24-bit fields.  */
95216dce513Schristos     { M32C_OPERAND_LAB_8_24,   BFD_RELOC_24, 1 },
95316dce513Schristos     { M32C_OPERAND_DSP_8_S24,  BFD_RELOC_24, 1 },
95416dce513Schristos     { M32C_OPERAND_DSP_8_U24,  BFD_RELOC_24, 1 },
95516dce513Schristos     { M32C_OPERAND_DSP_16_U24, BFD_RELOC_24, 2 },
95616dce513Schristos     { M32C_OPERAND_DSP_24_U24, BFD_RELOC_24, 3 },
95716dce513Schristos     { M32C_OPERAND_DSP_32_U24, BFD_RELOC_24, 4 },
95816dce513Schristos     { M32C_OPERAND_DSP_40_U24, BFD_RELOC_24, 5 },
95916dce513Schristos     { M32C_OPERAND_DSP_48_U24, BFD_RELOC_24, 6 },
96016dce513Schristos     { M32C_OPERAND_DSP_16_U20, BFD_RELOC_24, 2 },
96116dce513Schristos     { M32C_OPERAND_DSP_24_U20, BFD_RELOC_24, 3 },
96216dce513Schristos     { M32C_OPERAND_DSP_32_U20, BFD_RELOC_24, 4 },
96316dce513Schristos     { M32C_OPERAND_BITBASE32_16_U27_UNPREFIXED, BFD_RELOC_24, 2 },
96416dce513Schristos     { M32C_OPERAND_BITBASE32_24_U27_PREFIXED, BFD_RELOC_24, 3 },
96516dce513Schristos 
96616dce513Schristos     /* Absolute relocs for 32-bit fields.  */
96716dce513Schristos     { M32C_OPERAND_IMM_16_SI,  BFD_RELOC_32, 2 },
96816dce513Schristos     { M32C_OPERAND_IMM_24_SI,  BFD_RELOC_32, 3 },
96916dce513Schristos     { M32C_OPERAND_IMM_32_SI,  BFD_RELOC_32, 4 },
97016dce513Schristos     { M32C_OPERAND_IMM_40_SI,  BFD_RELOC_32, 5 },
97116dce513Schristos 
97216dce513Schristos   };
97316dce513Schristos 
97416dce513Schristos   int i;
97516dce513Schristos 
97616dce513Schristos   for (i = ARRAY_SIZE (op_reloc_table); --i >= 0; )
97716dce513Schristos     {
97816dce513Schristos       const struct op_reloc *or = &op_reloc_table[i];
97916dce513Schristos 
98016dce513Schristos       if (or->operand == operand->type)
98116dce513Schristos         {
98216dce513Schristos           fixP->fx_where += or->offset;
98316dce513Schristos           fixP->fx_size -= or->offset;
98416dce513Schristos 
98516dce513Schristos 	  if (fixP->fx_cgen.opinfo
98616dce513Schristos 	      && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
98716dce513Schristos 	    return fixP->fx_cgen.opinfo;
98816dce513Schristos 
98916dce513Schristos           return or->reloc;
99016dce513Schristos         }
99116dce513Schristos     }
99216dce513Schristos 
99316dce513Schristos   fprintf
99416dce513Schristos     (stderr,
99516dce513Schristos      "Error: tc-m32c.c:md_cgen_lookup_reloc Unimplemented relocation for operand %s\n",
99616dce513Schristos      operand->name);
99716dce513Schristos 
99816dce513Schristos   return BFD_RELOC_NONE;
99916dce513Schristos }
100016dce513Schristos 
100116dce513Schristos void
m32c_cons_fix_new(fragS * frag,int where,int size,expressionS * exp,bfd_reloc_code_real_type type)100216dce513Schristos m32c_cons_fix_new (fragS *	frag,
100316dce513Schristos 		   int		where,
100416dce513Schristos 		   int		size,
100516dce513Schristos 		   expressionS *exp,
100616dce513Schristos 		   bfd_reloc_code_real_type type)
100716dce513Schristos {
100816dce513Schristos   switch (size)
100916dce513Schristos     {
101016dce513Schristos     case 1:
101116dce513Schristos       type = BFD_RELOC_8;
101216dce513Schristos       break;
101316dce513Schristos     case 2:
101416dce513Schristos       type = BFD_RELOC_16;
101516dce513Schristos       break;
101616dce513Schristos     case 3:
101716dce513Schristos       type = BFD_RELOC_24;
101816dce513Schristos       break;
101916dce513Schristos     case 4:
102016dce513Schristos     default:
102116dce513Schristos       type = BFD_RELOC_32;
102216dce513Schristos       break;
102316dce513Schristos     case 8:
102416dce513Schristos       type = BFD_RELOC_64;
102516dce513Schristos       break;
102616dce513Schristos     }
102716dce513Schristos 
102816dce513Schristos   fix_new_exp (frag, where, (int) size, exp, 0, type);
102916dce513Schristos }
103016dce513Schristos 
103116dce513Schristos void
m32c_apply_fix(struct fix * f,valueT * t,segT s)103216dce513Schristos m32c_apply_fix (struct fix *f, valueT *t, segT s)
103316dce513Schristos {
103416dce513Schristos   if (f->fx_r_type == BFD_RELOC_M32C_RL_JUMP
103516dce513Schristos       || f->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
103616dce513Schristos       || f->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
103716dce513Schristos     return;
103816dce513Schristos   gas_cgen_md_apply_fix (f, t, s);
103916dce513Schristos }
104016dce513Schristos 
104116dce513Schristos arelent *
tc_gen_reloc(asection * sec,fixS * fx)104216dce513Schristos tc_gen_reloc (asection *sec, fixS *fx)
104316dce513Schristos {
104416dce513Schristos   if (fx->fx_r_type == BFD_RELOC_M32C_RL_JUMP
104516dce513Schristos       || fx->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
104616dce513Schristos       || fx->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
104716dce513Schristos     {
104816dce513Schristos       arelent * reloc;
104916dce513Schristos 
105016dce513Schristos       reloc = XNEW (arelent);
105116dce513Schristos 
105216dce513Schristos       reloc->sym_ptr_ptr = XNEW (asymbol *);
105316dce513Schristos       *reloc->sym_ptr_ptr = symbol_get_bfdsym (fx->fx_addsy);
105416dce513Schristos       reloc->address = fx->fx_frag->fr_address + fx->fx_where;
105516dce513Schristos       reloc->howto = bfd_reloc_type_lookup (stdoutput, fx->fx_r_type);
105616dce513Schristos       reloc->addend = fx->fx_offset;
105716dce513Schristos       return reloc;
105816dce513Schristos 
105916dce513Schristos     }
106016dce513Schristos   return gas_cgen_tc_gen_reloc (sec, fx);
106116dce513Schristos }
106216dce513Schristos 
106316dce513Schristos /* See whether we need to force a relocation into the output file.
106416dce513Schristos    This is used to force out switch and PC relative relocations when
106516dce513Schristos    relaxing.  */
106616dce513Schristos 
106716dce513Schristos int
m32c_force_relocation(fixS * fixp)106816dce513Schristos m32c_force_relocation (fixS * fixp)
106916dce513Schristos {
107016dce513Schristos   int reloc = fixp->fx_r_type;
107116dce513Schristos 
107216dce513Schristos   if (reloc > (int)BFD_RELOC_UNUSED)
107316dce513Schristos     {
107416dce513Schristos       reloc -= (int)BFD_RELOC_UNUSED;
107516dce513Schristos       switch (reloc)
107616dce513Schristos 	{
107716dce513Schristos 	case M32C_OPERAND_DSP_32_S16:
107816dce513Schristos 	case M32C_OPERAND_DSP_32_U16:
107916dce513Schristos 	case M32C_OPERAND_IMM_32_HI:
108016dce513Schristos 	case M32C_OPERAND_DSP_16_S16:
108116dce513Schristos 	case M32C_OPERAND_DSP_16_U16:
108216dce513Schristos 	case M32C_OPERAND_IMM_16_HI:
108316dce513Schristos 	case M32C_OPERAND_DSP_24_S16:
108416dce513Schristos 	case M32C_OPERAND_DSP_24_U16:
108516dce513Schristos 	case M32C_OPERAND_IMM_24_HI:
108616dce513Schristos 	  return 1;
108716dce513Schristos 
108816dce513Schristos         /* If we're doing linker relaxing, we need to keep all the
108916dce513Schristos 	   pc-relative jumps in case we need to fix them due to
109016dce513Schristos 	   deleted bytes between the jump and its destination.  */
109116dce513Schristos 	case M32C_OPERAND_LAB_8_8:
109216dce513Schristos 	case M32C_OPERAND_LAB_8_16:
109316dce513Schristos 	case M32C_OPERAND_LAB_8_24:
109416dce513Schristos 	case M32C_OPERAND_LAB_16_8:
109516dce513Schristos 	case M32C_OPERAND_LAB_24_8:
109616dce513Schristos 	case M32C_OPERAND_LAB_32_8:
109716dce513Schristos 	case M32C_OPERAND_LAB_40_8:
109816dce513Schristos 	  if (m32c_relax)
109916dce513Schristos 	    return 1;
110016dce513Schristos 	default:
110116dce513Schristos 	  break;
110216dce513Schristos 	}
110316dce513Schristos     }
110416dce513Schristos   else
110516dce513Schristos     {
110616dce513Schristos       switch (fixp->fx_r_type)
110716dce513Schristos 	{
110816dce513Schristos 	case BFD_RELOC_16:
110916dce513Schristos 	  return 1;
111016dce513Schristos 
111116dce513Schristos 	case BFD_RELOC_M32C_RL_JUMP:
111216dce513Schristos 	case BFD_RELOC_M32C_RL_1ADDR:
111316dce513Schristos 	case BFD_RELOC_M32C_RL_2ADDR:
111416dce513Schristos 	case BFD_RELOC_8_PCREL:
111516dce513Schristos 	case BFD_RELOC_16_PCREL:
111616dce513Schristos 	  if (m32c_relax)
111716dce513Schristos 	    return 1;
111816dce513Schristos 	default:
111916dce513Schristos 	  break;
112016dce513Schristos 	}
112116dce513Schristos     }
112216dce513Schristos 
112316dce513Schristos   return generic_force_reloc (fixp);
112416dce513Schristos }
112516dce513Schristos 
112616dce513Schristos /* Write a value out to the object file, using the appropriate endianness.  */
112716dce513Schristos 
112816dce513Schristos void
md_number_to_chars(char * buf,valueT val,int n)112916dce513Schristos md_number_to_chars (char * buf, valueT val, int n)
113016dce513Schristos {
113116dce513Schristos   number_to_chars_littleendian (buf, val, n);
113216dce513Schristos }
113316dce513Schristos 
113416dce513Schristos /* Turn a string in input_line_pointer into a floating point constant of type
113516dce513Schristos    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
113616dce513Schristos    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.  */
113716dce513Schristos 
113816dce513Schristos const char *
md_atof(int type,char * litP,int * sizeP)113916dce513Schristos md_atof (int type, char * litP, int * sizeP)
114016dce513Schristos {
1141*e992f068Schristos   return ieee_md_atof (type, litP, sizeP, true);
114216dce513Schristos }
114316dce513Schristos 
1144*e992f068Schristos bool
m32c_fix_adjustable(fixS * fixP)114516dce513Schristos m32c_fix_adjustable (fixS * fixP)
114616dce513Schristos {
114716dce513Schristos   int reloc;
114816dce513Schristos   if (fixP->fx_addsy == NULL)
114916dce513Schristos     return 1;
115016dce513Schristos 
115116dce513Schristos   /* We need the symbol name for the VTABLE entries.  */
115216dce513Schristos   reloc = fixP->fx_r_type;
115316dce513Schristos   if (reloc > (int)BFD_RELOC_UNUSED)
115416dce513Schristos     {
115516dce513Schristos       reloc -= (int)BFD_RELOC_UNUSED;
115616dce513Schristos       switch (reloc)
115716dce513Schristos 	{
115816dce513Schristos 	case M32C_OPERAND_DSP_32_S16:
115916dce513Schristos 	case M32C_OPERAND_DSP_32_U16:
116016dce513Schristos 	case M32C_OPERAND_IMM_32_HI:
116116dce513Schristos 	case M32C_OPERAND_DSP_16_S16:
116216dce513Schristos 	case M32C_OPERAND_DSP_16_U16:
116316dce513Schristos 	case M32C_OPERAND_IMM_16_HI:
116416dce513Schristos 	case M32C_OPERAND_DSP_24_S16:
116516dce513Schristos 	case M32C_OPERAND_DSP_24_U16:
116616dce513Schristos 	case M32C_OPERAND_IMM_24_HI:
116716dce513Schristos 	  return 0;
116816dce513Schristos 	}
116916dce513Schristos     }
117016dce513Schristos   else
117116dce513Schristos     {
117216dce513Schristos       if (fixP->fx_r_type == BFD_RELOC_16)
117316dce513Schristos 	return 0;
117416dce513Schristos     }
117516dce513Schristos 
117616dce513Schristos   /* Do not adjust relocations involving symbols in merged sections.
117716dce513Schristos 
117816dce513Schristos      A reloc patching in the value of some symbol S plus some addend A
117916dce513Schristos      can be produced in different ways:
118016dce513Schristos 
118116dce513Schristos      1) It might simply be a reference to the data at S + A.  Clearly,
118216dce513Schristos         if linker merging shift that data around, the value patched in
118316dce513Schristos         by the reloc needs to be adjusted accordingly.
118416dce513Schristos 
118516dce513Schristos      2) Or, it might be a reference to S, with A added in as a constant
118616dce513Schristos 	bias.  For example, given code like this:
118716dce513Schristos 
118816dce513Schristos 	  static int S[100];
118916dce513Schristos 
119016dce513Schristos 	  ... S[i - 8] ...
119116dce513Schristos 
119216dce513Schristos 	it would be reasonable for the compiler to rearrange the array
119316dce513Schristos 	reference to something like:
119416dce513Schristos 
119516dce513Schristos 	  ... (S-8)[i] ...
119616dce513Schristos 
119716dce513Schristos 	and emit assembly code that refers to S - (8 * sizeof (int)),
119816dce513Schristos 	so the subtraction is done entirely at compile-time.  In this
119916dce513Schristos 	case, the reloc's addend A would be -(8 * sizeof (int)), and
120016dce513Schristos 	shifting around code or data at S + A should not affect the
120116dce513Schristos 	reloc: the reloc isn't referring to that code or data at all.
120216dce513Schristos 
120316dce513Schristos      The linker has no way of knowing which case it has in hand.  So,
120416dce513Schristos      to disambiguate, we have the linker always treat reloc addends as
120516dce513Schristos      in case 2): they're constants that should be simply added to the
120616dce513Schristos      symbol value, just like the reloc says.  And we express case 1)
120716dce513Schristos      in different way: we have the compiler place a label at the real
120816dce513Schristos      target, and reference that label with an addend of zero.  (The
120916dce513Schristos      compiler is unlikely to reference code using a label plus an
121016dce513Schristos      offset anyway, since it doesn't know the sizes of the
121116dce513Schristos      instructions.)
121216dce513Schristos 
121316dce513Schristos      The simplification being done by gas/write.c:adjust_reloc_syms,
121416dce513Schristos      however, turns the explicit-label usage into the label-plus-
121516dce513Schristos      offset usage, re-introducing the ambiguity the compiler avoided.
121616dce513Schristos      So we need to disable that simplification for symbols referring
121716dce513Schristos      to merged data.
121816dce513Schristos 
121916dce513Schristos      This only affects object size a little bit.  */
122016dce513Schristos   if (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE)
122116dce513Schristos     return 0;
122216dce513Schristos 
122316dce513Schristos   if (m32c_relax)
122416dce513Schristos     return 0;
122516dce513Schristos 
122616dce513Schristos   return 1;
122716dce513Schristos }
122816dce513Schristos 
122916dce513Schristos /* Worker function for m32c_is_colon_insn().  */
123016dce513Schristos static int
restore_colon(char * next_i_l_p,char * nul_char)123116dce513Schristos restore_colon (char *next_i_l_p, char *nul_char)
123216dce513Schristos {
123316dce513Schristos   /* Restore the colon, and advance input_line_pointer to
123416dce513Schristos      the end of the new symbol.  */
123516dce513Schristos   *input_line_pointer = *nul_char;
123616dce513Schristos   input_line_pointer = next_i_l_p;
123716dce513Schristos   *nul_char = *next_i_l_p;
123816dce513Schristos   *next_i_l_p = 0;
123916dce513Schristos   return 1;
124016dce513Schristos }
124116dce513Schristos 
124216dce513Schristos /* Determines if the symbol starting at START and ending in
124316dce513Schristos    a colon that was at the location pointed to by INPUT_LINE_POINTER
124416dce513Schristos    (but which has now been replaced bu a NUL) is in fact an
124516dce513Schristos    :Z, :S, :Q, or :G suffix.
124616dce513Schristos    If it is, then it restores the colon, advances INPUT_LINE_POINTER
124716dce513Schristos    to the real end of the instruction/symbol, saves the char there to
124816dce513Schristos    NUL_CHAR and pokes a NUL, and returns 1.  Otherwise it returns 0.  */
124916dce513Schristos int
m32c_is_colon_insn(char * start ATTRIBUTE_UNUSED,char * nul_char)125016dce513Schristos m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED, char *nul_char)
125116dce513Schristos {
125216dce513Schristos   char * i_l_p = input_line_pointer;
125316dce513Schristos 
125416dce513Schristos   if (*nul_char == '"')
125516dce513Schristos     ++i_l_p;
125616dce513Schristos 
125716dce513Schristos   /* Check to see if the text following the colon is 'G' */
125816dce513Schristos   if (TOLOWER (i_l_p[1]) == 'g' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
125916dce513Schristos     return restore_colon (i_l_p + 2, nul_char);
126016dce513Schristos 
126116dce513Schristos   /* Check to see if the text following the colon is 'Q' */
126216dce513Schristos   if (TOLOWER (i_l_p[1]) == 'q' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
126316dce513Schristos     return restore_colon (i_l_p + 2, nul_char);
126416dce513Schristos 
126516dce513Schristos   /* Check to see if the text following the colon is 'S' */
126616dce513Schristos   if (TOLOWER (i_l_p[1]) == 's' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
126716dce513Schristos     return restore_colon (i_l_p + 2, nul_char);
126816dce513Schristos 
126916dce513Schristos   /* Check to see if the text following the colon is 'Z' */
127016dce513Schristos   if (TOLOWER (i_l_p[1]) == 'z' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
127116dce513Schristos     return restore_colon (i_l_p + 2, nul_char);
127216dce513Schristos 
127316dce513Schristos   return 0;
127416dce513Schristos }
1275