/* tc-m32c.c -- Assembler for the Renesas M32C.
- Copyright (C) 2005 Free Software Foundation.
+ Copyright (C) 2005-2021 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 2, or (at your option)
+ 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,
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. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include <stdio.h>
#include "as.h"
-#include "subsegs.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 "libiberty.h"
#include "safe-ctype.h"
-#include "bfd.h"
/* Structure to hold all of the different components
describing an individual instruction. */
}
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[] = "|";
/* 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);
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 void s_bss (int);
int
-md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
+md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
{
switch (c)
{
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;
}
md_show_usage (FILE * stream)
{
fprintf (stream, _(" M32C specific command line options:\n"));
-}
+}
static void
s_bss (int ignore ATTRIBUTE_UNUSED)
const pseudo_typeS md_pseudo_table[] =
{
{ "bss", s_bss, 0},
+ { "3byte", cons, 3 },
{ "word", cons, 4 },
{ NULL, NULL, 0 }
};
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,
/* 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
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);
+ new_str = XNEWVEC (char, 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;
if (indirection[operand] != none)
continue;
}
-
+
else if (s[0] == '[' && brace_n[operand])
{
brace_n[operand] += 1;
{
fprintf (stderr, "Unmatched [[operand-%d]] %d\n", operand, brace_n[operand]);
}
-
+
if (indirection[1] != none && indirection[2] != none)
- md_assemble ("src-dest-indirect");
+ md_assemble ((char *) "src-dest-indirect");
else if (indirection[1] != none)
- md_assemble ("src-indirect");
+ md_assemble ((char *) "src-indirect");
else if (indirection[2] != none)
- md_assemble ("dest-indirect");
+ md_assemble ((char *) "dest-indirect");
md_assemble (new_str);
free (new_str);
static int last_insn_had_delay_slot = 0;
m32c_insn insn;
char * errmsg;
+ finished_insnS results;
+ int rl_type;
+ int insn_size;
if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str))
return;
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, NULL);
+ 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
+void
md_operand (expressionS * exp)
{
/* In case of a syntax error, escape back to try next syntax combo. */
valueT
md_section_align (segT segment, valueT size)
{
- int align = bfd_get_section_alignment (stdoutput, segment);
- return ((size + (1 << align) - 1) & (-1 << align));
+ int align = bfd_section_alignment (segment);
+ return ((size + (1 << align) - 1) & -(1 << align));
}
symbolS *
/* 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 */
+ /* 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_A,
M32C_MACRO_JCND32_W,
M32C_MACRO_JCND32_A,
-} M32C_Macros;
+ /* 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,
+};
static struct {
int insn;
/* 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 }
+ /* 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]))
}
static int
-insn_to_subtype (int insn)
+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 (insn == subtype_mappings[i].insn)
+ if (inum == subtype_mappings[i].insn)
{
/*printf("mapping %d used\n", i);*/
return i;
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_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);
+ fragP->fr_subtype = insn_to_subtype (new_insn, 0);
}
if (fragP->fr_cgen.insn->base
}
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.
{
int addend;
int operand;
- int new_insn;
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);
- new_insn = subtype_mappings[fragP->fr_subtype].insn;
fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes;
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[4] = (addend - 3) >> 8;
operand = M32C_OPERAND_LAB_8_16;
where += 2;
- new_insn = M32C_INSN_JMP16_W;
+ rl_addend = 0x51;
break;
case -M32C_MACRO_JCND16_5_A:
op[2] = 0xfc;
operand = M32C_OPERAND_LAB_8_24;
where += 2;
- new_insn = M32C_INSN_JMP16_A;
+ 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[5] = (addend - 4) >> 8;
operand = M32C_OPERAND_LAB_8_16;
where += 3;
- new_insn = M32C_INSN_JMP16_W;
+ rl_addend = 0x61;
break;
case -M32C_MACRO_JCND16_A:
op[3] = 0xfc;
operand = M32C_OPERAND_LAB_8_24;
where += 3;
- new_insn = M32C_INSN_JMP16_A;
+ 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[1] = addend - 1;
op[2] = (addend - 1) >> 8;
operand = M32C_OPERAND_LAB_8_16;
+ rl_addend = 0x31;
break;
case M32C_INSN_JMP16_A:
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[4] = (addend - 3) >> 8;
operand = M32C_OPERAND_LAB_8_16;
where += 2;
- new_insn = M32C_INSN_JMP32_W;
+ rl_addend = 0x51;
break;
case -M32C_MACRO_JCND32_A:
op[2] = 0xcc;
operand = M32C_OPERAND_LAB_8_24;
where += 2;
- new_insn = M32C_INSN_JMP32_A;
+ 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[1] = addend - 1;
op[2] = (addend - 1) >> 8;
operand = M32C_OPERAND_LAB_8_16;
+ rl_addend = 0x31;
break;
case M32C_INSN_JMP32_A:
op[2] = 0;
op[3] = 0;
operand = M32C_OPERAND_LAB_8_24;
+ rl_addend = 0x41;
break;
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[2] = 0;
op[3] = 0;
operand = M32C_OPERAND_LAB_8_24;
+ rl_addend = 0x41;
break;
case M32C_INSN_JSR32_W:
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[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",
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)
+ || operand == M32C_OPERAND_LAB_8_24
+ || (m32c_relax && (operand != M32C_OPERAND_LAB_5_3
+ && operand != M32C_OPERAND_LAB32_JMP_S)))
{
- assert (fragP->fr_cgen.insn != 0);
+ gas_assert (fragP->fr_cgen.insn != 0);
gas_cgen_record_fixup (fragP,
where,
fragP->fr_cgen.insn,
cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
operand),
fragP->fr_cgen.opinfo,
- fragP->fr_symbol, fragP->fr_offset);
+ fragP->fr_symbol,
+ fragP->fr_offset);
}
}
\f
} 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 },
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 = XNEW (arelent);
+
+ reloc->sym_ptr_ptr = XNEW (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. */
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
{
- if (fixp->fx_r_type == BFD_RELOC_16)
- return 1;
+ 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);
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 *
+const char *
md_atof (int type, char * litP, int * sizeP)
{
- int i;
- int prec;
- LITTLENUM_TYPE words [MAX_LITTLENUMS];
- char * t;
-
- switch (type)
- {
- case 'f':
- case 'F':
- case 's':
- case 'S':
- prec = 2;
- break;
-
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- prec = 4;
- break;
-
- /* FIXME: Some targets allow other format chars for bigger sizes here. */
-
- default:
- * sizeP = 0;
- return _("Bad call to md_atof()");
- }
-
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
- * sizeP = prec * sizeof (LITTLENUM_TYPE);
-
- for (i = 0; i < prec; i++)
- {
- md_number_to_chars (litP, (valueT) words[i],
- sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
- }
-
- return 0;
+ return ieee_md_atof (type, litP, sizeP, TRUE);
}
bfd_boolean
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 char restore_colon PARAMS ((int));
-
-static char
-restore_colon (int advance_i_l_p_by)
+static int
+restore_colon (char *next_i_l_p, char *nul_char)
{
- char c;
-
/* Restore the colon, and advance input_line_pointer to
the end of the new symbol. */
- * input_line_pointer = ':';
- input_line_pointer += advance_i_l_p_by;
- c = * input_line_pointer;
- * input_line_pointer = 0;
-
- return c;
+ *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
(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, and returns the character
- that really terminated the symbol. Otherwise it returns 0. */
-char
-m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED)
+ 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 (2);
+ 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 (2);
+ 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 (2);
+ 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 (2);
+ return restore_colon (i_l_p + 2, nul_char);
return 0;
}