xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/config/tc-m32c.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* tc-m32c.c -- Assembler for the Renesas M32C.
2*3d8817e4Smiod    Copyright (C) 2005 Free Software Foundation.
3*3d8817e4Smiod    Contributed by RedHat.
4*3d8817e4Smiod 
5*3d8817e4Smiod    This file is part of GAS, the GNU Assembler.
6*3d8817e4Smiod 
7*3d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
8*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
10*3d8817e4Smiod    any later version.
11*3d8817e4Smiod 
12*3d8817e4Smiod    GAS is distributed in the hope that it will be useful,
13*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*3d8817e4Smiod    GNU General Public License for more details.
16*3d8817e4Smiod 
17*3d8817e4Smiod    You should have received a copy of the GNU General Public License
18*3d8817e4Smiod    along with GAS; see the file COPYING.  If not, write to
19*3d8817e4Smiod    the Free Software Foundation, 59 Temple Place - Suite 330,
20*3d8817e4Smiod    Boston, MA 02111-1307, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod #include <stdio.h>
23*3d8817e4Smiod #include "as.h"
24*3d8817e4Smiod #include "subsegs.h"
25*3d8817e4Smiod #include "symcat.h"
26*3d8817e4Smiod #include "opcodes/m32c-desc.h"
27*3d8817e4Smiod #include "opcodes/m32c-opc.h"
28*3d8817e4Smiod #include "cgen.h"
29*3d8817e4Smiod #include "elf/common.h"
30*3d8817e4Smiod #include "elf/m32c.h"
31*3d8817e4Smiod #include "libbfd.h"
32*3d8817e4Smiod #include "libiberty.h"
33*3d8817e4Smiod #include "safe-ctype.h"
34*3d8817e4Smiod #include "bfd.h"
35*3d8817e4Smiod 
36*3d8817e4Smiod /* Structure to hold all of the different components
37*3d8817e4Smiod    describing an individual instruction.  */
38*3d8817e4Smiod typedef struct
39*3d8817e4Smiod {
40*3d8817e4Smiod   const CGEN_INSN *	insn;
41*3d8817e4Smiod   const CGEN_INSN *	orig_insn;
42*3d8817e4Smiod   CGEN_FIELDS		fields;
43*3d8817e4Smiod #if CGEN_INT_INSN_P
44*3d8817e4Smiod   CGEN_INSN_INT         buffer [1];
45*3d8817e4Smiod #define INSN_VALUE(buf) (*(buf))
46*3d8817e4Smiod #else
47*3d8817e4Smiod   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
48*3d8817e4Smiod #define INSN_VALUE(buf) (buf)
49*3d8817e4Smiod #endif
50*3d8817e4Smiod   char *		addr;
51*3d8817e4Smiod   fragS *		frag;
52*3d8817e4Smiod   int                   num_fixups;
53*3d8817e4Smiod   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
54*3d8817e4Smiod   int                   indices [MAX_OPERAND_INSTANCES];
55*3d8817e4Smiod }
56*3d8817e4Smiod m32c_insn;
57*3d8817e4Smiod 
58*3d8817e4Smiod #define rl_for(insn) (CGEN_ATTR_CGEN_INSN_RL_TYPE_VALUE (&(insn.insn->base->attrs)))
59*3d8817e4Smiod #define relaxable(insn) (CGEN_ATTR_CGEN_INSN_RELAXABLE_VALUE (&(insn.insn->base->attrs)))
60*3d8817e4Smiod 
61*3d8817e4Smiod const char comment_chars[]        = ";";
62*3d8817e4Smiod const char line_comment_chars[]   = "#";
63*3d8817e4Smiod const char line_separator_chars[] = "|";
64*3d8817e4Smiod const char EXP_CHARS[]            = "eE";
65*3d8817e4Smiod const char FLT_CHARS[]            = "dD";
66*3d8817e4Smiod 
67*3d8817e4Smiod #define M32C_SHORTOPTS ""
68*3d8817e4Smiod const char * md_shortopts = M32C_SHORTOPTS;
69*3d8817e4Smiod 
70*3d8817e4Smiod /* assembler options */
71*3d8817e4Smiod #define OPTION_CPU_M16C	       (OPTION_MD_BASE)
72*3d8817e4Smiod #define OPTION_CPU_M32C        (OPTION_MD_BASE + 1)
73*3d8817e4Smiod #define OPTION_LINKRELAX       (OPTION_MD_BASE + 2)
74*3d8817e4Smiod 
75*3d8817e4Smiod struct option md_longopts[] =
76*3d8817e4Smiod {
77*3d8817e4Smiod   { "m16c",       no_argument,	      NULL, OPTION_CPU_M16C   },
78*3d8817e4Smiod   { "m32c",       no_argument,	      NULL, OPTION_CPU_M32C   },
79*3d8817e4Smiod   { "relax",      no_argument,	      NULL, OPTION_LINKRELAX   },
80*3d8817e4Smiod   {NULL, no_argument, NULL, 0}
81*3d8817e4Smiod };
82*3d8817e4Smiod size_t md_longopts_size = sizeof (md_longopts);
83*3d8817e4Smiod 
84*3d8817e4Smiod /* Default machine */
85*3d8817e4Smiod 
86*3d8817e4Smiod #define DEFAULT_MACHINE bfd_mach_m16c
87*3d8817e4Smiod #define DEFAULT_FLAGS	EF_M32C_CPU_M16C
88*3d8817e4Smiod 
89*3d8817e4Smiod static unsigned long m32c_mach = bfd_mach_m16c;
90*3d8817e4Smiod static int cpu_mach = (1 << MACH_M16C);
91*3d8817e4Smiod static int insn_size;
92*3d8817e4Smiod static int m32c_relax = 0;
93*3d8817e4Smiod 
94*3d8817e4Smiod /* Flags to set in the elf header */
95*3d8817e4Smiod static flagword m32c_flags = DEFAULT_FLAGS;
96*3d8817e4Smiod 
97*3d8817e4Smiod static char default_isa = 1 << (7 - ISA_M16C);
98*3d8817e4Smiod static CGEN_BITSET m32c_isa = {1, & default_isa};
99*3d8817e4Smiod 
100*3d8817e4Smiod static void
set_isa(enum isa_attr isa_num)101*3d8817e4Smiod set_isa (enum isa_attr isa_num)
102*3d8817e4Smiod {
103*3d8817e4Smiod   cgen_bitset_set (& m32c_isa, isa_num);
104*3d8817e4Smiod }
105*3d8817e4Smiod 
106*3d8817e4Smiod static void s_bss (int);
107*3d8817e4Smiod 
108*3d8817e4Smiod int
md_parse_option(int c,char * arg ATTRIBUTE_UNUSED)109*3d8817e4Smiod md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
110*3d8817e4Smiod {
111*3d8817e4Smiod   switch (c)
112*3d8817e4Smiod     {
113*3d8817e4Smiod     case OPTION_CPU_M16C:
114*3d8817e4Smiod       m32c_flags = (m32c_flags & ~EF_M32C_CPU_MASK) | EF_M32C_CPU_M16C;
115*3d8817e4Smiod       m32c_mach = bfd_mach_m16c;
116*3d8817e4Smiod       cpu_mach = (1 << MACH_M16C);
117*3d8817e4Smiod       set_isa (ISA_M16C);
118*3d8817e4Smiod       break;
119*3d8817e4Smiod 
120*3d8817e4Smiod     case OPTION_CPU_M32C:
121*3d8817e4Smiod       m32c_flags = (m32c_flags & ~EF_M32C_CPU_MASK) | EF_M32C_CPU_M32C;
122*3d8817e4Smiod       m32c_mach = bfd_mach_m32c;
123*3d8817e4Smiod       cpu_mach = (1 << MACH_M32C);
124*3d8817e4Smiod       set_isa (ISA_M32C);
125*3d8817e4Smiod       break;
126*3d8817e4Smiod 
127*3d8817e4Smiod     case OPTION_LINKRELAX:
128*3d8817e4Smiod       m32c_relax = 1;
129*3d8817e4Smiod       break;
130*3d8817e4Smiod 
131*3d8817e4Smiod     default:
132*3d8817e4Smiod       return 0;
133*3d8817e4Smiod     }
134*3d8817e4Smiod   return 1;
135*3d8817e4Smiod }
136*3d8817e4Smiod 
137*3d8817e4Smiod void
md_show_usage(FILE * stream)138*3d8817e4Smiod md_show_usage (FILE * stream)
139*3d8817e4Smiod {
140*3d8817e4Smiod   fprintf (stream, _(" M32C specific command line options:\n"));
141*3d8817e4Smiod }
142*3d8817e4Smiod 
143*3d8817e4Smiod static void
s_bss(int ignore ATTRIBUTE_UNUSED)144*3d8817e4Smiod s_bss (int ignore ATTRIBUTE_UNUSED)
145*3d8817e4Smiod {
146*3d8817e4Smiod   int temp;
147*3d8817e4Smiod 
148*3d8817e4Smiod   temp = get_absolute_expression ();
149*3d8817e4Smiod   subseg_set (bss_section, (subsegT) temp);
150*3d8817e4Smiod   demand_empty_rest_of_line ();
151*3d8817e4Smiod }
152*3d8817e4Smiod 
153*3d8817e4Smiod /* The target specific pseudo-ops which we support.  */
154*3d8817e4Smiod const pseudo_typeS md_pseudo_table[] =
155*3d8817e4Smiod {
156*3d8817e4Smiod   { "bss",	s_bss, 		0},
157*3d8817e4Smiod   { "word",	cons,		4 },
158*3d8817e4Smiod   { NULL, 	NULL, 		0 }
159*3d8817e4Smiod };
160*3d8817e4Smiod 
161*3d8817e4Smiod 
162*3d8817e4Smiod void
md_begin(void)163*3d8817e4Smiod md_begin (void)
164*3d8817e4Smiod {
165*3d8817e4Smiod   /* Initialize the `cgen' interface.  */
166*3d8817e4Smiod 
167*3d8817e4Smiod   /* Set the machine number and endian.  */
168*3d8817e4Smiod   gas_cgen_cpu_desc = m32c_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
169*3d8817e4Smiod 					  CGEN_CPU_OPEN_ENDIAN,
170*3d8817e4Smiod 					  CGEN_ENDIAN_BIG,
171*3d8817e4Smiod 					  CGEN_CPU_OPEN_ISAS, & m32c_isa,
172*3d8817e4Smiod 					  CGEN_CPU_OPEN_END);
173*3d8817e4Smiod 
174*3d8817e4Smiod   m32c_cgen_init_asm (gas_cgen_cpu_desc);
175*3d8817e4Smiod 
176*3d8817e4Smiod   /* This is a callback from cgen to gas to parse operands.  */
177*3d8817e4Smiod   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
178*3d8817e4Smiod 
179*3d8817e4Smiod   /* Set the ELF flags if desired. */
180*3d8817e4Smiod   if (m32c_flags)
181*3d8817e4Smiod     bfd_set_private_flags (stdoutput, m32c_flags);
182*3d8817e4Smiod 
183*3d8817e4Smiod   /* Set the machine type */
184*3d8817e4Smiod   bfd_default_set_arch_mach (stdoutput, bfd_arch_m32c, m32c_mach);
185*3d8817e4Smiod 
186*3d8817e4Smiod   insn_size = 0;
187*3d8817e4Smiod }
188*3d8817e4Smiod 
189*3d8817e4Smiod void
m32c_md_end(void)190*3d8817e4Smiod m32c_md_end (void)
191*3d8817e4Smiod {
192*3d8817e4Smiod   int i, n_nops;
193*3d8817e4Smiod 
194*3d8817e4Smiod   if (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)
195*3d8817e4Smiod     {
196*3d8817e4Smiod       /* Pad with nops for objdump.  */
197*3d8817e4Smiod       n_nops = (32 - ((insn_size) % 32)) / 8;
198*3d8817e4Smiod       for (i = 1; i <= n_nops; i++)
199*3d8817e4Smiod 	md_assemble ("nop");
200*3d8817e4Smiod     }
201*3d8817e4Smiod }
202*3d8817e4Smiod 
203*3d8817e4Smiod void
m32c_start_line_hook(void)204*3d8817e4Smiod m32c_start_line_hook (void)
205*3d8817e4Smiod {
206*3d8817e4Smiod #if 0 /* not necessary....handled in the .cpu file */
207*3d8817e4Smiod   char *s = input_line_pointer;
208*3d8817e4Smiod   char *sg;
209*3d8817e4Smiod 
210*3d8817e4Smiod   for (s = input_line_pointer ; s && s[0] != '\n'; s++)
211*3d8817e4Smiod     {
212*3d8817e4Smiod       if (s[0] == ':')
213*3d8817e4Smiod 	{
214*3d8817e4Smiod 	  /* Remove :g suffix.  Squeeze out blanks.  */
215*3d8817e4Smiod 	  if (s[1] == 'g')
216*3d8817e4Smiod 	    {
217*3d8817e4Smiod 	      for (sg = s - 1; sg && sg >= input_line_pointer; sg--)
218*3d8817e4Smiod 		{
219*3d8817e4Smiod 		  sg[2] = sg[0];
220*3d8817e4Smiod 		}
221*3d8817e4Smiod 	      sg[1] = ' ';
222*3d8817e4Smiod 	      sg[2] = ' ';
223*3d8817e4Smiod 	      input_line_pointer += 2;
224*3d8817e4Smiod 	    }
225*3d8817e4Smiod 	}
226*3d8817e4Smiod     }
227*3d8817e4Smiod #endif
228*3d8817e4Smiod }
229*3d8817e4Smiod 
230*3d8817e4Smiod /* Process [[indirect-operands]] in instruction str.  */
231*3d8817e4Smiod 
232*3d8817e4Smiod static bfd_boolean
m32c_indirect_operand(char * str)233*3d8817e4Smiod m32c_indirect_operand (char *str)
234*3d8817e4Smiod {
235*3d8817e4Smiod   char *new_str;
236*3d8817e4Smiod   char *s;
237*3d8817e4Smiod   char *ns;
238*3d8817e4Smiod   int ns_len;
239*3d8817e4Smiod   char *ns_end;
240*3d8817e4Smiod   enum indirect_type {none, relative, absolute} ;
241*3d8817e4Smiod   enum indirect_type indirection [3] = { none, none, none };
242*3d8817e4Smiod   int brace_n [3] = { 0, 0, 0 };
243*3d8817e4Smiod   int operand;
244*3d8817e4Smiod 
245*3d8817e4Smiod   s = str;
246*3d8817e4Smiod   operand = 1;
247*3d8817e4Smiod   for (s = str; *s; s++)
248*3d8817e4Smiod     {
249*3d8817e4Smiod       if (s[0] == ',')
250*3d8817e4Smiod 	operand = 2;
251*3d8817e4Smiod       /* [abs] where abs is not a0 or a1  */
252*3d8817e4Smiod       if (s[1] == '[' && ! (s[2] == 'a' && (s[3] == '0' || s[3] == '1'))
253*3d8817e4Smiod 	  && (ISBLANK (s[0]) || s[0] == ','))
254*3d8817e4Smiod 	indirection[operand] = absolute;
255*3d8817e4Smiod       if (s[0] == ']' && s[1] == ']')
256*3d8817e4Smiod 	indirection[operand] = relative;
257*3d8817e4Smiod       if (s[0] == '[' && s[1] == '[')
258*3d8817e4Smiod 	indirection[operand] = relative;
259*3d8817e4Smiod     }
260*3d8817e4Smiod 
261*3d8817e4Smiod   if (indirection[1] == none && indirection[2] == none)
262*3d8817e4Smiod     return FALSE;
263*3d8817e4Smiod 
264*3d8817e4Smiod   operand = 1;
265*3d8817e4Smiod   ns_len = strlen (str);
266*3d8817e4Smiod   new_str = (char*) xmalloc (ns_len);
267*3d8817e4Smiod   ns = new_str;
268*3d8817e4Smiod   ns_end = ns + ns_len;
269*3d8817e4Smiod 
270*3d8817e4Smiod   for (s = str; *s; s++)
271*3d8817e4Smiod     {
272*3d8817e4Smiod       if (s[0] == ',')
273*3d8817e4Smiod 	operand = 2;
274*3d8817e4Smiod 
275*3d8817e4Smiod       if (s[0] == '[' && ! brace_n[operand])
276*3d8817e4Smiod 	{
277*3d8817e4Smiod 	  brace_n[operand] += 1;
278*3d8817e4Smiod 	  /* Squeeze [[ to [ if this is an indirect operand.  */
279*3d8817e4Smiod 	  if (indirection[operand] != none)
280*3d8817e4Smiod 	    continue;
281*3d8817e4Smiod 	}
282*3d8817e4Smiod 
283*3d8817e4Smiod       else if (s[0] == '[' && brace_n[operand])
284*3d8817e4Smiod 	{
285*3d8817e4Smiod 	  brace_n[operand] += 1;
286*3d8817e4Smiod 	}
287*3d8817e4Smiod       else if (s[0] == ']' && s[1] == ']' && indirection[operand] == relative)
288*3d8817e4Smiod 	{
289*3d8817e4Smiod 	  s += 1;		/* skip one ].  */
290*3d8817e4Smiod 	  brace_n[operand] -= 2; /* allow for 2 [.  */
291*3d8817e4Smiod 	}
292*3d8817e4Smiod       else if (s[0] == ']' && indirection[operand] == absolute)
293*3d8817e4Smiod 	{
294*3d8817e4Smiod 	  brace_n[operand] -= 1;
295*3d8817e4Smiod 	  continue;		/* skip closing ].  */
296*3d8817e4Smiod 	}
297*3d8817e4Smiod       else if (s[0] == ']')
298*3d8817e4Smiod 	{
299*3d8817e4Smiod 	  brace_n[operand] -= 1;
300*3d8817e4Smiod 	}
301*3d8817e4Smiod       *ns = s[0];
302*3d8817e4Smiod       ns += 1;
303*3d8817e4Smiod       if (ns >= ns_end)
304*3d8817e4Smiod 	return FALSE;
305*3d8817e4Smiod       if (s[0] == 0)
306*3d8817e4Smiod 	break;
307*3d8817e4Smiod     }
308*3d8817e4Smiod   *ns = '\0';
309*3d8817e4Smiod   for (operand = 1; operand <= 2; operand++)
310*3d8817e4Smiod     if (brace_n[operand])
311*3d8817e4Smiod       {
312*3d8817e4Smiod 	fprintf (stderr, "Unmatched [[operand-%d]] %d\n", operand, brace_n[operand]);
313*3d8817e4Smiod       }
314*3d8817e4Smiod 
315*3d8817e4Smiod   if (indirection[1] != none && indirection[2] != none)
316*3d8817e4Smiod     md_assemble ("src-dest-indirect");
317*3d8817e4Smiod   else if (indirection[1] != none)
318*3d8817e4Smiod     md_assemble ("src-indirect");
319*3d8817e4Smiod   else if (indirection[2] != none)
320*3d8817e4Smiod     md_assemble ("dest-indirect");
321*3d8817e4Smiod 
322*3d8817e4Smiod   md_assemble (new_str);
323*3d8817e4Smiod   free (new_str);
324*3d8817e4Smiod   return TRUE;
325*3d8817e4Smiod }
326*3d8817e4Smiod 
327*3d8817e4Smiod void
md_assemble(char * str)328*3d8817e4Smiod md_assemble (char * str)
329*3d8817e4Smiod {
330*3d8817e4Smiod   static int last_insn_had_delay_slot = 0;
331*3d8817e4Smiod   m32c_insn insn;
332*3d8817e4Smiod   char *    errmsg;
333*3d8817e4Smiod   finished_insnS results;
334*3d8817e4Smiod   int rl_type;
335*3d8817e4Smiod 
336*3d8817e4Smiod   if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str))
337*3d8817e4Smiod     return;
338*3d8817e4Smiod 
339*3d8817e4Smiod   /* Initialize GAS's cgen interface for a new instruction.  */
340*3d8817e4Smiod   gas_cgen_init_parse ();
341*3d8817e4Smiod 
342*3d8817e4Smiod   insn.insn = m32c_cgen_assemble_insn
343*3d8817e4Smiod     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
344*3d8817e4Smiod 
345*3d8817e4Smiod   if (!insn.insn)
346*3d8817e4Smiod     {
347*3d8817e4Smiod       as_bad ("%s", errmsg);
348*3d8817e4Smiod       return;
349*3d8817e4Smiod     }
350*3d8817e4Smiod 
351*3d8817e4Smiod   results.num_fixups = 0;
352*3d8817e4Smiod   /* Doesn't really matter what we pass for RELAX_P here.  */
353*3d8817e4Smiod   gas_cgen_finish_insn (insn.insn, insn.buffer,
354*3d8817e4Smiod 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, &results);
355*3d8817e4Smiod 
356*3d8817e4Smiod   last_insn_had_delay_slot
357*3d8817e4Smiod     = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
358*3d8817e4Smiod   insn_size = CGEN_INSN_BITSIZE(insn.insn);
359*3d8817e4Smiod 
360*3d8817e4Smiod   rl_type = rl_for (insn);
361*3d8817e4Smiod 
362*3d8817e4Smiod   /* We have to mark all the jumps, because we need to adjust them
363*3d8817e4Smiod      when we delete bytes, but we only need to mark the displacements
364*3d8817e4Smiod      if they're symbolic - if they're not, we've already picked the
365*3d8817e4Smiod      shortest opcode by now.  The linker, however, will still have to
366*3d8817e4Smiod      check any operands to see if they're the displacement type, since
367*3d8817e4Smiod      we don't know (nor record) *which* operands are relaxable.  */
368*3d8817e4Smiod   if (m32c_relax
369*3d8817e4Smiod       && rl_type != RL_TYPE_NONE
370*3d8817e4Smiod       && (rl_type == RL_TYPE_JUMP || results.num_fixups)
371*3d8817e4Smiod       && !relaxable (insn))
372*3d8817e4Smiod     {
373*3d8817e4Smiod       int reloc = 0;
374*3d8817e4Smiod       int addend = results.num_fixups + 16 * insn_size/8;
375*3d8817e4Smiod 
376*3d8817e4Smiod       switch (rl_for (insn))
377*3d8817e4Smiod 	{
378*3d8817e4Smiod 	case RL_TYPE_JUMP:  reloc = BFD_RELOC_M32C_RL_JUMP;  break;
379*3d8817e4Smiod 	case RL_TYPE_1ADDR: reloc = BFD_RELOC_M32C_RL_1ADDR; break;
380*3d8817e4Smiod 	case RL_TYPE_2ADDR: reloc = BFD_RELOC_M32C_RL_2ADDR; break;
381*3d8817e4Smiod 	}
382*3d8817e4Smiod       if (insn.insn->base->num == M32C_INSN_JMP16_S
383*3d8817e4Smiod 	  || insn.insn->base->num == M32C_INSN_JMP32_S)
384*3d8817e4Smiod 	addend = 0x10;
385*3d8817e4Smiod 
386*3d8817e4Smiod       fix_new (results.frag,
387*3d8817e4Smiod 	       results.addr - results.frag->fr_literal,
388*3d8817e4Smiod 	       0, abs_section_sym, addend, 0,
389*3d8817e4Smiod 	       reloc);
390*3d8817e4Smiod     }
391*3d8817e4Smiod }
392*3d8817e4Smiod 
393*3d8817e4Smiod /* The syntax in the manual says constants begin with '#'.
394*3d8817e4Smiod    We just ignore it.  */
395*3d8817e4Smiod 
396*3d8817e4Smiod void
md_operand(expressionS * exp)397*3d8817e4Smiod md_operand (expressionS * exp)
398*3d8817e4Smiod {
399*3d8817e4Smiod   /* In case of a syntax error, escape back to try next syntax combo. */
400*3d8817e4Smiod   if (exp->X_op == O_absent)
401*3d8817e4Smiod     gas_cgen_md_operand (exp);
402*3d8817e4Smiod }
403*3d8817e4Smiod 
404*3d8817e4Smiod valueT
md_section_align(segT segment,valueT size)405*3d8817e4Smiod md_section_align (segT segment, valueT size)
406*3d8817e4Smiod {
407*3d8817e4Smiod   int align = bfd_get_section_alignment (stdoutput, segment);
408*3d8817e4Smiod   return ((size + (1 << align) - 1) & (-1 << align));
409*3d8817e4Smiod }
410*3d8817e4Smiod 
411*3d8817e4Smiod symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)412*3d8817e4Smiod md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
413*3d8817e4Smiod {
414*3d8817e4Smiod   return 0;
415*3d8817e4Smiod }
416*3d8817e4Smiod 
417*3d8817e4Smiod const relax_typeS md_relax_table[] =
418*3d8817e4Smiod {
419*3d8817e4Smiod   /* The fields are:
420*3d8817e4Smiod      1) most positive reach of this state,
421*3d8817e4Smiod      2) most negative reach of this state,
422*3d8817e4Smiod      3) how many bytes this mode will have in the variable part of the frag
423*3d8817e4Smiod      4) which index into the table to try if we can't fit into this one.  */
424*3d8817e4Smiod 
425*3d8817e4Smiod   /* 0 */ {     0,      0, 0,  0 }, /* unused */
426*3d8817e4Smiod   /* 1 */ {     0,      0, 0,  0 }, /* marker for "don't know yet" */
427*3d8817e4Smiod 
428*3d8817e4Smiod   /* 2 */ {   127,   -128, 2,  3 }, /* jcnd16_5.b */
429*3d8817e4Smiod   /* 3 */ { 32767, -32768, 5,  4 }, /* jcnd16_5.w */
430*3d8817e4Smiod   /* 4 */ {     0,      0, 6,  0 }, /* jcnd16_5.a */
431*3d8817e4Smiod 
432*3d8817e4Smiod   /* 5 */ {   127,   -128, 2,  6 }, /* jcnd16.b */
433*3d8817e4Smiod   /* 6 */ { 32767, -32768, 5,  7 }, /* jcnd16.w */
434*3d8817e4Smiod   /* 7 */ {     0,      0, 6,  0 }, /* jcnd16.a */
435*3d8817e4Smiod 
436*3d8817e4Smiod   /* 8 */ {     8,      1, 1,  9 }, /* jmp16.s */
437*3d8817e4Smiod   /* 9 */ {   127,   -128, 2, 10 }, /* jmp16.b */
438*3d8817e4Smiod  /* 10 */ { 32767, -32768, 3, 11 }, /* jmp16.w */
439*3d8817e4Smiod  /* 11 */ {     0,      0, 4,  0 }, /* jmp16.a */
440*3d8817e4Smiod 
441*3d8817e4Smiod  /* 12 */ {   127,   -128, 2, 13 }, /* jcnd32.b */
442*3d8817e4Smiod  /* 13 */ { 32767, -32768, 5, 14 }, /* jcnd32.w */
443*3d8817e4Smiod  /* 14 */ {     0,      0, 6,  0 }, /* jcnd32.a */
444*3d8817e4Smiod 
445*3d8817e4Smiod  /* 15 */ {     8,      1, 1, 16 }, /* jmp32.s */
446*3d8817e4Smiod  /* 16 */ {   127,   -128, 2, 17 }, /* jmp32.b */
447*3d8817e4Smiod  /* 17 */ { 32767, -32768, 3, 18 }, /* jmp32.w */
448*3d8817e4Smiod  /* 18 */ {     0,      0, 4,  0 }, /* jmp32.a */
449*3d8817e4Smiod 
450*3d8817e4Smiod  /* 19 */ { 32767, -32768, 3, 20 }, /* jsr16.w */
451*3d8817e4Smiod  /* 20 */ {     0,      0, 4,  0 }, /* jsr16.a */
452*3d8817e4Smiod  /* 21 */ { 32767, -32768, 3, 11 }, /* jsr32.w */
453*3d8817e4Smiod  /* 22 */ {     0,      0, 4,  0 }  /* jsr32.a */
454*3d8817e4Smiod };
455*3d8817e4Smiod 
456*3d8817e4Smiod enum {
457*3d8817e4Smiod   M32C_MACRO_JCND16_5_W,
458*3d8817e4Smiod   M32C_MACRO_JCND16_5_A,
459*3d8817e4Smiod   M32C_MACRO_JCND16_W,
460*3d8817e4Smiod   M32C_MACRO_JCND16_A,
461*3d8817e4Smiod   M32C_MACRO_JCND32_W,
462*3d8817e4Smiod   M32C_MACRO_JCND32_A,
463*3d8817e4Smiod } M32C_Macros;
464*3d8817e4Smiod 
465*3d8817e4Smiod static struct {
466*3d8817e4Smiod   int insn;
467*3d8817e4Smiod   int bytes;
468*3d8817e4Smiod   int insn_for_extern;
469*3d8817e4Smiod   int pcrel_aim_offset;
470*3d8817e4Smiod } subtype_mappings[] = {
471*3d8817e4Smiod   /* 0 */ { 0, 0, 0, 0 },
472*3d8817e4Smiod   /* 1 */ { 0, 0, 0, 0 },
473*3d8817e4Smiod 
474*3d8817e4Smiod   /* 2 */ {  M32C_INSN_JCND16_5,    2, -M32C_MACRO_JCND16_5_A, 1 },
475*3d8817e4Smiod   /* 3 */ { -M32C_MACRO_JCND16_5_W, 5, -M32C_MACRO_JCND16_5_A, 4 },
476*3d8817e4Smiod   /* 4 */ { -M32C_MACRO_JCND16_5_A, 6, -M32C_MACRO_JCND16_5_A, 0 },
477*3d8817e4Smiod 
478*3d8817e4Smiod   /* 5 */ {  M32C_INSN_JCND16,      3, -M32C_MACRO_JCND16_A,   1 },
479*3d8817e4Smiod   /* 6 */ { -M32C_MACRO_JCND16_W,   6, -M32C_MACRO_JCND16_A,   4 },
480*3d8817e4Smiod   /* 7 */ { -M32C_MACRO_JCND16_A,   7, -M32C_MACRO_JCND16_A,   0 },
481*3d8817e4Smiod 
482*3d8817e4Smiod   /* 8 */ {  M32C_INSN_JMP16_S,     1, M32C_INSN_JMP16_A,     0 },
483*3d8817e4Smiod   /* 9 */ {  M32C_INSN_JMP16_B,     2, M32C_INSN_JMP16_A,     1 },
484*3d8817e4Smiod  /* 10 */ {  M32C_INSN_JMP16_W,     3, M32C_INSN_JMP16_A,     2 },
485*3d8817e4Smiod  /* 11 */ {  M32C_INSN_JMP16_A,     4, M32C_INSN_JMP16_A,     0 },
486*3d8817e4Smiod 
487*3d8817e4Smiod  /* 12 */ {  M32C_INSN_JCND32,      2, -M32C_MACRO_JCND32_A,   1 },
488*3d8817e4Smiod  /* 13 */ { -M32C_MACRO_JCND32_W,   5, -M32C_MACRO_JCND32_A,   4 },
489*3d8817e4Smiod  /* 14 */ { -M32C_MACRO_JCND32_A,   6, -M32C_MACRO_JCND32_A,   0 },
490*3d8817e4Smiod 
491*3d8817e4Smiod  /* 15 */ {  M32C_INSN_JMP32_S,     1, M32C_INSN_JMP32_A,     0 },
492*3d8817e4Smiod  /* 16 */ {  M32C_INSN_JMP32_B,     2, M32C_INSN_JMP32_A,     1 },
493*3d8817e4Smiod  /* 17 */ {  M32C_INSN_JMP32_W,     3, M32C_INSN_JMP32_A,     2 },
494*3d8817e4Smiod  /* 18 */ {  M32C_INSN_JMP32_A,     4, M32C_INSN_JMP32_A,     0 },
495*3d8817e4Smiod 
496*3d8817e4Smiod  /* 19 */ {  M32C_INSN_JSR16_W,     3, M32C_INSN_JSR16_A,     2 },
497*3d8817e4Smiod  /* 20 */ {  M32C_INSN_JSR16_A,     4, M32C_INSN_JSR16_A,     0 },
498*3d8817e4Smiod  /* 21 */ {  M32C_INSN_JSR32_W,     3, M32C_INSN_JSR32_A,     2 },
499*3d8817e4Smiod  /* 22 */ {  M32C_INSN_JSR32_A,     4, M32C_INSN_JSR32_A,     0 }
500*3d8817e4Smiod };
501*3d8817e4Smiod #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
502*3d8817e4Smiod 
503*3d8817e4Smiod void
m32c_prepare_relax_scan(fragS * fragP,offsetT * aim,relax_substateT this_state)504*3d8817e4Smiod m32c_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
505*3d8817e4Smiod {
506*3d8817e4Smiod   symbolS *symbolP = fragP->fr_symbol;
507*3d8817e4Smiod   if (symbolP && !S_IS_DEFINED (symbolP))
508*3d8817e4Smiod     *aim = 0;
509*3d8817e4Smiod   /* Adjust for m32c pcrel not being relative to the next opcode.  */
510*3d8817e4Smiod   *aim += subtype_mappings[this_state].pcrel_aim_offset;
511*3d8817e4Smiod }
512*3d8817e4Smiod 
513*3d8817e4Smiod static int
insn_to_subtype(int insn)514*3d8817e4Smiod insn_to_subtype (int insn)
515*3d8817e4Smiod {
516*3d8817e4Smiod   unsigned int i;
517*3d8817e4Smiod   for (i=0; i<NUM_MAPPINGS; i++)
518*3d8817e4Smiod     if (insn == subtype_mappings[i].insn)
519*3d8817e4Smiod       {
520*3d8817e4Smiod 	/*printf("mapping %d used\n", i);*/
521*3d8817e4Smiod 	return i;
522*3d8817e4Smiod       }
523*3d8817e4Smiod   abort ();
524*3d8817e4Smiod }
525*3d8817e4Smiod 
526*3d8817e4Smiod /* Return an initial guess of the length by which a fragment must grow to
527*3d8817e4Smiod    hold a branch to reach its destination.
528*3d8817e4Smiod    Also updates fr_type/fr_subtype as necessary.
529*3d8817e4Smiod 
530*3d8817e4Smiod    Called just before doing relaxation.
531*3d8817e4Smiod    Any symbol that is now undefined will not become defined.
532*3d8817e4Smiod    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
533*3d8817e4Smiod    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
534*3d8817e4Smiod    Although it may not be explicit in the frag, pretend fr_var starts with a
535*3d8817e4Smiod    0 value.  */
536*3d8817e4Smiod 
537*3d8817e4Smiod int
md_estimate_size_before_relax(fragS * fragP,segT segment ATTRIBUTE_UNUSED)538*3d8817e4Smiod md_estimate_size_before_relax (fragS * fragP, segT segment ATTRIBUTE_UNUSED)
539*3d8817e4Smiod {
540*3d8817e4Smiod   int where = fragP->fr_opcode - fragP->fr_literal;
541*3d8817e4Smiod 
542*3d8817e4Smiod   if (fragP->fr_subtype == 1)
543*3d8817e4Smiod     fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
544*3d8817e4Smiod 
545*3d8817e4Smiod   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
546*3d8817e4Smiod     {
547*3d8817e4Smiod       int new_insn;
548*3d8817e4Smiod 
549*3d8817e4Smiod       new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
550*3d8817e4Smiod       fragP->fr_subtype = insn_to_subtype (new_insn);
551*3d8817e4Smiod     }
552*3d8817e4Smiod 
553*3d8817e4Smiod   if (fragP->fr_cgen.insn->base
554*3d8817e4Smiod       && fragP->fr_cgen.insn->base->num
555*3d8817e4Smiod          != subtype_mappings[fragP->fr_subtype].insn
556*3d8817e4Smiod       && subtype_mappings[fragP->fr_subtype].insn > 0)
557*3d8817e4Smiod     {
558*3d8817e4Smiod       int new_insn= subtype_mappings[fragP->fr_subtype].insn;
559*3d8817e4Smiod       if (new_insn >= 0)
560*3d8817e4Smiod 	{
561*3d8817e4Smiod 	  fragP->fr_cgen.insn = (fragP->fr_cgen.insn
562*3d8817e4Smiod 				 - fragP->fr_cgen.insn->base->num
563*3d8817e4Smiod 				 + new_insn);
564*3d8817e4Smiod 	}
565*3d8817e4Smiod     }
566*3d8817e4Smiod 
567*3d8817e4Smiod   return subtype_mappings[fragP->fr_subtype].bytes - (fragP->fr_fix - where);
568*3d8817e4Smiod }
569*3d8817e4Smiod 
570*3d8817e4Smiod /* *fragP has been relaxed to its final size, and now needs to have
571*3d8817e4Smiod    the bytes inside it modified to conform to the new size.
572*3d8817e4Smiod 
573*3d8817e4Smiod    Called after relaxation is finished.
574*3d8817e4Smiod    fragP->fr_type == rs_machine_dependent.
575*3d8817e4Smiod    fragP->fr_subtype is the subtype of what the address relaxed to.  */
576*3d8817e4Smiod 
577*3d8817e4Smiod static int
target_address_for(fragS * frag)578*3d8817e4Smiod target_address_for (fragS *frag)
579*3d8817e4Smiod {
580*3d8817e4Smiod   int rv = frag->fr_offset;
581*3d8817e4Smiod   symbolS *sym = frag->fr_symbol;
582*3d8817e4Smiod 
583*3d8817e4Smiod   if (sym)
584*3d8817e4Smiod     rv += S_GET_VALUE (sym);
585*3d8817e4Smiod 
586*3d8817e4Smiod   /*printf("target_address_for returns %d\n", rv);*/
587*3d8817e4Smiod   return rv;
588*3d8817e4Smiod }
589*3d8817e4Smiod 
590*3d8817e4Smiod void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)591*3d8817e4Smiod md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
592*3d8817e4Smiod 		 segT    sec ATTRIBUTE_UNUSED,
593*3d8817e4Smiod 		 fragS * fragP ATTRIBUTE_UNUSED)
594*3d8817e4Smiod {
595*3d8817e4Smiod   int addend;
596*3d8817e4Smiod   int operand;
597*3d8817e4Smiod   int new_insn;
598*3d8817e4Smiod   int where = fragP->fr_opcode - fragP->fr_literal;
599*3d8817e4Smiod   int rl_where = fragP->fr_opcode - fragP->fr_literal;
600*3d8817e4Smiod   unsigned char *op = (unsigned char *)fragP->fr_opcode;
601*3d8817e4Smiod   int op_base = 0;
602*3d8817e4Smiod   int op_op = 0;
603*3d8817e4Smiod   int rl_addend = 0;
604*3d8817e4Smiod 
605*3d8817e4Smiod   addend = target_address_for (fragP) - (fragP->fr_address + where);
606*3d8817e4Smiod   new_insn = subtype_mappings[fragP->fr_subtype].insn;
607*3d8817e4Smiod 
608*3d8817e4Smiod   fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes;
609*3d8817e4Smiod 
610*3d8817e4Smiod   op_base = 0;
611*3d8817e4Smiod 
612*3d8817e4Smiod   switch (subtype_mappings[fragP->fr_subtype].insn)
613*3d8817e4Smiod     {
614*3d8817e4Smiod     case M32C_INSN_JCND16_5:
615*3d8817e4Smiod       op[1] = addend - 1;
616*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_8;
617*3d8817e4Smiod       op_op = 1;
618*3d8817e4Smiod       rl_addend = 0x21;
619*3d8817e4Smiod       break;
620*3d8817e4Smiod 
621*3d8817e4Smiod     case -M32C_MACRO_JCND16_5_W:
622*3d8817e4Smiod       op[0] ^= 0x04;
623*3d8817e4Smiod       op[1] = 4;
624*3d8817e4Smiod       op[2] = 0xf4;
625*3d8817e4Smiod       op[3] = addend - 3;
626*3d8817e4Smiod       op[4] = (addend - 3) >> 8;
627*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
628*3d8817e4Smiod       where += 2;
629*3d8817e4Smiod       new_insn = M32C_INSN_JMP16_W;
630*3d8817e4Smiod       op_base = 2;
631*3d8817e4Smiod       op_op = 3;
632*3d8817e4Smiod       rl_addend = 0x51;
633*3d8817e4Smiod       break;
634*3d8817e4Smiod 
635*3d8817e4Smiod     case -M32C_MACRO_JCND16_5_A:
636*3d8817e4Smiod       op[0] ^= 0x04;
637*3d8817e4Smiod       op[1] = 5;
638*3d8817e4Smiod       op[2] = 0xfc;
639*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
640*3d8817e4Smiod       where += 2;
641*3d8817e4Smiod       new_insn = M32C_INSN_JMP16_A;
642*3d8817e4Smiod       op_base = 2;
643*3d8817e4Smiod       op_op = 3;
644*3d8817e4Smiod       rl_addend = 0x61;
645*3d8817e4Smiod       break;
646*3d8817e4Smiod 
647*3d8817e4Smiod 
648*3d8817e4Smiod     case M32C_INSN_JCND16:
649*3d8817e4Smiod       op[2] = addend - 2;
650*3d8817e4Smiod       operand = M32C_OPERAND_LAB_16_8;
651*3d8817e4Smiod       op_base = 0;
652*3d8817e4Smiod       op_op = 2;
653*3d8817e4Smiod       rl_addend = 0x31;
654*3d8817e4Smiod       break;
655*3d8817e4Smiod 
656*3d8817e4Smiod     case -M32C_MACRO_JCND16_W:
657*3d8817e4Smiod       op[1] ^= 0x04;
658*3d8817e4Smiod       op[2] = 4;
659*3d8817e4Smiod       op[3] = 0xf4;
660*3d8817e4Smiod       op[4] = addend - 4;
661*3d8817e4Smiod       op[5] = (addend - 4) >> 8;
662*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
663*3d8817e4Smiod       where += 3;
664*3d8817e4Smiod       new_insn = M32C_INSN_JMP16_W;
665*3d8817e4Smiod       op_base = 3;
666*3d8817e4Smiod       op_op = 4;
667*3d8817e4Smiod       rl_addend = 0x61;
668*3d8817e4Smiod       break;
669*3d8817e4Smiod 
670*3d8817e4Smiod     case -M32C_MACRO_JCND16_A:
671*3d8817e4Smiod       op[1] ^= 0x04;
672*3d8817e4Smiod       op[2] = 5;
673*3d8817e4Smiod       op[3] = 0xfc;
674*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
675*3d8817e4Smiod       where += 3;
676*3d8817e4Smiod       new_insn = M32C_INSN_JMP16_A;
677*3d8817e4Smiod       op_base = 3;
678*3d8817e4Smiod       op_op = 4;
679*3d8817e4Smiod       rl_addend = 0x71;
680*3d8817e4Smiod       break;
681*3d8817e4Smiod 
682*3d8817e4Smiod     case M32C_INSN_JMP16_S:
683*3d8817e4Smiod       op[0] = 0x60 | ((addend-2) & 0x07);
684*3d8817e4Smiod       operand = M32C_OPERAND_LAB_5_3;
685*3d8817e4Smiod       op_base = 0;
686*3d8817e4Smiod       op_op = 0;
687*3d8817e4Smiod       rl_addend = 0x10;
688*3d8817e4Smiod       break;
689*3d8817e4Smiod 
690*3d8817e4Smiod     case M32C_INSN_JMP16_B:
691*3d8817e4Smiod       op[0] = 0xfe;
692*3d8817e4Smiod       op[1] = addend - 1;
693*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_8;
694*3d8817e4Smiod       op_base = 0;
695*3d8817e4Smiod       op_op = 1;
696*3d8817e4Smiod       rl_addend = 0x21;
697*3d8817e4Smiod       break;
698*3d8817e4Smiod 
699*3d8817e4Smiod     case M32C_INSN_JMP16_W:
700*3d8817e4Smiod       op[0] = 0xf4;
701*3d8817e4Smiod       op[1] = addend - 1;
702*3d8817e4Smiod       op[2] = (addend - 1) >> 8;
703*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
704*3d8817e4Smiod       op_base = 0;
705*3d8817e4Smiod       op_op = 1;
706*3d8817e4Smiod       rl_addend = 0x31;
707*3d8817e4Smiod       break;
708*3d8817e4Smiod 
709*3d8817e4Smiod     case M32C_INSN_JMP16_A:
710*3d8817e4Smiod       op[0] = 0xfc;
711*3d8817e4Smiod       op[1] = 0;
712*3d8817e4Smiod       op[2] = 0;
713*3d8817e4Smiod       op[3] = 0;
714*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
715*3d8817e4Smiod       op_base = 0;
716*3d8817e4Smiod       op_op = 1;
717*3d8817e4Smiod       rl_addend = 0x41;
718*3d8817e4Smiod       break;
719*3d8817e4Smiod 
720*3d8817e4Smiod     case M32C_INSN_JCND32:
721*3d8817e4Smiod       op[1] = addend - 1;
722*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_8;
723*3d8817e4Smiod       op_base = 0;
724*3d8817e4Smiod       op_op = 1;
725*3d8817e4Smiod       rl_addend = 0x21;
726*3d8817e4Smiod       break;
727*3d8817e4Smiod 
728*3d8817e4Smiod     case -M32C_MACRO_JCND32_W:
729*3d8817e4Smiod       op[0] ^= 0x40;
730*3d8817e4Smiod       op[1] = 4;
731*3d8817e4Smiod       op[2] = 0xce;
732*3d8817e4Smiod       op[3] = addend - 3;
733*3d8817e4Smiod       op[4] = (addend - 3) >> 8;
734*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
735*3d8817e4Smiod       where += 2;
736*3d8817e4Smiod       new_insn = M32C_INSN_JMP32_W;
737*3d8817e4Smiod       op_base = 2;
738*3d8817e4Smiod       op_op = 3;
739*3d8817e4Smiod       rl_addend = 0x51;
740*3d8817e4Smiod       break;
741*3d8817e4Smiod 
742*3d8817e4Smiod     case -M32C_MACRO_JCND32_A:
743*3d8817e4Smiod       op[0] ^= 0x40;
744*3d8817e4Smiod       op[1] = 5;
745*3d8817e4Smiod       op[2] = 0xcc;
746*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
747*3d8817e4Smiod       where += 2;
748*3d8817e4Smiod       new_insn = M32C_INSN_JMP32_A;
749*3d8817e4Smiod       op_base = 2;
750*3d8817e4Smiod       op_op = 3;
751*3d8817e4Smiod       rl_addend = 0x61;
752*3d8817e4Smiod       break;
753*3d8817e4Smiod 
754*3d8817e4Smiod 
755*3d8817e4Smiod 
756*3d8817e4Smiod     case M32C_INSN_JMP32_S:
757*3d8817e4Smiod       addend = ((addend-2) & 0x07);
758*3d8817e4Smiod       op[0] = 0x4a | (addend & 0x01) | ((addend << 3) & 0x30);
759*3d8817e4Smiod       operand = M32C_OPERAND_LAB32_JMP_S;
760*3d8817e4Smiod       op_base = 0;
761*3d8817e4Smiod       op_op = 0;
762*3d8817e4Smiod       rl_addend = 0x10;
763*3d8817e4Smiod       break;
764*3d8817e4Smiod 
765*3d8817e4Smiod     case M32C_INSN_JMP32_B:
766*3d8817e4Smiod       op[0] = 0xbb;
767*3d8817e4Smiod       op[1] = addend - 1;
768*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_8;
769*3d8817e4Smiod       op_base = 0;
770*3d8817e4Smiod       op_op = 1;
771*3d8817e4Smiod       rl_addend = 0x21;
772*3d8817e4Smiod       break;
773*3d8817e4Smiod 
774*3d8817e4Smiod     case M32C_INSN_JMP32_W:
775*3d8817e4Smiod       op[0] = 0xce;
776*3d8817e4Smiod       op[1] = addend - 1;
777*3d8817e4Smiod       op[2] = (addend - 1) >> 8;
778*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
779*3d8817e4Smiod       op_base = 0;
780*3d8817e4Smiod       op_op = 1;
781*3d8817e4Smiod       rl_addend = 0x31;
782*3d8817e4Smiod       break;
783*3d8817e4Smiod 
784*3d8817e4Smiod     case M32C_INSN_JMP32_A:
785*3d8817e4Smiod       op[0] = 0xcc;
786*3d8817e4Smiod       op[1] = 0;
787*3d8817e4Smiod       op[2] = 0;
788*3d8817e4Smiod       op[3] = 0;
789*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
790*3d8817e4Smiod       op_base = 0;
791*3d8817e4Smiod       op_op = 1;
792*3d8817e4Smiod       rl_addend = 0x41;
793*3d8817e4Smiod       break;
794*3d8817e4Smiod 
795*3d8817e4Smiod 
796*3d8817e4Smiod     case M32C_INSN_JSR16_W:
797*3d8817e4Smiod       op[0] = 0xf5;
798*3d8817e4Smiod       op[1] = addend - 1;
799*3d8817e4Smiod       op[2] = (addend - 1) >> 8;
800*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
801*3d8817e4Smiod       op_base = 0;
802*3d8817e4Smiod       op_op = 1;
803*3d8817e4Smiod       rl_addend = 0x31;
804*3d8817e4Smiod       break;
805*3d8817e4Smiod 
806*3d8817e4Smiod     case M32C_INSN_JSR16_A:
807*3d8817e4Smiod       op[0] = 0xfd;
808*3d8817e4Smiod       op[1] = 0;
809*3d8817e4Smiod       op[2] = 0;
810*3d8817e4Smiod       op[3] = 0;
811*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
812*3d8817e4Smiod       op_base = 0;
813*3d8817e4Smiod       op_op = 1;
814*3d8817e4Smiod       rl_addend = 0x41;
815*3d8817e4Smiod       break;
816*3d8817e4Smiod 
817*3d8817e4Smiod     case M32C_INSN_JSR32_W:
818*3d8817e4Smiod       op[0] = 0xcf;
819*3d8817e4Smiod       op[1] = addend - 1;
820*3d8817e4Smiod       op[2] = (addend - 1) >> 8;
821*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_16;
822*3d8817e4Smiod       op_base = 0;
823*3d8817e4Smiod       op_op = 1;
824*3d8817e4Smiod       rl_addend = 0x31;
825*3d8817e4Smiod       break;
826*3d8817e4Smiod 
827*3d8817e4Smiod     case M32C_INSN_JSR32_A:
828*3d8817e4Smiod       op[0] = 0xcd;
829*3d8817e4Smiod       op[1] = 0;
830*3d8817e4Smiod       op[2] = 0;
831*3d8817e4Smiod       op[3] = 0;
832*3d8817e4Smiod       operand = M32C_OPERAND_LAB_8_24;
833*3d8817e4Smiod       op_base = 0;
834*3d8817e4Smiod       op_op = 1;
835*3d8817e4Smiod       rl_addend = 0x41;
836*3d8817e4Smiod       break;
837*3d8817e4Smiod 
838*3d8817e4Smiod 
839*3d8817e4Smiod 
840*3d8817e4Smiod     default:
841*3d8817e4Smiod       printf("\nHey!  Need more opcode converters! missing: %d %s\n\n",
842*3d8817e4Smiod 	     fragP->fr_subtype,
843*3d8817e4Smiod 	     fragP->fr_cgen.insn->base->name);
844*3d8817e4Smiod       abort();
845*3d8817e4Smiod     }
846*3d8817e4Smiod 
847*3d8817e4Smiod   if (m32c_relax)
848*3d8817e4Smiod     {
849*3d8817e4Smiod       if (operand != M32C_OPERAND_LAB_8_24)
850*3d8817e4Smiod 	fragP->fr_offset = (fragP->fr_address + where);
851*3d8817e4Smiod 
852*3d8817e4Smiod       fix_new (fragP,
853*3d8817e4Smiod 	       rl_where,
854*3d8817e4Smiod 	       0, abs_section_sym, rl_addend, 0,
855*3d8817e4Smiod 	       BFD_RELOC_M32C_RL_JUMP);
856*3d8817e4Smiod     }
857*3d8817e4Smiod 
858*3d8817e4Smiod   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
859*3d8817e4Smiod       || operand == M32C_OPERAND_LAB_8_24
860*3d8817e4Smiod       || (m32c_relax && (operand != M32C_OPERAND_LAB_5_3
861*3d8817e4Smiod 			 && operand != M32C_OPERAND_LAB32_JMP_S)))
862*3d8817e4Smiod     {
863*3d8817e4Smiod       assert (fragP->fr_cgen.insn != 0);
864*3d8817e4Smiod       gas_cgen_record_fixup (fragP,
865*3d8817e4Smiod 			     where,
866*3d8817e4Smiod 			     fragP->fr_cgen.insn,
867*3d8817e4Smiod 			     (fragP->fr_fix - where) * 8,
868*3d8817e4Smiod 			     cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
869*3d8817e4Smiod 							 operand),
870*3d8817e4Smiod 			     fragP->fr_cgen.opinfo,
871*3d8817e4Smiod 			     fragP->fr_symbol, fragP->fr_offset);
872*3d8817e4Smiod     }
873*3d8817e4Smiod }
874*3d8817e4Smiod 
875*3d8817e4Smiod /* Functions concerning relocs.  */
876*3d8817e4Smiod 
877*3d8817e4Smiod /* The location from which a PC relative jump should be calculated,
878*3d8817e4Smiod    given a PC relative reloc.  */
879*3d8817e4Smiod 
880*3d8817e4Smiod long
md_pcrel_from_section(fixS * fixP,segT sec)881*3d8817e4Smiod md_pcrel_from_section (fixS * fixP, segT sec)
882*3d8817e4Smiod {
883*3d8817e4Smiod   if (fixP->fx_addsy != (symbolS *) NULL
884*3d8817e4Smiod       && (! S_IS_DEFINED (fixP->fx_addsy)
885*3d8817e4Smiod 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
886*3d8817e4Smiod     /* The symbol is undefined (or is defined but not in this section).
887*3d8817e4Smiod        Let the linker figure it out.  */
888*3d8817e4Smiod     return 0;
889*3d8817e4Smiod 
890*3d8817e4Smiod   return (fixP->fx_frag->fr_address + fixP->fx_where);
891*3d8817e4Smiod }
892*3d8817e4Smiod 
893*3d8817e4Smiod /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
894*3d8817e4Smiod    Returns BFD_RELOC_NONE if no reloc type can be found.
895*3d8817e4Smiod    *FIXP may be modified if desired.  */
896*3d8817e4Smiod 
897*3d8817e4Smiod bfd_reloc_code_real_type
md_cgen_lookup_reloc(const CGEN_INSN * insn ATTRIBUTE_UNUSED,const CGEN_OPERAND * operand,fixS * fixP ATTRIBUTE_UNUSED)898*3d8817e4Smiod md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
899*3d8817e4Smiod 		      const CGEN_OPERAND * operand,
900*3d8817e4Smiod 		      fixS *               fixP ATTRIBUTE_UNUSED)
901*3d8817e4Smiod {
902*3d8817e4Smiod   static const struct op_reloc {
903*3d8817e4Smiod     /* A CGEN operand type that can be a relocatable expression.  */
904*3d8817e4Smiod     CGEN_OPERAND_TYPE operand;
905*3d8817e4Smiod 
906*3d8817e4Smiod     /* The appropriate BFD reloc type to use for that.  */
907*3d8817e4Smiod     bfd_reloc_code_real_type reloc;
908*3d8817e4Smiod 
909*3d8817e4Smiod     /* The offset from the start of the instruction to the field to be
910*3d8817e4Smiod        relocated, in bytes.  */
911*3d8817e4Smiod     int offset;
912*3d8817e4Smiod   } op_reloc_table[] = {
913*3d8817e4Smiod 
914*3d8817e4Smiod     /* PC-REL relocs for 8-bit fields.  */
915*3d8817e4Smiod     { M32C_OPERAND_LAB_8_8,    BFD_RELOC_8_PCREL, 1 },
916*3d8817e4Smiod     { M32C_OPERAND_LAB_16_8,   BFD_RELOC_8_PCREL, 2 },
917*3d8817e4Smiod     { M32C_OPERAND_LAB_24_8,   BFD_RELOC_8_PCREL, 3 },
918*3d8817e4Smiod     { M32C_OPERAND_LAB_32_8,   BFD_RELOC_8_PCREL, 4 },
919*3d8817e4Smiod     { M32C_OPERAND_LAB_40_8,   BFD_RELOC_8_PCREL, 5 },
920*3d8817e4Smiod 
921*3d8817e4Smiod     /* PC-REL relocs for 16-bit fields.  */
922*3d8817e4Smiod     { M32C_OPERAND_LAB_8_16,   BFD_RELOC_16_PCREL, 1 },
923*3d8817e4Smiod 
924*3d8817e4Smiod     /* Absolute relocs for 8-bit fields.  */
925*3d8817e4Smiod     { M32C_OPERAND_IMM_8_QI,   BFD_RELOC_8, 1 },
926*3d8817e4Smiod     { M32C_OPERAND_IMM_16_QI,  BFD_RELOC_8, 2 },
927*3d8817e4Smiod     { M32C_OPERAND_IMM_24_QI,  BFD_RELOC_8, 3 },
928*3d8817e4Smiod     { M32C_OPERAND_IMM_32_QI,  BFD_RELOC_8, 4 },
929*3d8817e4Smiod     { M32C_OPERAND_IMM_40_QI,  BFD_RELOC_8, 5 },
930*3d8817e4Smiod     { M32C_OPERAND_IMM_48_QI,  BFD_RELOC_8, 6 },
931*3d8817e4Smiod     { M32C_OPERAND_IMM_56_QI,  BFD_RELOC_8, 7 },
932*3d8817e4Smiod     { M32C_OPERAND_DSP_8_S8,   BFD_RELOC_8, 1 },
933*3d8817e4Smiod     { M32C_OPERAND_DSP_16_S8,  BFD_RELOC_8, 2 },
934*3d8817e4Smiod     { M32C_OPERAND_DSP_24_S8,  BFD_RELOC_8, 3 },
935*3d8817e4Smiod     { M32C_OPERAND_DSP_32_S8,  BFD_RELOC_8, 4 },
936*3d8817e4Smiod     { M32C_OPERAND_DSP_40_S8,  BFD_RELOC_8, 5 },
937*3d8817e4Smiod     { M32C_OPERAND_DSP_48_S8,  BFD_RELOC_8, 6 },
938*3d8817e4Smiod     { M32C_OPERAND_DSP_8_U8,   BFD_RELOC_8, 1 },
939*3d8817e4Smiod     { M32C_OPERAND_DSP_16_U8,  BFD_RELOC_8, 2 },
940*3d8817e4Smiod     { M32C_OPERAND_DSP_24_U8,  BFD_RELOC_8, 3 },
941*3d8817e4Smiod     { M32C_OPERAND_DSP_32_U8,  BFD_RELOC_8, 4 },
942*3d8817e4Smiod     { M32C_OPERAND_DSP_40_U8,  BFD_RELOC_8, 5 },
943*3d8817e4Smiod     { M32C_OPERAND_DSP_48_U8,  BFD_RELOC_8, 6 },
944*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_16_S11_UNPREFIXED, BFD_RELOC_8, 2 },
945*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_16_U11_UNPREFIXED, BFD_RELOC_8, 2 },
946*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_24_S11_PREFIXED, BFD_RELOC_8, 3 },
947*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_24_U11_PREFIXED, BFD_RELOC_8, 3 },
948*3d8817e4Smiod 
949*3d8817e4Smiod     /* Absolute relocs for 16-bit fields.  */
950*3d8817e4Smiod     { M32C_OPERAND_IMM_8_HI,   BFD_RELOC_16, 1 },
951*3d8817e4Smiod     { M32C_OPERAND_IMM_16_HI,  BFD_RELOC_16, 2 },
952*3d8817e4Smiod     { M32C_OPERAND_IMM_24_HI,  BFD_RELOC_16, 3 },
953*3d8817e4Smiod     { M32C_OPERAND_IMM_32_HI,  BFD_RELOC_16, 4 },
954*3d8817e4Smiod     { M32C_OPERAND_IMM_40_HI,  BFD_RELOC_16, 5 },
955*3d8817e4Smiod     { M32C_OPERAND_IMM_48_HI,  BFD_RELOC_16, 6 },
956*3d8817e4Smiod     { M32C_OPERAND_IMM_56_HI,  BFD_RELOC_16, 7 },
957*3d8817e4Smiod     { M32C_OPERAND_IMM_64_HI,  BFD_RELOC_16, 8 },
958*3d8817e4Smiod     { M32C_OPERAND_DSP_16_S16, BFD_RELOC_16, 2 },
959*3d8817e4Smiod     { M32C_OPERAND_DSP_24_S16, BFD_RELOC_16, 3 },
960*3d8817e4Smiod     { M32C_OPERAND_DSP_32_S16, BFD_RELOC_16, 4 },
961*3d8817e4Smiod     { M32C_OPERAND_DSP_40_S16, BFD_RELOC_16, 5 },
962*3d8817e4Smiod     { M32C_OPERAND_DSP_8_U16,  BFD_RELOC_16, 1 },
963*3d8817e4Smiod     { M32C_OPERAND_DSP_16_U16, BFD_RELOC_16, 2 },
964*3d8817e4Smiod     { M32C_OPERAND_DSP_24_U16, BFD_RELOC_16, 3 },
965*3d8817e4Smiod     { M32C_OPERAND_DSP_32_U16, BFD_RELOC_16, 4 },
966*3d8817e4Smiod     { M32C_OPERAND_DSP_40_U16, BFD_RELOC_16, 5 },
967*3d8817e4Smiod     { M32C_OPERAND_DSP_48_U16, BFD_RELOC_16, 6 },
968*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_16_S19_UNPREFIXED, BFD_RELOC_16, 2 },
969*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_16_U19_UNPREFIXED, BFD_RELOC_16, 2 },
970*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_24_S19_PREFIXED, BFD_RELOC_16, 3 },
971*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_24_U19_PREFIXED, BFD_RELOC_16, 3 },
972*3d8817e4Smiod 
973*3d8817e4Smiod     /* Absolute relocs for 24-bit fields.  */
974*3d8817e4Smiod     { M32C_OPERAND_LAB_8_24,   BFD_RELOC_24, 1 },
975*3d8817e4Smiod     { M32C_OPERAND_DSP_8_S24,  BFD_RELOC_24, 1 },
976*3d8817e4Smiod     { M32C_OPERAND_DSP_8_U24,  BFD_RELOC_24, 1 },
977*3d8817e4Smiod     { M32C_OPERAND_DSP_16_U24, BFD_RELOC_24, 2 },
978*3d8817e4Smiod     { M32C_OPERAND_DSP_24_U24, BFD_RELOC_24, 3 },
979*3d8817e4Smiod     { M32C_OPERAND_DSP_32_U24, BFD_RELOC_24, 4 },
980*3d8817e4Smiod     { M32C_OPERAND_DSP_40_U24, BFD_RELOC_24, 5 },
981*3d8817e4Smiod     { M32C_OPERAND_DSP_48_U24, BFD_RELOC_24, 6 },
982*3d8817e4Smiod     { M32C_OPERAND_DSP_16_U20, BFD_RELOC_24, 2 },
983*3d8817e4Smiod     { M32C_OPERAND_DSP_24_U20, BFD_RELOC_24, 3 },
984*3d8817e4Smiod     { M32C_OPERAND_DSP_32_U20, BFD_RELOC_24, 4 },
985*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_16_U27_UNPREFIXED, BFD_RELOC_24, 2 },
986*3d8817e4Smiod     { M32C_OPERAND_BITBASE32_24_U27_PREFIXED, BFD_RELOC_24, 3 },
987*3d8817e4Smiod 
988*3d8817e4Smiod     /* Absolute relocs for 32-bit fields.  */
989*3d8817e4Smiod     { M32C_OPERAND_IMM_16_SI,  BFD_RELOC_32, 2 },
990*3d8817e4Smiod     { M32C_OPERAND_IMM_24_SI,  BFD_RELOC_32, 3 },
991*3d8817e4Smiod     { M32C_OPERAND_IMM_32_SI,  BFD_RELOC_32, 4 },
992*3d8817e4Smiod     { M32C_OPERAND_IMM_40_SI,  BFD_RELOC_32, 5 },
993*3d8817e4Smiod 
994*3d8817e4Smiod   };
995*3d8817e4Smiod 
996*3d8817e4Smiod   int i;
997*3d8817e4Smiod 
998*3d8817e4Smiod   for (i = ARRAY_SIZE (op_reloc_table); --i >= 0; )
999*3d8817e4Smiod     {
1000*3d8817e4Smiod       const struct op_reloc *or = &op_reloc_table[i];
1001*3d8817e4Smiod 
1002*3d8817e4Smiod       if (or->operand == operand->type)
1003*3d8817e4Smiod         {
1004*3d8817e4Smiod           fixP->fx_where += or->offset;
1005*3d8817e4Smiod           fixP->fx_size -= or->offset;
1006*3d8817e4Smiod 
1007*3d8817e4Smiod 	  if (fixP->fx_cgen.opinfo
1008*3d8817e4Smiod 	      && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
1009*3d8817e4Smiod 	    return fixP->fx_cgen.opinfo;
1010*3d8817e4Smiod 
1011*3d8817e4Smiod           return or->reloc;
1012*3d8817e4Smiod         }
1013*3d8817e4Smiod     }
1014*3d8817e4Smiod 
1015*3d8817e4Smiod   fprintf
1016*3d8817e4Smiod     (stderr,
1017*3d8817e4Smiod      "Error: tc-m32c.c:md_cgen_lookup_reloc Unimplemented relocation for operand %s\n",
1018*3d8817e4Smiod      operand->name);
1019*3d8817e4Smiod 
1020*3d8817e4Smiod   return BFD_RELOC_NONE;
1021*3d8817e4Smiod }
1022*3d8817e4Smiod 
1023*3d8817e4Smiod void
m32c_apply_fix(struct fix * f,valueT * t,segT s)1024*3d8817e4Smiod m32c_apply_fix (struct fix *f, valueT *t, segT s)
1025*3d8817e4Smiod {
1026*3d8817e4Smiod   if (f->fx_r_type == BFD_RELOC_M32C_RL_JUMP
1027*3d8817e4Smiod       || f->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
1028*3d8817e4Smiod       || f->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
1029*3d8817e4Smiod     return;
1030*3d8817e4Smiod   gas_cgen_md_apply_fix (f, t, s);
1031*3d8817e4Smiod }
1032*3d8817e4Smiod 
1033*3d8817e4Smiod arelent *
tc_gen_reloc(asection * sec,fixS * fx)1034*3d8817e4Smiod tc_gen_reloc (asection *sec, fixS *fx)
1035*3d8817e4Smiod {
1036*3d8817e4Smiod   if (fx->fx_r_type == BFD_RELOC_M32C_RL_JUMP
1037*3d8817e4Smiod       || fx->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
1038*3d8817e4Smiod       || fx->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
1039*3d8817e4Smiod     {
1040*3d8817e4Smiod       arelent * reloc;
1041*3d8817e4Smiod 
1042*3d8817e4Smiod       reloc = xmalloc (sizeof (* reloc));
1043*3d8817e4Smiod 
1044*3d8817e4Smiod       reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1045*3d8817e4Smiod       *reloc->sym_ptr_ptr = symbol_get_bfdsym (fx->fx_addsy);
1046*3d8817e4Smiod       reloc->address = fx->fx_frag->fr_address + fx->fx_where;
1047*3d8817e4Smiod       reloc->howto = bfd_reloc_type_lookup (stdoutput, fx->fx_r_type);
1048*3d8817e4Smiod       reloc->addend = fx->fx_offset;
1049*3d8817e4Smiod       return reloc;
1050*3d8817e4Smiod 
1051*3d8817e4Smiod     }
1052*3d8817e4Smiod   return gas_cgen_tc_gen_reloc (sec, fx);
1053*3d8817e4Smiod }
1054*3d8817e4Smiod 
1055*3d8817e4Smiod /* See whether we need to force a relocation into the output file.
1056*3d8817e4Smiod    This is used to force out switch and PC relative relocations when
1057*3d8817e4Smiod    relaxing.  */
1058*3d8817e4Smiod 
1059*3d8817e4Smiod int
m32c_force_relocation(fixS * fixp)1060*3d8817e4Smiod m32c_force_relocation (fixS * fixp)
1061*3d8817e4Smiod {
1062*3d8817e4Smiod   int reloc = fixp->fx_r_type;
1063*3d8817e4Smiod 
1064*3d8817e4Smiod   if (reloc > (int)BFD_RELOC_UNUSED)
1065*3d8817e4Smiod     {
1066*3d8817e4Smiod       reloc -= (int)BFD_RELOC_UNUSED;
1067*3d8817e4Smiod       switch (reloc)
1068*3d8817e4Smiod 	{
1069*3d8817e4Smiod 	case M32C_OPERAND_DSP_32_S16:
1070*3d8817e4Smiod 	case M32C_OPERAND_DSP_32_U16:
1071*3d8817e4Smiod 	case M32C_OPERAND_IMM_32_HI:
1072*3d8817e4Smiod 	case M32C_OPERAND_DSP_16_S16:
1073*3d8817e4Smiod 	case M32C_OPERAND_DSP_16_U16:
1074*3d8817e4Smiod 	case M32C_OPERAND_IMM_16_HI:
1075*3d8817e4Smiod 	case M32C_OPERAND_DSP_24_S16:
1076*3d8817e4Smiod 	case M32C_OPERAND_DSP_24_U16:
1077*3d8817e4Smiod 	case M32C_OPERAND_IMM_24_HI:
1078*3d8817e4Smiod 	  return 1;
1079*3d8817e4Smiod 
1080*3d8817e4Smiod         /* If we're doing linker relaxing, we need to keep all the
1081*3d8817e4Smiod 	   pc-relative jumps in case we need to fix them due to
1082*3d8817e4Smiod 	   deleted bytes between the jump and its destination.  */
1083*3d8817e4Smiod 	case M32C_OPERAND_LAB_8_8:
1084*3d8817e4Smiod 	case M32C_OPERAND_LAB_8_16:
1085*3d8817e4Smiod 	case M32C_OPERAND_LAB_8_24:
1086*3d8817e4Smiod 	case M32C_OPERAND_LAB_16_8:
1087*3d8817e4Smiod 	case M32C_OPERAND_LAB_24_8:
1088*3d8817e4Smiod 	case M32C_OPERAND_LAB_32_8:
1089*3d8817e4Smiod 	case M32C_OPERAND_LAB_40_8:
1090*3d8817e4Smiod 	  if (m32c_relax)
1091*3d8817e4Smiod 	    return 1;
1092*3d8817e4Smiod 	default:
1093*3d8817e4Smiod 	  break;
1094*3d8817e4Smiod 	}
1095*3d8817e4Smiod     }
1096*3d8817e4Smiod   else
1097*3d8817e4Smiod     {
1098*3d8817e4Smiod       switch (fixp->fx_r_type)
1099*3d8817e4Smiod 	{
1100*3d8817e4Smiod 	case BFD_RELOC_16:
1101*3d8817e4Smiod 	  return 1;
1102*3d8817e4Smiod 
1103*3d8817e4Smiod 	case BFD_RELOC_M32C_RL_JUMP:
1104*3d8817e4Smiod 	case BFD_RELOC_M32C_RL_1ADDR:
1105*3d8817e4Smiod 	case BFD_RELOC_M32C_RL_2ADDR:
1106*3d8817e4Smiod 	case BFD_RELOC_8_PCREL:
1107*3d8817e4Smiod 	case BFD_RELOC_16_PCREL:
1108*3d8817e4Smiod 	  if (m32c_relax)
1109*3d8817e4Smiod 	    return 1;
1110*3d8817e4Smiod 	default:
1111*3d8817e4Smiod 	  break;
1112*3d8817e4Smiod 	}
1113*3d8817e4Smiod     }
1114*3d8817e4Smiod 
1115*3d8817e4Smiod   return generic_force_reloc (fixp);
1116*3d8817e4Smiod }
1117*3d8817e4Smiod 
1118*3d8817e4Smiod /* Write a value out to the object file, using the appropriate endianness.  */
1119*3d8817e4Smiod 
1120*3d8817e4Smiod void
md_number_to_chars(char * buf,valueT val,int n)1121*3d8817e4Smiod md_number_to_chars (char * buf, valueT val, int n)
1122*3d8817e4Smiod {
1123*3d8817e4Smiod   number_to_chars_littleendian (buf, val, n);
1124*3d8817e4Smiod }
1125*3d8817e4Smiod 
1126*3d8817e4Smiod /* Turn a string in input_line_pointer into a floating point constant of type
1127*3d8817e4Smiod    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
1128*3d8817e4Smiod    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.  */
1129*3d8817e4Smiod 
1130*3d8817e4Smiod /* Equal to MAX_PRECISION in atof-ieee.c.  */
1131*3d8817e4Smiod #define MAX_LITTLENUMS 6
1132*3d8817e4Smiod 
1133*3d8817e4Smiod char *
md_atof(int type,char * litP,int * sizeP)1134*3d8817e4Smiod md_atof (int type, char * litP, int * sizeP)
1135*3d8817e4Smiod {
1136*3d8817e4Smiod   int              i;
1137*3d8817e4Smiod   int              prec;
1138*3d8817e4Smiod   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
1139*3d8817e4Smiod   char *           t;
1140*3d8817e4Smiod 
1141*3d8817e4Smiod   switch (type)
1142*3d8817e4Smiod     {
1143*3d8817e4Smiod     case 'f':
1144*3d8817e4Smiod     case 'F':
1145*3d8817e4Smiod     case 's':
1146*3d8817e4Smiod     case 'S':
1147*3d8817e4Smiod       prec = 2;
1148*3d8817e4Smiod       break;
1149*3d8817e4Smiod 
1150*3d8817e4Smiod     case 'd':
1151*3d8817e4Smiod     case 'D':
1152*3d8817e4Smiod     case 'r':
1153*3d8817e4Smiod     case 'R':
1154*3d8817e4Smiod       prec = 4;
1155*3d8817e4Smiod       break;
1156*3d8817e4Smiod 
1157*3d8817e4Smiod    /* FIXME: Some targets allow other format chars for bigger sizes here.  */
1158*3d8817e4Smiod 
1159*3d8817e4Smiod     default:
1160*3d8817e4Smiod       * sizeP = 0;
1161*3d8817e4Smiod       return _("Bad call to md_atof()");
1162*3d8817e4Smiod     }
1163*3d8817e4Smiod 
1164*3d8817e4Smiod   t = atof_ieee (input_line_pointer, type, words);
1165*3d8817e4Smiod   if (t)
1166*3d8817e4Smiod     input_line_pointer = t;
1167*3d8817e4Smiod   * sizeP = prec * sizeof (LITTLENUM_TYPE);
1168*3d8817e4Smiod 
1169*3d8817e4Smiod   for (i = 0; i < prec; i++)
1170*3d8817e4Smiod     {
1171*3d8817e4Smiod       md_number_to_chars (litP, (valueT) words[i],
1172*3d8817e4Smiod 			  sizeof (LITTLENUM_TYPE));
1173*3d8817e4Smiod       litP += sizeof (LITTLENUM_TYPE);
1174*3d8817e4Smiod     }
1175*3d8817e4Smiod 
1176*3d8817e4Smiod   return 0;
1177*3d8817e4Smiod }
1178*3d8817e4Smiod 
1179*3d8817e4Smiod bfd_boolean
m32c_fix_adjustable(fixS * fixP)1180*3d8817e4Smiod m32c_fix_adjustable (fixS * fixP)
1181*3d8817e4Smiod {
1182*3d8817e4Smiod   int reloc;
1183*3d8817e4Smiod   if (fixP->fx_addsy == NULL)
1184*3d8817e4Smiod     return 1;
1185*3d8817e4Smiod 
1186*3d8817e4Smiod   /* We need the symbol name for the VTABLE entries.  */
1187*3d8817e4Smiod   reloc = fixP->fx_r_type;
1188*3d8817e4Smiod   if (reloc > (int)BFD_RELOC_UNUSED)
1189*3d8817e4Smiod     {
1190*3d8817e4Smiod       reloc -= (int)BFD_RELOC_UNUSED;
1191*3d8817e4Smiod       switch (reloc)
1192*3d8817e4Smiod 	{
1193*3d8817e4Smiod 	case M32C_OPERAND_DSP_32_S16:
1194*3d8817e4Smiod 	case M32C_OPERAND_DSP_32_U16:
1195*3d8817e4Smiod 	case M32C_OPERAND_IMM_32_HI:
1196*3d8817e4Smiod 	case M32C_OPERAND_DSP_16_S16:
1197*3d8817e4Smiod 	case M32C_OPERAND_DSP_16_U16:
1198*3d8817e4Smiod 	case M32C_OPERAND_IMM_16_HI:
1199*3d8817e4Smiod 	case M32C_OPERAND_DSP_24_S16:
1200*3d8817e4Smiod 	case M32C_OPERAND_DSP_24_U16:
1201*3d8817e4Smiod 	case M32C_OPERAND_IMM_24_HI:
1202*3d8817e4Smiod 	  return 0;
1203*3d8817e4Smiod 	}
1204*3d8817e4Smiod     }
1205*3d8817e4Smiod   else
1206*3d8817e4Smiod     {
1207*3d8817e4Smiod       if (fixP->fx_r_type == BFD_RELOC_16)
1208*3d8817e4Smiod 	return 0;
1209*3d8817e4Smiod     }
1210*3d8817e4Smiod 
1211*3d8817e4Smiod   /* Do not adjust relocations involving symbols in merged sections.
1212*3d8817e4Smiod 
1213*3d8817e4Smiod      A reloc patching in the value of some symbol S plus some addend A
1214*3d8817e4Smiod      can be produced in different ways:
1215*3d8817e4Smiod 
1216*3d8817e4Smiod      1) It might simply be a reference to the data at S + A.  Clearly,
1217*3d8817e4Smiod         if linker merging shift that data around, the value patched in
1218*3d8817e4Smiod         by the reloc needs to be adjusted accordingly.
1219*3d8817e4Smiod 
1220*3d8817e4Smiod      2) Or, it might be a reference to S, with A added in as a constant
1221*3d8817e4Smiod 	bias.  For example, given code like this:
1222*3d8817e4Smiod 
1223*3d8817e4Smiod 	  static int S[100];
1224*3d8817e4Smiod 
1225*3d8817e4Smiod 	  ... S[i - 8] ...
1226*3d8817e4Smiod 
1227*3d8817e4Smiod 	it would be reasonable for the compiler to rearrange the array
1228*3d8817e4Smiod 	reference to something like:
1229*3d8817e4Smiod 
1230*3d8817e4Smiod 	  ... (S-8)[i] ...
1231*3d8817e4Smiod 
1232*3d8817e4Smiod 	and emit assembly code that refers to S - (8 * sizeof (int)),
1233*3d8817e4Smiod 	so the subtraction is done entirely at compile-time.  In this
1234*3d8817e4Smiod 	case, the reloc's addend A would be -(8 * sizeof (int)), and
1235*3d8817e4Smiod 	shifting around code or data at S + A should not affect the
1236*3d8817e4Smiod 	reloc: the reloc isn't referring to that code or data at all.
1237*3d8817e4Smiod 
1238*3d8817e4Smiod      The linker has no way of knowing which case it has in hand.  So,
1239*3d8817e4Smiod      to disambiguate, we have the linker always treat reloc addends as
1240*3d8817e4Smiod      in case 2): they're constants that should be simply added to the
1241*3d8817e4Smiod      symbol value, just like the reloc says.  And we express case 1)
1242*3d8817e4Smiod      in different way: we have the compiler place a label at the real
1243*3d8817e4Smiod      target, and reference that label with an addend of zero.  (The
1244*3d8817e4Smiod      compiler is unlikely to reference code using a label plus an
1245*3d8817e4Smiod      offset anyway, since it doesn't know the sizes of the
1246*3d8817e4Smiod      instructions.)
1247*3d8817e4Smiod 
1248*3d8817e4Smiod      The simplification being done by gas/write.c:adjust_reloc_syms,
1249*3d8817e4Smiod      however, turns the explicit-label usage into the label-plus-
1250*3d8817e4Smiod      offset usage, re-introducing the ambiguity the compiler avoided.
1251*3d8817e4Smiod      So we need to disable that simplification for symbols referring
1252*3d8817e4Smiod      to merged data.
1253*3d8817e4Smiod 
1254*3d8817e4Smiod      This only affects object size a little bit.  */
1255*3d8817e4Smiod   if (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE)
1256*3d8817e4Smiod     return 0;
1257*3d8817e4Smiod 
1258*3d8817e4Smiod   if (m32c_relax)
1259*3d8817e4Smiod     return 0;
1260*3d8817e4Smiod 
1261*3d8817e4Smiod   return 1;
1262*3d8817e4Smiod }
1263*3d8817e4Smiod 
1264*3d8817e4Smiod /* Worker function for m32c_is_colon_insn().  */
1265*3d8817e4Smiod static char restore_colon PARAMS ((int));
1266*3d8817e4Smiod 
1267*3d8817e4Smiod static char
restore_colon(int advance_i_l_p_by)1268*3d8817e4Smiod restore_colon (int advance_i_l_p_by)
1269*3d8817e4Smiod {
1270*3d8817e4Smiod   char c;
1271*3d8817e4Smiod 
1272*3d8817e4Smiod   /* Restore the colon, and advance input_line_pointer to
1273*3d8817e4Smiod      the end of the new symbol.  */
1274*3d8817e4Smiod   * input_line_pointer = ':';
1275*3d8817e4Smiod   input_line_pointer += advance_i_l_p_by;
1276*3d8817e4Smiod   c = * input_line_pointer;
1277*3d8817e4Smiod   * input_line_pointer = 0;
1278*3d8817e4Smiod 
1279*3d8817e4Smiod   return c;
1280*3d8817e4Smiod }
1281*3d8817e4Smiod 
1282*3d8817e4Smiod /* Determines if the symbol starting at START and ending in
1283*3d8817e4Smiod    a colon that was at the location pointed to by INPUT_LINE_POINTER
1284*3d8817e4Smiod    (but which has now been replaced bu a NUL) is in fact an
1285*3d8817e4Smiod    :Z, :S, :Q, or :G suffix.
1286*3d8817e4Smiod    If it is, then it restores the colon, advances INPUT_LINE_POINTER
1287*3d8817e4Smiod    to the real end of the instruction/symbol, and returns the character
1288*3d8817e4Smiod    that really terminated the symbol.  Otherwise it returns 0.  */
1289*3d8817e4Smiod char
m32c_is_colon_insn(char * start ATTRIBUTE_UNUSED)1290*3d8817e4Smiod m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED)
1291*3d8817e4Smiod {
1292*3d8817e4Smiod   char * i_l_p = input_line_pointer;
1293*3d8817e4Smiod 
1294*3d8817e4Smiod   /* Check to see if the text following the colon is 'G' */
1295*3d8817e4Smiod   if (TOLOWER (i_l_p[1]) == 'g' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
1296*3d8817e4Smiod     return restore_colon (2);
1297*3d8817e4Smiod 
1298*3d8817e4Smiod   /* Check to see if the text following the colon is 'Q' */
1299*3d8817e4Smiod   if (TOLOWER (i_l_p[1]) == 'q' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
1300*3d8817e4Smiod     return restore_colon (2);
1301*3d8817e4Smiod 
1302*3d8817e4Smiod   /* Check to see if the text following the colon is 'S' */
1303*3d8817e4Smiod   if (TOLOWER (i_l_p[1]) == 's' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
1304*3d8817e4Smiod     return restore_colon (2);
1305*3d8817e4Smiod 
1306*3d8817e4Smiod   /* Check to see if the text following the colon is 'Z' */
1307*3d8817e4Smiod   if (TOLOWER (i_l_p[1]) == 'z' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
1308*3d8817e4Smiod     return restore_colon (2);
1309*3d8817e4Smiod 
1310*3d8817e4Smiod   return 0;
1311*3d8817e4Smiod }
1312