12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295 |
- /* tc-m32c.c -- Assembler for the Renesas M32C.
- Copyright (C) 2005-2015 Free Software Foundation, Inc.
- Contributed by RedHat.
- This file is part of GAS, the GNU Assembler.
- GAS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GAS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
- #include "as.h"
- #include "subsegs.h"
- #include "symcat.h"
- #include "opcodes/m32c-desc.h"
- #include "opcodes/m32c-opc.h"
- #include "cgen.h"
- #include "elf/common.h"
- #include "elf/m32c.h"
- #include "libbfd.h"
- #include "safe-ctype.h"
- /* Structure to hold all of the different components
- describing an individual instruction. */
- typedef struct
- {
- const CGEN_INSN * insn;
- const CGEN_INSN * orig_insn;
- CGEN_FIELDS fields;
- #if CGEN_INT_INSN_P
- CGEN_INSN_INT buffer [1];
- #define INSN_VALUE(buf) (*(buf))
- #else
- unsigned char buffer [CGEN_MAX_INSN_SIZE];
- #define INSN_VALUE(buf) (buf)
- #endif
- char * addr;
- fragS * frag;
- int num_fixups;
- fixS * fixups [GAS_CGEN_MAX_FIXUPS];
- int indices [MAX_OPERAND_INSTANCES];
- }
- m32c_insn;
- #define rl_for(_insn) (CGEN_ATTR_CGEN_INSN_RL_TYPE_VALUE (&((_insn).insn->base->attrs)))
- #define relaxable(_insn) (CGEN_ATTR_CGEN_INSN_RELAXABLE_VALUE (&((_insn).insn->base->attrs)))
- const char comment_chars[] = ";";
- const char line_comment_chars[] = "#";
- const char line_separator_chars[] = "|";
- const char EXP_CHARS[] = "eE";
- const char FLT_CHARS[] = "dD";
- #define M32C_SHORTOPTS ""
- const char * md_shortopts = M32C_SHORTOPTS;
- /* assembler options */
- #define OPTION_CPU_M16C (OPTION_MD_BASE)
- #define OPTION_CPU_M32C (OPTION_MD_BASE + 1)
- #define OPTION_LINKRELAX (OPTION_MD_BASE + 2)
- #define OPTION_H_TICK_HEX (OPTION_MD_BASE + 3)
- struct option md_longopts[] =
- {
- { "m16c", no_argument, NULL, OPTION_CPU_M16C },
- { "m32c", no_argument, NULL, OPTION_CPU_M32C },
- { "relax", no_argument, NULL, OPTION_LINKRELAX },
- { "h-tick-hex", no_argument, NULL, OPTION_H_TICK_HEX },
- {NULL, no_argument, NULL, 0}
- };
- size_t md_longopts_size = sizeof (md_longopts);
- /* Default machine */
- #define DEFAULT_MACHINE bfd_mach_m16c
- #define DEFAULT_FLAGS EF_M32C_CPU_M16C
- static unsigned long m32c_mach = bfd_mach_m16c;
- static int cpu_mach = (1 << MACH_M16C);
- static int insn_size;
- static int m32c_relax = 0;
- /* Flags to set in the elf header */
- static flagword m32c_flags = DEFAULT_FLAGS;
- static char default_isa = 1 << (7 - ISA_M16C);
- static CGEN_BITSET m32c_isa = {1, & default_isa};
- static void
- set_isa (enum isa_attr isa_num)
- {
- cgen_bitset_set (& m32c_isa, isa_num);
- }
- static void s_bss (int);
- int
- md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
- {
- switch (c)
- {
- case OPTION_CPU_M16C:
- m32c_flags = (m32c_flags & ~EF_M32C_CPU_MASK) | EF_M32C_CPU_M16C;
- m32c_mach = bfd_mach_m16c;
- cpu_mach = (1 << MACH_M16C);
- set_isa (ISA_M16C);
- break;
- case OPTION_CPU_M32C:
- m32c_flags = (m32c_flags & ~EF_M32C_CPU_MASK) | EF_M32C_CPU_M32C;
- m32c_mach = bfd_mach_m32c;
- cpu_mach = (1 << MACH_M32C);
- set_isa (ISA_M32C);
- break;
- case OPTION_LINKRELAX:
- m32c_relax = 1;
- break;
- case OPTION_H_TICK_HEX:
- enable_h_tick_hex = 1;
- break;
- default:
- return 0;
- }
- return 1;
- }
- void
- md_show_usage (FILE * stream)
- {
- fprintf (stream, _(" M32C specific command line options:\n"));
- }
- static void
- s_bss (int ignore ATTRIBUTE_UNUSED)
- {
- int temp;
- temp = get_absolute_expression ();
- subseg_set (bss_section, (subsegT) temp);
- demand_empty_rest_of_line ();
- }
- /* The target specific pseudo-ops which we support. */
- const pseudo_typeS md_pseudo_table[] =
- {
- { "bss", s_bss, 0},
- { "3byte", cons, 3 },
- { "word", cons, 4 },
- { NULL, NULL, 0 }
- };
- void
- md_begin (void)
- {
- /* Initialize the `cgen' interface. */
- /* Set the machine number and endian. */
- gas_cgen_cpu_desc = m32c_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
- CGEN_CPU_OPEN_ENDIAN,
- CGEN_ENDIAN_BIG,
- CGEN_CPU_OPEN_ISAS, & m32c_isa,
- CGEN_CPU_OPEN_END);
- m32c_cgen_init_asm (gas_cgen_cpu_desc);
- /* This is a callback from cgen to gas to parse operands. */
- cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
- /* Set the ELF flags if desired. */
- if (m32c_flags)
- bfd_set_private_flags (stdoutput, m32c_flags);
- /* Set the machine type */
- bfd_default_set_arch_mach (stdoutput, bfd_arch_m32c, m32c_mach);
- insn_size = 0;
- }
- void
- m32c_md_end (void)
- {
- int i, n_nops;
- if (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)
- {
- /* Pad with nops for objdump. */
- n_nops = (32 - ((insn_size) % 32)) / 8;
- for (i = 1; i <= n_nops; i++)
- md_assemble ("nop");
- }
- }
- void
- m32c_start_line_hook (void)
- {
- #if 0 /* not necessary....handled in the .cpu file */
- char *s = input_line_pointer;
- char *sg;
- for (s = input_line_pointer ; s && s[0] != '\n'; s++)
- {
- if (s[0] == ':')
- {
- /* Remove :g suffix. Squeeze out blanks. */
- if (s[1] == 'g')
- {
- for (sg = s - 1; sg && sg >= input_line_pointer; sg--)
- {
- sg[2] = sg[0];
- }
- sg[1] = ' ';
- sg[2] = ' ';
- input_line_pointer += 2;
- }
- }
- }
- #endif
- }
- /* Process [[indirect-operands]] in instruction str. */
- static bfd_boolean
- m32c_indirect_operand (char *str)
- {
- char *new_str;
- char *s;
- char *ns;
- int ns_len;
- char *ns_end;
- enum indirect_type {none, relative, absolute} ;
- enum indirect_type indirection [3] = { none, none, none };
- int brace_n [3] = { 0, 0, 0 };
- int operand;
- s = str;
- operand = 1;
- for (s = str; *s; s++)
- {
- if (s[0] == ',')
- operand = 2;
- /* [abs] where abs is not a0 or a1 */
- if (s[1] == '[' && ! (s[2] == 'a' && (s[3] == '0' || s[3] == '1'))
- && (ISBLANK (s[0]) || s[0] == ','))
- indirection[operand] = absolute;
- if (s[0] == ']' && s[1] == ']')
- indirection[operand] = relative;
- if (s[0] == '[' && s[1] == '[')
- indirection[operand] = relative;
- }
- if (indirection[1] == none && indirection[2] == none)
- return FALSE;
- operand = 1;
- ns_len = strlen (str);
- new_str = (char*) xmalloc (ns_len);
- ns = new_str;
- ns_end = ns + ns_len;
- for (s = str; *s; s++)
- {
- if (s[0] == ',')
- operand = 2;
- if (s[0] == '[' && ! brace_n[operand])
- {
- brace_n[operand] += 1;
- /* Squeeze [[ to [ if this is an indirect operand. */
- if (indirection[operand] != none)
- continue;
- }
- else if (s[0] == '[' && brace_n[operand])
- {
- brace_n[operand] += 1;
- }
- else if (s[0] == ']' && s[1] == ']' && indirection[operand] == relative)
- {
- s += 1; /* skip one ]. */
- brace_n[operand] -= 2; /* allow for 2 [. */
- }
- else if (s[0] == ']' && indirection[operand] == absolute)
- {
- brace_n[operand] -= 1;
- continue; /* skip closing ]. */
- }
- else if (s[0] == ']')
- {
- brace_n[operand] -= 1;
- }
- *ns = s[0];
- ns += 1;
- if (ns >= ns_end)
- return FALSE;
- if (s[0] == 0)
- break;
- }
- *ns = '\0';
- for (operand = 1; operand <= 2; operand++)
- if (brace_n[operand])
- {
- fprintf (stderr, "Unmatched [[operand-%d]] %d\n", operand, brace_n[operand]);
- }
- if (indirection[1] != none && indirection[2] != none)
- md_assemble ("src-dest-indirect");
- else if (indirection[1] != none)
- md_assemble ("src-indirect");
- else if (indirection[2] != none)
- md_assemble ("dest-indirect");
- md_assemble (new_str);
- free (new_str);
- return TRUE;
- }
- void
- md_assemble (char * str)
- {
- static int last_insn_had_delay_slot = 0;
- m32c_insn insn;
- char * errmsg;
- finished_insnS results;
- int rl_type;
- if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str))
- return;
- /* Initialize GAS's cgen interface for a new instruction. */
- gas_cgen_init_parse ();
- insn.insn = m32c_cgen_assemble_insn
- (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
- if (!insn.insn)
- {
- as_bad ("%s", errmsg);
- return;
- }
- results.num_fixups = 0;
- /* Doesn't really matter what we pass for RELAX_P here. */
- gas_cgen_finish_insn (insn.insn, insn.buffer,
- CGEN_FIELDS_BITSIZE (& insn.fields), 1, &results);
- last_insn_had_delay_slot
- = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
- (void) last_insn_had_delay_slot;
- insn_size = CGEN_INSN_BITSIZE(insn.insn);
- rl_type = rl_for (insn);
- /* We have to mark all the jumps, because we need to adjust them
- when we delete bytes, but we only need to mark the displacements
- if they're symbolic - if they're not, we've already picked the
- shortest opcode by now. The linker, however, will still have to
- check any operands to see if they're the displacement type, since
- we don't know (nor record) *which* operands are relaxable. */
- if (m32c_relax
- && rl_type != RL_TYPE_NONE
- && (rl_type == RL_TYPE_JUMP || results.num_fixups)
- && !relaxable (insn))
- {
- int reloc = 0;
- int addend = results.num_fixups + 16 * insn_size/8;
- switch (rl_for (insn))
- {
- case RL_TYPE_JUMP: reloc = BFD_RELOC_M32C_RL_JUMP; break;
- case RL_TYPE_1ADDR: reloc = BFD_RELOC_M32C_RL_1ADDR; break;
- case RL_TYPE_2ADDR: reloc = BFD_RELOC_M32C_RL_2ADDR; break;
- }
- if (insn.insn->base->num == M32C_INSN_JMP16_S
- || insn.insn->base->num == M32C_INSN_JMP32_S)
- addend = 0x10;
- fix_new (results.frag,
- results.addr - results.frag->fr_literal,
- 0, abs_section_sym, addend, 0,
- reloc);
- }
- }
- /* The syntax in the manual says constants begin with '#'.
- We just ignore it. */
- void
- md_operand (expressionS * exp)
- {
- /* In case of a syntax error, escape back to try next syntax combo. */
- if (exp->X_op == O_absent)
- gas_cgen_md_operand (exp);
- }
- valueT
- md_section_align (segT segment, valueT size)
- {
- int align = bfd_get_section_alignment (stdoutput, segment);
- return ((size + (1 << align) - 1) & (-1 << align));
- }
- symbolS *
- md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
- {
- return 0;
- }
- const relax_typeS md_relax_table[] =
- {
- /* The fields are:
- 1) most positive reach of this state,
- 2) most negative reach of this state,
- 3) how many bytes this mode will have in the variable part of the frag
- 4) which index into the table to try if we can't fit into this one. */
- /* 0 */ { 0, 0, 0, 0 }, /* unused */
- /* 1 */ { 0, 0, 0, 0 }, /* marker for "don't know yet" */
- /* 2 */ { 127, -128, 2, 3 }, /* jcnd16_5.b */
- /* 3 */ { 32767, -32768, 5, 4 }, /* jcnd16_5.w */
- /* 4 */ { 0, 0, 6, 0 }, /* jcnd16_5.a */
- /* 5 */ { 127, -128, 2, 6 }, /* jcnd16.b */
- /* 6 */ { 32767, -32768, 5, 7 }, /* jcnd16.w */
- /* 7 */ { 0, 0, 6, 0 }, /* jcnd16.a */
- /* 8 */ { 8, 1, 1, 9 }, /* jmp16.s */
- /* 9 */ { 127, -128, 2, 10 }, /* jmp16.b */
- /* 10 */ { 32767, -32768, 3, 11 }, /* jmp16.w */
- /* 11 */ { 0, 0, 4, 0 }, /* jmp16.a */
- /* 12 */ { 127, -128, 2, 13 }, /* jcnd32.b */
- /* 13 */ { 32767, -32768, 5, 14 }, /* jcnd32.w */
- /* 14 */ { 0, 0, 6, 0 }, /* jcnd32.a */
- /* 15 */ { 8, 1, 1, 16 }, /* jmp32.s */
- /* 16 */ { 127, -128, 2, 17 }, /* jmp32.b */
- /* 17 */ { 32767, -32768, 3, 18 }, /* jmp32.w */
- /* 18 */ { 0, 0, 4, 0 }, /* jmp32.a */
- /* 19 */ { 32767, -32768, 3, 20 }, /* jsr16.w */
- /* 20 */ { 0, 0, 4, 0 }, /* jsr16.a */
- /* 21 */ { 32767, -32768, 3, 11 }, /* jsr32.w */
- /* 22 */ { 0, 0, 4, 0 }, /* jsr32.a */
- /* 23 */ { 0, 0, 3, 0 }, /* adjnz pc8 */
- /* 24 */ { 0, 0, 4, 0 }, /* adjnz disp8 pc8 */
- /* 25 */ { 0, 0, 5, 0 }, /* adjnz disp16 pc8 */
- /* 26 */ { 0, 0, 6, 0 } /* adjnz disp24 pc8 */
- };
- enum {
- M32C_MACRO_JCND16_5_W,
- M32C_MACRO_JCND16_5_A,
- M32C_MACRO_JCND16_W,
- M32C_MACRO_JCND16_A,
- M32C_MACRO_JCND32_W,
- M32C_MACRO_JCND32_A,
- /* the digit is the array index of the pcrel byte */
- M32C_MACRO_ADJNZ_2,
- M32C_MACRO_ADJNZ_3,
- M32C_MACRO_ADJNZ_4,
- M32C_MACRO_ADJNZ_5,
- } M32C_Macros;
- static struct {
- int insn;
- int bytes;
- int insn_for_extern;
- int pcrel_aim_offset;
- } subtype_mappings[] = {
- /* 0 */ { 0, 0, 0, 0 },
- /* 1 */ { 0, 0, 0, 0 },
- /* 2 */ { M32C_INSN_JCND16_5, 2, -M32C_MACRO_JCND16_5_A, 1 },
- /* 3 */ { -M32C_MACRO_JCND16_5_W, 5, -M32C_MACRO_JCND16_5_A, 4 },
- /* 4 */ { -M32C_MACRO_JCND16_5_A, 6, -M32C_MACRO_JCND16_5_A, 0 },
- /* 5 */ { M32C_INSN_JCND16, 3, -M32C_MACRO_JCND16_A, 1 },
- /* 6 */ { -M32C_MACRO_JCND16_W, 6, -M32C_MACRO_JCND16_A, 4 },
- /* 7 */ { -M32C_MACRO_JCND16_A, 7, -M32C_MACRO_JCND16_A, 0 },
- /* 8 */ { M32C_INSN_JMP16_S, 1, M32C_INSN_JMP16_A, 0 },
- /* 9 */ { M32C_INSN_JMP16_B, 2, M32C_INSN_JMP16_A, 1 },
- /* 10 */ { M32C_INSN_JMP16_W, 3, M32C_INSN_JMP16_A, 2 },
- /* 11 */ { M32C_INSN_JMP16_A, 4, M32C_INSN_JMP16_A, 0 },
- /* 12 */ { M32C_INSN_JCND32, 2, -M32C_MACRO_JCND32_A, 1 },
- /* 13 */ { -M32C_MACRO_JCND32_W, 5, -M32C_MACRO_JCND32_A, 4 },
- /* 14 */ { -M32C_MACRO_JCND32_A, 6, -M32C_MACRO_JCND32_A, 0 },
- /* 15 */ { M32C_INSN_JMP32_S, 1, M32C_INSN_JMP32_A, 0 },
- /* 16 */ { M32C_INSN_JMP32_B, 2, M32C_INSN_JMP32_A, 1 },
- /* 17 */ { M32C_INSN_JMP32_W, 3, M32C_INSN_JMP32_A, 2 },
- /* 18 */ { M32C_INSN_JMP32_A, 4, M32C_INSN_JMP32_A, 0 },
- /* 19 */ { M32C_INSN_JSR16_W, 3, M32C_INSN_JSR16_A, 2 },
- /* 20 */ { M32C_INSN_JSR16_A, 4, M32C_INSN_JSR16_A, 0 },
- /* 21 */ { M32C_INSN_JSR32_W, 3, M32C_INSN_JSR32_A, 2 },
- /* 22 */ { M32C_INSN_JSR32_A, 4, M32C_INSN_JSR32_A, 0 },
- /* 23 */ { -M32C_MACRO_ADJNZ_2, 3, -M32C_MACRO_ADJNZ_2, 0 },
- /* 24 */ { -M32C_MACRO_ADJNZ_3, 4, -M32C_MACRO_ADJNZ_3, 0 },
- /* 25 */ { -M32C_MACRO_ADJNZ_4, 5, -M32C_MACRO_ADJNZ_4, 0 },
- /* 26 */ { -M32C_MACRO_ADJNZ_5, 6, -M32C_MACRO_ADJNZ_5, 0 }
- };
- #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
- void
- m32c_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
- {
- symbolS *symbolP = fragP->fr_symbol;
- if (symbolP && !S_IS_DEFINED (symbolP))
- *aim = 0;
- /* Adjust for m32c pcrel not being relative to the next opcode. */
- *aim += subtype_mappings[this_state].pcrel_aim_offset;
- }
- static int
- insn_to_subtype (int inum, const CGEN_INSN *insn)
- {
- unsigned int i;
- if (insn
- && (strncmp (insn->base->mnemonic, "adjnz", 5) == 0
- || strncmp (insn->base->mnemonic, "sbjnz", 5) == 0))
- {
- i = 23 + insn->base->bitsize/8 - 3;
- /*printf("mapping %d used for %s\n", i, insn->base->mnemonic);*/
- return i;
- }
- for (i=0; i<NUM_MAPPINGS; i++)
- if (inum == subtype_mappings[i].insn)
- {
- /*printf("mapping %d used\n", i);*/
- return i;
- }
- abort ();
- }
- /* Return an initial guess of the length by which a fragment must grow to
- hold a branch to reach its destination.
- Also updates fr_type/fr_subtype as necessary.
- Called just before doing relaxation.
- Any symbol that is now undefined will not become defined.
- The guess for fr_var is ACTUALLY the growth beyond fr_fix.
- Whatever we do to grow fr_fix or fr_var contributes to our returned value.
- Although it may not be explicit in the frag, pretend fr_var starts with a
- 0 value. */
- int
- md_estimate_size_before_relax (fragS * fragP, segT segment ATTRIBUTE_UNUSED)
- {
- int where = fragP->fr_opcode - fragP->fr_literal;
- if (fragP->fr_subtype == 1)
- fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num, fragP->fr_cgen.insn);
- if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
- {
- int new_insn;
- new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
- fragP->fr_subtype = insn_to_subtype (new_insn, 0);
- }
- if (fragP->fr_cgen.insn->base
- && fragP->fr_cgen.insn->base->num
- != subtype_mappings[fragP->fr_subtype].insn
- && subtype_mappings[fragP->fr_subtype].insn > 0)
- {
- int new_insn= subtype_mappings[fragP->fr_subtype].insn;
- if (new_insn >= 0)
- {
- fragP->fr_cgen.insn = (fragP->fr_cgen.insn
- - fragP->fr_cgen.insn->base->num
- + new_insn);
- }
- }
- return subtype_mappings[fragP->fr_subtype].bytes - (fragP->fr_fix - where);
- }
- /* *fragP has been relaxed to its final size, and now needs to have
- the bytes inside it modified to conform to the new size.
- Called after relaxation is finished.
- fragP->fr_type == rs_machine_dependent.
- fragP->fr_subtype is the subtype of what the address relaxed to. */
- static int
- target_address_for (fragS *frag)
- {
- int rv = frag->fr_offset;
- symbolS *sym = frag->fr_symbol;
- if (sym)
- rv += S_GET_VALUE (sym);
- /*printf("target_address_for returns %d\n", rv);*/
- return rv;
- }
- void
- md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
- segT sec ATTRIBUTE_UNUSED,
- fragS * fragP ATTRIBUTE_UNUSED)
- {
- int addend;
- int operand;
- int where = fragP->fr_opcode - fragP->fr_literal;
- int rl_where = fragP->fr_opcode - fragP->fr_literal;
- unsigned char *op = (unsigned char *)fragP->fr_opcode;
- int rl_addend = 0;
- addend = target_address_for (fragP) - (fragP->fr_address + where);
- fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes;
- switch (subtype_mappings[fragP->fr_subtype].insn)
- {
- case M32C_INSN_JCND16_5:
- op[1] = addend - 1;
- operand = M32C_OPERAND_LAB_8_8;
- rl_addend = 0x21;
- break;
- case -M32C_MACRO_JCND16_5_W:
- op[0] ^= 0x04;
- op[1] = 4;
- op[2] = 0xf4;
- op[3] = addend - 3;
- op[4] = (addend - 3) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- where += 2;
- rl_addend = 0x51;
- break;
- case -M32C_MACRO_JCND16_5_A:
- op[0] ^= 0x04;
- op[1] = 5;
- op[2] = 0xfc;
- operand = M32C_OPERAND_LAB_8_24;
- where += 2;
- rl_addend = 0x61;
- break;
- case M32C_INSN_JCND16:
- op[2] = addend - 2;
- operand = M32C_OPERAND_LAB_16_8;
- rl_addend = 0x31;
- break;
- case -M32C_MACRO_JCND16_W:
- op[1] ^= 0x04;
- op[2] = 4;
- op[3] = 0xf4;
- op[4] = addend - 4;
- op[5] = (addend - 4) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- where += 3;
- rl_addend = 0x61;
- break;
- case -M32C_MACRO_JCND16_A:
- op[1] ^= 0x04;
- op[2] = 5;
- op[3] = 0xfc;
- operand = M32C_OPERAND_LAB_8_24;
- where += 3;
- rl_addend = 0x71;
- break;
- case M32C_INSN_JMP16_S:
- op[0] = 0x60 | ((addend-2) & 0x07);
- operand = M32C_OPERAND_LAB_5_3;
- rl_addend = 0x10;
- break;
- case M32C_INSN_JMP16_B:
- op[0] = 0xfe;
- op[1] = addend - 1;
- operand = M32C_OPERAND_LAB_8_8;
- rl_addend = 0x21;
- break;
- case M32C_INSN_JMP16_W:
- op[0] = 0xf4;
- op[1] = addend - 1;
- op[2] = (addend - 1) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- rl_addend = 0x31;
- break;
- case M32C_INSN_JMP16_A:
- op[0] = 0xfc;
- op[1] = 0;
- op[2] = 0;
- op[3] = 0;
- operand = M32C_OPERAND_LAB_8_24;
- rl_addend = 0x41;
- break;
- case M32C_INSN_JCND32:
- op[1] = addend - 1;
- operand = M32C_OPERAND_LAB_8_8;
- rl_addend = 0x21;
- break;
- case -M32C_MACRO_JCND32_W:
- op[0] ^= 0x40;
- op[1] = 4;
- op[2] = 0xce;
- op[3] = addend - 3;
- op[4] = (addend - 3) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- where += 2;
- rl_addend = 0x51;
- break;
- case -M32C_MACRO_JCND32_A:
- op[0] ^= 0x40;
- op[1] = 5;
- op[2] = 0xcc;
- operand = M32C_OPERAND_LAB_8_24;
- where += 2;
- rl_addend = 0x61;
- break;
- case M32C_INSN_JMP32_S:
- addend = ((addend-2) & 0x07);
- op[0] = 0x4a | (addend & 0x01) | ((addend << 3) & 0x30);
- operand = M32C_OPERAND_LAB32_JMP_S;
- rl_addend = 0x10;
- break;
- case M32C_INSN_JMP32_B:
- op[0] = 0xbb;
- op[1] = addend - 1;
- operand = M32C_OPERAND_LAB_8_8;
- rl_addend = 0x21;
- break;
- case M32C_INSN_JMP32_W:
- op[0] = 0xce;
- op[1] = addend - 1;
- op[2] = (addend - 1) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- rl_addend = 0x31;
- break;
- case M32C_INSN_JMP32_A:
- op[0] = 0xcc;
- op[1] = 0;
- op[2] = 0;
- op[3] = 0;
- operand = M32C_OPERAND_LAB_8_24;
- rl_addend = 0x41;
- break;
- case M32C_INSN_JSR16_W:
- op[0] = 0xf5;
- op[1] = addend - 1;
- op[2] = (addend - 1) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- rl_addend = 0x31;
- break;
- case M32C_INSN_JSR16_A:
- op[0] = 0xfd;
- op[1] = 0;
- op[2] = 0;
- op[3] = 0;
- operand = M32C_OPERAND_LAB_8_24;
- rl_addend = 0x41;
- break;
- case M32C_INSN_JSR32_W:
- op[0] = 0xcf;
- op[1] = addend - 1;
- op[2] = (addend - 1) >> 8;
- operand = M32C_OPERAND_LAB_8_16;
- rl_addend = 0x31;
- break;
- case M32C_INSN_JSR32_A:
- op[0] = 0xcd;
- op[1] = 0;
- op[2] = 0;
- op[3] = 0;
- operand = M32C_OPERAND_LAB_8_24;
- rl_addend = 0x41;
- break;
- case -M32C_MACRO_ADJNZ_2:
- rl_addend = 0x31;
- op[2] = addend - 2;
- operand = M32C_OPERAND_LAB_16_8;
- break;
- case -M32C_MACRO_ADJNZ_3:
- rl_addend = 0x41;
- op[3] = addend - 2;
- operand = M32C_OPERAND_LAB_24_8;
- break;
- case -M32C_MACRO_ADJNZ_4:
- rl_addend = 0x51;
- op[4] = addend - 2;
- operand = M32C_OPERAND_LAB_32_8;
- break;
- case -M32C_MACRO_ADJNZ_5:
- rl_addend = 0x61;
- op[5] = addend - 2;
- operand = M32C_OPERAND_LAB_40_8;
- break;
- default:
- printf("\nHey! Need more opcode converters! missing: %d %s\n\n",
- fragP->fr_subtype,
- fragP->fr_cgen.insn->base->name);
- abort();
- }
- if (m32c_relax)
- {
- if (operand != M32C_OPERAND_LAB_8_24)
- fragP->fr_offset = (fragP->fr_address + where);
- fix_new (fragP,
- rl_where,
- 0, abs_section_sym, rl_addend, 0,
- BFD_RELOC_M32C_RL_JUMP);
- }
- if (S_GET_SEGMENT (fragP->fr_symbol) != sec
- || operand == M32C_OPERAND_LAB_8_24
- || (m32c_relax && (operand != M32C_OPERAND_LAB_5_3
- && operand != M32C_OPERAND_LAB32_JMP_S)))
- {
- gas_assert (fragP->fr_cgen.insn != 0);
- gas_cgen_record_fixup (fragP,
- where,
- fragP->fr_cgen.insn,
- (fragP->fr_fix - where) * 8,
- cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
- operand),
- fragP->fr_cgen.opinfo,
- fragP->fr_symbol,
- fragP->fr_offset);
- }
- }
- /* Functions concerning relocs. */
- /* The location from which a PC relative jump should be calculated,
- given a PC relative reloc. */
- long
- md_pcrel_from_section (fixS * fixP, segT sec)
- {
- if (fixP->fx_addsy != (symbolS *) NULL
- && (! S_IS_DEFINED (fixP->fx_addsy)
- || S_GET_SEGMENT (fixP->fx_addsy) != sec))
- /* The symbol is undefined (or is defined but not in this section).
- Let the linker figure it out. */
- return 0;
- return (fixP->fx_frag->fr_address + fixP->fx_where);
- }
- /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
- Returns BFD_RELOC_NONE if no reloc type can be found.
- *FIXP may be modified if desired. */
- bfd_reloc_code_real_type
- md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED,
- const CGEN_OPERAND * operand,
- fixS * fixP ATTRIBUTE_UNUSED)
- {
- static const struct op_reloc {
- /* A CGEN operand type that can be a relocatable expression. */
- CGEN_OPERAND_TYPE operand;
- /* The appropriate BFD reloc type to use for that. */
- bfd_reloc_code_real_type reloc;
- /* The offset from the start of the instruction to the field to be
- relocated, in bytes. */
- int offset;
- } op_reloc_table[] = {
- /* PC-REL relocs for 8-bit fields. */
- { M32C_OPERAND_LAB_8_8, BFD_RELOC_8_PCREL, 1 },
- { M32C_OPERAND_LAB_16_8, BFD_RELOC_8_PCREL, 2 },
- { M32C_OPERAND_LAB_24_8, BFD_RELOC_8_PCREL, 3 },
- { M32C_OPERAND_LAB_32_8, BFD_RELOC_8_PCREL, 4 },
- { M32C_OPERAND_LAB_40_8, BFD_RELOC_8_PCREL, 5 },
- /* PC-REL relocs for 16-bit fields. */
- { M32C_OPERAND_LAB_8_16, BFD_RELOC_16_PCREL, 1 },
- /* Absolute relocs for 8-bit fields. */
- { M32C_OPERAND_IMM_8_QI, BFD_RELOC_8, 1 },
- { M32C_OPERAND_IMM_16_QI, BFD_RELOC_8, 2 },
- { M32C_OPERAND_IMM_24_QI, BFD_RELOC_8, 3 },
- { M32C_OPERAND_IMM_32_QI, BFD_RELOC_8, 4 },
- { M32C_OPERAND_IMM_40_QI, BFD_RELOC_8, 5 },
- { M32C_OPERAND_IMM_48_QI, BFD_RELOC_8, 6 },
- { M32C_OPERAND_IMM_56_QI, BFD_RELOC_8, 7 },
- { M32C_OPERAND_DSP_8_S8, BFD_RELOC_8, 1 },
- { M32C_OPERAND_DSP_16_S8, BFD_RELOC_8, 2 },
- { M32C_OPERAND_DSP_24_S8, BFD_RELOC_8, 3 },
- { M32C_OPERAND_DSP_32_S8, BFD_RELOC_8, 4 },
- { M32C_OPERAND_DSP_40_S8, BFD_RELOC_8, 5 },
- { M32C_OPERAND_DSP_48_S8, BFD_RELOC_8, 6 },
- { M32C_OPERAND_DSP_8_U8, BFD_RELOC_8, 1 },
- { M32C_OPERAND_DSP_16_U8, BFD_RELOC_8, 2 },
- { M32C_OPERAND_DSP_24_U8, BFD_RELOC_8, 3 },
- { M32C_OPERAND_DSP_32_U8, BFD_RELOC_8, 4 },
- { M32C_OPERAND_DSP_40_U8, BFD_RELOC_8, 5 },
- { M32C_OPERAND_DSP_48_U8, BFD_RELOC_8, 6 },
- { M32C_OPERAND_BITBASE32_16_S11_UNPREFIXED, BFD_RELOC_8, 2 },
- { M32C_OPERAND_BITBASE32_16_U11_UNPREFIXED, BFD_RELOC_8, 2 },
- { M32C_OPERAND_BITBASE32_24_S11_PREFIXED, BFD_RELOC_8, 3 },
- { M32C_OPERAND_BITBASE32_24_U11_PREFIXED, BFD_RELOC_8, 3 },
- /* Absolute relocs for 16-bit fields. */
- { M32C_OPERAND_IMM_8_HI, BFD_RELOC_16, 1 },
- { M32C_OPERAND_IMM_16_HI, BFD_RELOC_16, 2 },
- { M32C_OPERAND_IMM_24_HI, BFD_RELOC_16, 3 },
- { M32C_OPERAND_IMM_32_HI, BFD_RELOC_16, 4 },
- { M32C_OPERAND_IMM_40_HI, BFD_RELOC_16, 5 },
- { M32C_OPERAND_IMM_48_HI, BFD_RELOC_16, 6 },
- { M32C_OPERAND_IMM_56_HI, BFD_RELOC_16, 7 },
- { M32C_OPERAND_IMM_64_HI, BFD_RELOC_16, 8 },
- { M32C_OPERAND_DSP_16_S16, BFD_RELOC_16, 2 },
- { M32C_OPERAND_DSP_24_S16, BFD_RELOC_16, 3 },
- { M32C_OPERAND_DSP_32_S16, BFD_RELOC_16, 4 },
- { M32C_OPERAND_DSP_40_S16, BFD_RELOC_16, 5 },
- { M32C_OPERAND_DSP_8_U16, BFD_RELOC_16, 1 },
- { M32C_OPERAND_DSP_16_U16, BFD_RELOC_16, 2 },
- { M32C_OPERAND_DSP_24_U16, BFD_RELOC_16, 3 },
- { M32C_OPERAND_DSP_32_U16, BFD_RELOC_16, 4 },
- { M32C_OPERAND_DSP_40_U16, BFD_RELOC_16, 5 },
- { M32C_OPERAND_DSP_48_U16, BFD_RELOC_16, 6 },
- { M32C_OPERAND_BITBASE32_16_S19_UNPREFIXED, BFD_RELOC_16, 2 },
- { M32C_OPERAND_BITBASE32_16_U19_UNPREFIXED, BFD_RELOC_16, 2 },
- { M32C_OPERAND_BITBASE32_24_S19_PREFIXED, BFD_RELOC_16, 3 },
- { M32C_OPERAND_BITBASE32_24_U19_PREFIXED, BFD_RELOC_16, 3 },
- /* Absolute relocs for 24-bit fields. */
- { M32C_OPERAND_LAB_8_24, BFD_RELOC_24, 1 },
- { M32C_OPERAND_DSP_8_S24, BFD_RELOC_24, 1 },
- { M32C_OPERAND_DSP_8_U24, BFD_RELOC_24, 1 },
- { M32C_OPERAND_DSP_16_U24, BFD_RELOC_24, 2 },
- { M32C_OPERAND_DSP_24_U24, BFD_RELOC_24, 3 },
- { M32C_OPERAND_DSP_32_U24, BFD_RELOC_24, 4 },
- { M32C_OPERAND_DSP_40_U24, BFD_RELOC_24, 5 },
- { M32C_OPERAND_DSP_48_U24, BFD_RELOC_24, 6 },
- { M32C_OPERAND_DSP_16_U20, BFD_RELOC_24, 2 },
- { M32C_OPERAND_DSP_24_U20, BFD_RELOC_24, 3 },
- { M32C_OPERAND_DSP_32_U20, BFD_RELOC_24, 4 },
- { M32C_OPERAND_BITBASE32_16_U27_UNPREFIXED, BFD_RELOC_24, 2 },
- { M32C_OPERAND_BITBASE32_24_U27_PREFIXED, BFD_RELOC_24, 3 },
- /* Absolute relocs for 32-bit fields. */
- { M32C_OPERAND_IMM_16_SI, BFD_RELOC_32, 2 },
- { M32C_OPERAND_IMM_24_SI, BFD_RELOC_32, 3 },
- { M32C_OPERAND_IMM_32_SI, BFD_RELOC_32, 4 },
- { M32C_OPERAND_IMM_40_SI, BFD_RELOC_32, 5 },
- };
- int i;
- for (i = ARRAY_SIZE (op_reloc_table); --i >= 0; )
- {
- const struct op_reloc *or = &op_reloc_table[i];
- if (or->operand == operand->type)
- {
- fixP->fx_where += or->offset;
- fixP->fx_size -= or->offset;
- if (fixP->fx_cgen.opinfo
- && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
- return fixP->fx_cgen.opinfo;
- return or->reloc;
- }
- }
- fprintf
- (stderr,
- "Error: tc-m32c.c:md_cgen_lookup_reloc Unimplemented relocation for operand %s\n",
- operand->name);
- return BFD_RELOC_NONE;
- }
- void
- m32c_cons_fix_new (fragS * frag,
- int where,
- int size,
- expressionS *exp,
- bfd_reloc_code_real_type type)
- {
- switch (size)
- {
- case 1:
- type = BFD_RELOC_8;
- break;
- case 2:
- type = BFD_RELOC_16;
- break;
- case 3:
- type = BFD_RELOC_24;
- break;
- case 4:
- default:
- type = BFD_RELOC_32;
- break;
- case 8:
- type = BFD_RELOC_64;
- break;
- }
- fix_new_exp (frag, where, (int) size, exp, 0, type);
- }
- void
- m32c_apply_fix (struct fix *f, valueT *t, segT s)
- {
- if (f->fx_r_type == BFD_RELOC_M32C_RL_JUMP
- || f->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
- || f->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
- return;
- gas_cgen_md_apply_fix (f, t, s);
- }
- arelent *
- tc_gen_reloc (asection *sec, fixS *fx)
- {
- if (fx->fx_r_type == BFD_RELOC_M32C_RL_JUMP
- || fx->fx_r_type == BFD_RELOC_M32C_RL_1ADDR
- || fx->fx_r_type == BFD_RELOC_M32C_RL_2ADDR)
- {
- arelent * reloc;
- reloc = xmalloc (sizeof (* reloc));
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
- *reloc->sym_ptr_ptr = symbol_get_bfdsym (fx->fx_addsy);
- reloc->address = fx->fx_frag->fr_address + fx->fx_where;
- reloc->howto = bfd_reloc_type_lookup (stdoutput, fx->fx_r_type);
- reloc->addend = fx->fx_offset;
- return reloc;
- }
- return gas_cgen_tc_gen_reloc (sec, fx);
- }
- /* See whether we need to force a relocation into the output file.
- This is used to force out switch and PC relative relocations when
- relaxing. */
- int
- m32c_force_relocation (fixS * fixp)
- {
- int reloc = fixp->fx_r_type;
- if (reloc > (int)BFD_RELOC_UNUSED)
- {
- reloc -= (int)BFD_RELOC_UNUSED;
- switch (reloc)
- {
- case M32C_OPERAND_DSP_32_S16:
- case M32C_OPERAND_DSP_32_U16:
- case M32C_OPERAND_IMM_32_HI:
- case M32C_OPERAND_DSP_16_S16:
- case M32C_OPERAND_DSP_16_U16:
- case M32C_OPERAND_IMM_16_HI:
- case M32C_OPERAND_DSP_24_S16:
- case M32C_OPERAND_DSP_24_U16:
- case M32C_OPERAND_IMM_24_HI:
- return 1;
- /* If we're doing linker relaxing, we need to keep all the
- pc-relative jumps in case we need to fix them due to
- deleted bytes between the jump and its destination. */
- case M32C_OPERAND_LAB_8_8:
- case M32C_OPERAND_LAB_8_16:
- case M32C_OPERAND_LAB_8_24:
- case M32C_OPERAND_LAB_16_8:
- case M32C_OPERAND_LAB_24_8:
- case M32C_OPERAND_LAB_32_8:
- case M32C_OPERAND_LAB_40_8:
- if (m32c_relax)
- return 1;
- default:
- break;
- }
- }
- else
- {
- switch (fixp->fx_r_type)
- {
- case BFD_RELOC_16:
- return 1;
- case BFD_RELOC_M32C_RL_JUMP:
- case BFD_RELOC_M32C_RL_1ADDR:
- case BFD_RELOC_M32C_RL_2ADDR:
- case BFD_RELOC_8_PCREL:
- case BFD_RELOC_16_PCREL:
- if (m32c_relax)
- return 1;
- default:
- break;
- }
- }
- return generic_force_reloc (fixp);
- }
- /* Write a value out to the object file, using the appropriate endianness. */
- void
- md_number_to_chars (char * buf, valueT val, int n)
- {
- number_to_chars_littleendian (buf, val, n);
- }
- /* Turn a string in input_line_pointer into a floating point constant of type
- type, and store the appropriate bytes in *litP. The number of LITTLENUMS
- emitted is stored in *sizeP . An error message is returned, or NULL on OK. */
- /* Equal to MAX_PRECISION in atof-ieee.c. */
- #define MAX_LITTLENUMS 6
- char *
- md_atof (int type, char * litP, int * sizeP)
- {
- return ieee_md_atof (type, litP, sizeP, TRUE);
- }
- bfd_boolean
- m32c_fix_adjustable (fixS * fixP)
- {
- int reloc;
- if (fixP->fx_addsy == NULL)
- return 1;
- /* We need the symbol name for the VTABLE entries. */
- reloc = fixP->fx_r_type;
- if (reloc > (int)BFD_RELOC_UNUSED)
- {
- reloc -= (int)BFD_RELOC_UNUSED;
- switch (reloc)
- {
- case M32C_OPERAND_DSP_32_S16:
- case M32C_OPERAND_DSP_32_U16:
- case M32C_OPERAND_IMM_32_HI:
- case M32C_OPERAND_DSP_16_S16:
- case M32C_OPERAND_DSP_16_U16:
- case M32C_OPERAND_IMM_16_HI:
- case M32C_OPERAND_DSP_24_S16:
- case M32C_OPERAND_DSP_24_U16:
- case M32C_OPERAND_IMM_24_HI:
- return 0;
- }
- }
- else
- {
- if (fixP->fx_r_type == BFD_RELOC_16)
- return 0;
- }
- /* Do not adjust relocations involving symbols in merged sections.
- A reloc patching in the value of some symbol S plus some addend A
- can be produced in different ways:
- 1) It might simply be a reference to the data at S + A. Clearly,
- if linker merging shift that data around, the value patched in
- by the reloc needs to be adjusted accordingly.
- 2) Or, it might be a reference to S, with A added in as a constant
- bias. For example, given code like this:
- static int S[100];
- ... S[i - 8] ...
- it would be reasonable for the compiler to rearrange the array
- reference to something like:
- ... (S-8)[i] ...
- and emit assembly code that refers to S - (8 * sizeof (int)),
- so the subtraction is done entirely at compile-time. In this
- case, the reloc's addend A would be -(8 * sizeof (int)), and
- shifting around code or data at S + A should not affect the
- reloc: the reloc isn't referring to that code or data at all.
- The linker has no way of knowing which case it has in hand. So,
- to disambiguate, we have the linker always treat reloc addends as
- in case 2): they're constants that should be simply added to the
- symbol value, just like the reloc says. And we express case 1)
- in different way: we have the compiler place a label at the real
- target, and reference that label with an addend of zero. (The
- compiler is unlikely to reference code using a label plus an
- offset anyway, since it doesn't know the sizes of the
- instructions.)
- The simplification being done by gas/write.c:adjust_reloc_syms,
- however, turns the explicit-label usage into the label-plus-
- offset usage, re-introducing the ambiguity the compiler avoided.
- So we need to disable that simplification for symbols referring
- to merged data.
- This only affects object size a little bit. */
- if (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE)
- return 0;
- if (m32c_relax)
- return 0;
- return 1;
- }
- /* Worker function for m32c_is_colon_insn(). */
- static int
- restore_colon (char *next_i_l_p, char *nul_char)
- {
- /* Restore the colon, and advance input_line_pointer to
- the end of the new symbol. */
- *input_line_pointer = *nul_char;
- input_line_pointer = next_i_l_p;
- *nul_char = *next_i_l_p;
- *next_i_l_p = 0;
- return 1;
- }
- /* Determines if the symbol starting at START and ending in
- a colon that was at the location pointed to by INPUT_LINE_POINTER
- (but which has now been replaced bu a NUL) is in fact an
- :Z, :S, :Q, or :G suffix.
- If it is, then it restores the colon, advances INPUT_LINE_POINTER
- to the real end of the instruction/symbol, saves the char there to
- NUL_CHAR and pokes a NUL, and returns 1. Otherwise it returns 0. */
- int
- m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED, char *nul_char)
- {
- char * i_l_p = input_line_pointer;
- if (*nul_char == '"')
- ++i_l_p;
- /* Check to see if the text following the colon is 'G' */
- if (TOLOWER (i_l_p[1]) == 'g' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
- return restore_colon (i_l_p + 2, nul_char);
- /* Check to see if the text following the colon is 'Q' */
- if (TOLOWER (i_l_p[1]) == 'q' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
- return restore_colon (i_l_p + 2, nul_char);
- /* Check to see if the text following the colon is 'S' */
- if (TOLOWER (i_l_p[1]) == 's' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
- return restore_colon (i_l_p + 2, nul_char);
- /* Check to see if the text following the colon is 'Z' */
- if (TOLOWER (i_l_p[1]) == 'z' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
- return restore_colon (i_l_p + 2, nul_char);
- return 0;
- }
|