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