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