2003-04-04 16:15:15 +08:00
|
|
|
/* tc-tic4x.c -- Assemble for the Texas Instruments TMS320C[34]x.
|
2024-01-04 19:52:08 +08:00
|
|
|
Copyright (C) 1997-2024 Free Software Foundation, Inc.
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
|
|
|
|
|
|
|
|
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
|
2007-07-03 19:01:12 +08:00
|
|
|
the Free Software Foundation; either version 3, or (at your option)
|
2002-08-28 18:38:51 +08:00
|
|
|
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
|
2015-08-12 19:40:42 +08:00
|
|
|
the Free Software Foundation, 51 Franklin Street - Fifth Floor,
|
2005-05-05 17:13:19 +08:00
|
|
|
Boston, MA 02110-1301, USA. */
|
2002-11-11 22:29:01 +08:00
|
|
|
/*
|
|
|
|
TODOs:
|
|
|
|
------
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2002-11-16 20:23:23 +08:00
|
|
|
o .align cannot handle fill-data-width larger than 0xFF/8-bits. It
|
|
|
|
should be possible to define a 32-bits pattern.
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-11-22 23:32:28 +08:00
|
|
|
o .align: Implement a 'bu' insn if the number of nop's exceeds 4
|
2002-11-16 20:23:23 +08:00
|
|
|
within the align frag. if(fragsize>4words) insert bu fragend+1
|
|
|
|
first.
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
o .usect if has symbol on previous line not implemented
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
o .sym, .eos, .stag, .etag, .member not implemented
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2002-11-16 20:23:23 +08:00
|
|
|
o Evaluation of constant floating point expressions (expr.c needs
|
|
|
|
work!)
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2012-05-17 23:13:28 +08:00
|
|
|
o Support 'abc' constants (that is 0x616263). */
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
#include "as.h"
|
2012-05-17 23:13:28 +08:00
|
|
|
#include "safe-ctype.h"
|
2002-08-28 18:38:51 +08:00
|
|
|
#include "opcode/tic4x.h"
|
|
|
|
#include "subsegs.h"
|
|
|
|
|
|
|
|
/* OK, we accept a syntax similar to the other well known C30
|
2003-04-04 16:15:15 +08:00
|
|
|
assembly tools. With TIC4X_ALT_SYNTAX defined we are more
|
2002-08-28 18:38:51 +08:00
|
|
|
flexible, allowing a more Unix-like syntax: `%' in front of
|
|
|
|
register names, `#' in front of immediate constants, and
|
|
|
|
not requiring `@' in front of direct addresses. */
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
#define TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Handle of the inst mnemonic hash table. */
|
2020-08-18 16:57:21 +08:00
|
|
|
static htab_t tic4x_op_hash = NULL;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Handle asg pseudo. */
|
2020-08-18 16:57:21 +08:00
|
|
|
static htab_t tic4x_asg_hash = NULL;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
static unsigned int tic4x_cpu = 0; /* Default to TMS320C40. */
|
|
|
|
static unsigned int tic4x_revision = 0; /* CPU revision */
|
|
|
|
static unsigned int tic4x_idle2 = 0; /* Idle2 support */
|
|
|
|
static unsigned int tic4x_lowpower = 0; /* Lowpower support */
|
|
|
|
static unsigned int tic4x_enhanced = 0; /* Enhanced opcode support */
|
|
|
|
static unsigned int tic4x_big_model = 0; /* Default to small memory model. */
|
|
|
|
static unsigned int tic4x_reg_args = 0; /* Default to args passed on stack. */
|
|
|
|
static unsigned long tic4x_oplevel = 0; /* Opcode level */
|
2002-11-18 17:09:35 +08:00
|
|
|
|
|
|
|
#define OPTION_CPU 'm'
|
|
|
|
#define OPTION_BIG (OPTION_MD_BASE + 1)
|
|
|
|
#define OPTION_SMALL (OPTION_MD_BASE + 2)
|
|
|
|
#define OPTION_MEMPARM (OPTION_MD_BASE + 3)
|
|
|
|
#define OPTION_REGPARM (OPTION_MD_BASE + 4)
|
|
|
|
#define OPTION_IDLE2 (OPTION_MD_BASE + 5)
|
|
|
|
#define OPTION_LOWPOWER (OPTION_MD_BASE + 6)
|
|
|
|
#define OPTION_ENHANCED (OPTION_MD_BASE + 7)
|
|
|
|
#define OPTION_REV (OPTION_MD_BASE + 8)
|
|
|
|
|
2014-01-22 13:06:27 +08:00
|
|
|
const char *md_shortopts = "bm:prs";
|
2002-11-18 17:09:35 +08:00
|
|
|
struct option md_longopts[] =
|
|
|
|
{
|
|
|
|
{ "mcpu", required_argument, NULL, OPTION_CPU },
|
|
|
|
{ "mdsp", required_argument, NULL, OPTION_CPU },
|
|
|
|
{ "mbig", no_argument, NULL, OPTION_BIG },
|
|
|
|
{ "msmall", no_argument, NULL, OPTION_SMALL },
|
|
|
|
{ "mmemparm", no_argument, NULL, OPTION_MEMPARM },
|
|
|
|
{ "mregparm", no_argument, NULL, OPTION_REGPARM },
|
|
|
|
{ "midle2", no_argument, NULL, OPTION_IDLE2 },
|
|
|
|
{ "mlowpower", no_argument, NULL, OPTION_LOWPOWER },
|
|
|
|
{ "menhanced", no_argument, NULL, OPTION_ENHANCED },
|
|
|
|
{ "mrev", required_argument, NULL, OPTION_REV },
|
|
|
|
{ NULL, no_argument, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
size_t md_longopts_size = sizeof (md_longopts);
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
M_UNKNOWN, M_IMMED, M_DIRECT, M_REGISTER, M_INDIRECT,
|
|
|
|
M_IMMED_F, M_PARALLEL, M_HI
|
|
|
|
}
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_addr_mode_t;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
typedef struct tic4x_operand
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_addr_mode_t mode; /* Addressing mode. */
|
2002-08-28 18:38:51 +08:00
|
|
|
expressionS expr; /* Expression. */
|
|
|
|
int disp; /* Displacement for indirect addressing. */
|
|
|
|
int aregno; /* Aux. register number. */
|
|
|
|
LITTLENUM_TYPE fwords[MAX_LITTLENUMS]; /* Float immed. number. */
|
|
|
|
}
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_operand_t;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
typedef struct tic4x_insn
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
char name[TIC4X_NAME_MAX]; /* Mnemonic of instruction. */
|
2002-08-28 18:38:51 +08:00
|
|
|
unsigned int in_use; /* True if in_use. */
|
|
|
|
unsigned int parallel; /* True if parallel instruction. */
|
|
|
|
unsigned int nchars; /* This is always 4 for the C30. */
|
|
|
|
unsigned long opcode; /* Opcode number. */
|
|
|
|
expressionS exp; /* Expression required for relocation. */
|
2016-05-14 14:34:23 +08:00
|
|
|
/* Relocation type required. */
|
|
|
|
bfd_reloc_code_real_type reloc;
|
2002-08-28 18:38:51 +08:00
|
|
|
int pcrel; /* True if relocation PC relative. */
|
|
|
|
char *pname; /* Name of instruction in parallel. */
|
|
|
|
unsigned int num_operands; /* Number of operands in total. */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_inst_t *inst; /* Pointer to first template. */
|
|
|
|
tic4x_operand_t operands[TIC4X_OPERANDS_MAX];
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_insn_t;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
static tic4x_insn_t the_insn; /* Info about our instruction. */
|
|
|
|
static tic4x_insn_t *insn = &the_insn;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2008-08-13 07:39:31 +08:00
|
|
|
static void tic4x_asg (int);
|
|
|
|
static void tic4x_bss (int);
|
|
|
|
static void tic4x_globl (int);
|
|
|
|
static void tic4x_cons (int);
|
|
|
|
static void tic4x_stringer (int);
|
|
|
|
static void tic4x_eval (int);
|
|
|
|
static void tic4x_newblock (int);
|
|
|
|
static void tic4x_sect (int);
|
|
|
|
static void tic4x_set (int);
|
|
|
|
static void tic4x_usect (int);
|
|
|
|
static void tic4x_version (int);
|
2002-09-17 16:35:10 +08:00
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
const pseudo_typeS
|
|
|
|
md_pseudo_table[] =
|
|
|
|
{
|
|
|
|
{"align", s_align_bytes, 32},
|
2003-04-04 16:15:15 +08:00
|
|
|
{"ascii", tic4x_stringer, 1},
|
|
|
|
{"asciz", tic4x_stringer, 0},
|
|
|
|
{"asg", tic4x_asg, 0},
|
2002-11-11 22:29:01 +08:00
|
|
|
{"block", s_space, 4},
|
2003-04-04 16:15:15 +08:00
|
|
|
{"byte", tic4x_cons, 1},
|
|
|
|
{"bss", tic4x_bss, 0},
|
2002-11-11 22:29:01 +08:00
|
|
|
{"copy", s_include, 0},
|
2003-04-04 16:15:15 +08:00
|
|
|
{"def", tic4x_globl, 0},
|
|
|
|
{"equ", tic4x_set, 0},
|
|
|
|
{"eval", tic4x_eval, 0},
|
|
|
|
{"global", tic4x_globl, 0},
|
|
|
|
{"globl", tic4x_globl, 0},
|
|
|
|
{"hword", tic4x_cons, 2},
|
2002-08-28 18:38:51 +08:00
|
|
|
{"ieee", float_cons, 'i'},
|
2003-04-04 16:15:15 +08:00
|
|
|
{"int", tic4x_cons, 4}, /* .int allocates 4 bytes. */
|
2002-11-11 22:29:01 +08:00
|
|
|
{"ldouble", float_cons, 'e'},
|
2003-04-04 16:15:15 +08:00
|
|
|
{"newblock", tic4x_newblock, 0},
|
2002-11-11 22:29:01 +08:00
|
|
|
{"ref", s_ignore, 0}, /* All undefined treated as external. */
|
2003-04-04 16:15:15 +08:00
|
|
|
{"set", tic4x_set, 0},
|
|
|
|
{"sect", tic4x_sect, 1}, /* Define named section. */
|
2002-08-28 18:38:51 +08:00
|
|
|
{"space", s_space, 4},
|
2003-04-04 16:15:15 +08:00
|
|
|
{"string", tic4x_stringer, 0},
|
|
|
|
{"usect", tic4x_usect, 0}, /* Reserve space in uninit. named sect. */
|
|
|
|
{"version", tic4x_version, 0},
|
|
|
|
{"word", tic4x_cons, 4}, /* .word allocates 4 bytes. */
|
|
|
|
{"xdef", tic4x_globl, 0},
|
2002-08-28 18:38:51 +08:00
|
|
|
{NULL, 0, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
int md_short_jump_size = 4;
|
|
|
|
int md_long_jump_size = 4;
|
|
|
|
|
|
|
|
/* This array holds the chars that always start a comment. If the
|
|
|
|
pre-processor is disabled, these aren't very useful. */
|
2003-04-04 16:15:15 +08:00
|
|
|
#ifdef TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
const char comment_chars[] = ";!";
|
|
|
|
#else
|
|
|
|
const char comment_chars[] = ";";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* This array holds the chars that only start a comment at the beginning of
|
|
|
|
a line. If the line seems to have the form '# 123 filename'
|
2015-08-12 19:40:42 +08:00
|
|
|
.line and .file directives will appear in the pre-processed output.
|
2002-08-28 18:38:51 +08:00
|
|
|
Note that input_file.c hand checks for '#' at the beginning of the
|
|
|
|
first line of the input file. This is because the compiler outputs
|
2015-08-12 19:40:42 +08:00
|
|
|
#NO_APP at the beginning of its output.
|
2002-08-28 18:38:51 +08:00
|
|
|
Also note that comments like this one will always work. */
|
|
|
|
const char line_comment_chars[] = "#*";
|
|
|
|
|
|
|
|
/* We needed an unused char for line separation to work around the
|
|
|
|
lack of macros, using sed and such. */
|
|
|
|
const char line_separator_chars[] = "&";
|
|
|
|
|
|
|
|
/* Chars that can be used to separate mant from exp in floating point nums. */
|
|
|
|
const char EXP_CHARS[] = "eE";
|
|
|
|
|
|
|
|
/* Chars that mean this number is a floating point constant. */
|
|
|
|
/* As in 0f12.456 */
|
|
|
|
/* or 0d1.2345e12 */
|
|
|
|
const char FLT_CHARS[] = "fFilsS";
|
|
|
|
|
|
|
|
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
|
|
|
|
changed in read.c. Ideally it shouldn't have to know about it at
|
|
|
|
all, but nothing is ideal around here. */
|
|
|
|
|
|
|
|
/* Flonums returned here. */
|
|
|
|
extern FLONUM_TYPE generic_floating_point_number;
|
|
|
|
|
|
|
|
/* Precision in LittleNums. */
|
2017-01-23 23:23:07 +08:00
|
|
|
#define MAX_PRECISION (4) /* It's a bit overkill for us, but the code
|
2003-11-22 23:32:28 +08:00
|
|
|
requires it... */
|
2002-08-28 18:38:51 +08:00
|
|
|
#define S_PRECISION (1) /* Short float constants 16-bit. */
|
|
|
|
#define F_PRECISION (2) /* Float and double types 32-bit. */
|
2002-11-11 22:29:01 +08:00
|
|
|
#define E_PRECISION (4) /* Extended precision, 64-bit (real 40-bit). */
|
2002-08-28 18:38:51 +08:00
|
|
|
#define GUARD (2)
|
|
|
|
|
|
|
|
/* Turn generic_floating_point_number into a real short/float/double. */
|
2002-11-11 22:29:01 +08:00
|
|
|
static int
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_gen_to_words (FLONUM_TYPE flonum, LITTLENUM_TYPE *words, int precision)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
int return_value = 0;
|
|
|
|
LITTLENUM_TYPE *p; /* Littlenum pointer. */
|
|
|
|
int mantissa_bits; /* Bits in mantissa field. */
|
|
|
|
int exponent_bits; /* Bits in exponent field. */
|
|
|
|
int exponent;
|
|
|
|
unsigned int sone; /* Scaled one. */
|
|
|
|
unsigned int sfract; /* Scaled fraction. */
|
|
|
|
unsigned int smant; /* Scaled mantissa. */
|
|
|
|
unsigned int tmp;
|
2002-11-11 22:29:01 +08:00
|
|
|
unsigned int mover; /* Mantissa overflow bits */
|
|
|
|
unsigned int rbit; /* Round bit. */
|
2002-08-28 18:38:51 +08:00
|
|
|
int shift; /* Shift count. */
|
|
|
|
|
2005-02-28 02:44:55 +08:00
|
|
|
/* NOTE: Svein Seldal <Svein@dev.seldal.com>
|
2002-11-11 22:29:01 +08:00
|
|
|
The code in this function is altered slightly to support floats
|
|
|
|
with 31-bits mantissas, thus the documentation below may be a
|
|
|
|
little bit inaccurate.
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
By Michael P. Hayes <m.hayes@elec.canterbury.ac.nz>
|
|
|
|
Here is how a generic floating point number is stored using
|
2002-08-28 18:38:51 +08:00
|
|
|
flonums (an extension of bignums) where p is a pointer to an
|
|
|
|
array of LITTLENUMs.
|
|
|
|
|
|
|
|
For example 2e-3 is stored with exp = -4 and
|
|
|
|
bits[0] = 0x0000
|
|
|
|
bits[1] = 0x0000
|
|
|
|
bits[2] = 0x4fde
|
|
|
|
bits[3] = 0x978d
|
|
|
|
bits[4] = 0x126e
|
|
|
|
bits[5] = 0x0083
|
|
|
|
with low = &bits[2], high = &bits[5], and leader = &bits[5].
|
|
|
|
|
|
|
|
This number can be written as
|
|
|
|
0x0083126e978d4fde.00000000 * 65536**-4 or
|
|
|
|
0x0.0083126e978d4fde * 65536**0 or
|
|
|
|
0x0.83126e978d4fde * 2**-8 = 2e-3
|
|
|
|
|
|
|
|
Note that low points to the 65536**0 littlenum (bits[2]) and
|
|
|
|
leader points to the most significant non-zero littlenum
|
|
|
|
(bits[5]).
|
|
|
|
|
|
|
|
TMS320C3X floating point numbers are a bit of a strange beast.
|
|
|
|
The 32-bit flavour has the 8 MSBs representing the exponent in
|
|
|
|
twos complement format (-128 to +127). There is then a sign bit
|
|
|
|
followed by 23 bits of mantissa. The mantissa is expressed in
|
|
|
|
twos complement format with the binary point after the most
|
|
|
|
significant non sign bit. The bit after the binary point is
|
|
|
|
suppressed since it is the complement of the sign bit. The
|
|
|
|
effective mantissa is thus 24 bits. Zero is represented by an
|
|
|
|
exponent of -128.
|
|
|
|
|
|
|
|
The 16-bit flavour has the 4 MSBs representing the exponent in
|
|
|
|
twos complement format (-8 to +7). There is then a sign bit
|
|
|
|
followed by 11 bits of mantissa. The mantissa is expressed in
|
|
|
|
twos complement format with the binary point after the most
|
|
|
|
significant non sign bit. The bit after the binary point is
|
|
|
|
suppressed since it is the complement of the sign bit. The
|
|
|
|
effective mantissa is thus 12 bits. Zero is represented by an
|
|
|
|
exponent of -8. For example,
|
|
|
|
|
|
|
|
number norm mant m x e s i fraction f
|
|
|
|
+0.500 => 1.00000000000 -1 -1 0 1 .00000000000 (1 + 0) * 2^(-1)
|
|
|
|
+0.999 => 1.11111111111 -1 -1 0 1 .11111111111 (1 + 0.99) * 2^(-1)
|
|
|
|
+1.000 => 1.00000000000 0 0 0 1 .00000000000 (1 + 0) * 2^(0)
|
|
|
|
+1.500 => 1.10000000000 0 0 0 1 .10000000000 (1 + 0.5) * 2^(0)
|
|
|
|
+1.999 => 1.11111111111 0 0 0 1 .11111111111 (1 + 0.9) * 2^(0)
|
|
|
|
+2.000 => 1.00000000000 1 1 0 1 .00000000000 (1 + 0) * 2^(1)
|
|
|
|
+4.000 => 1.00000000000 2 2 0 1 .00000000000 (1 + 0) * 2^(2)
|
|
|
|
-0.500 => 1.00000000000 -1 -1 1 0 .10000000000 (-2 + 0) * 2^(-2)
|
|
|
|
-1.000 => 1.00000000000 0 -1 1 0 .00000000000 (-2 + 0) * 2^(-1)
|
|
|
|
-1.500 => 1.10000000000 0 0 1 0 .10000000000 (-2 + 0.5) * 2^(0)
|
|
|
|
-1.999 => 1.11111111111 0 0 1 0 .00000000001 (-2 + 0.11) * 2^(0)
|
|
|
|
-2.000 => 1.00000000000 1 1 1 0 .00000000000 (-2 + 0) * 2^(0)
|
|
|
|
-4.000 => 1.00000000000 2 1 1 0 .00000000000 (-2 + 0) * 2^(1)
|
|
|
|
|
|
|
|
where e is the exponent, s is the sign bit, i is the implied bit,
|
|
|
|
and f is the fraction stored in the mantissa field.
|
|
|
|
|
|
|
|
num = (1 + f) * 2^x = m * 2^e if s = 0
|
|
|
|
num = (-2 + f) * 2^x = -m * 2^e if s = 1
|
|
|
|
where 0 <= f < 1.0 and 1.0 <= m < 2.0
|
|
|
|
|
|
|
|
The fraction (f) and exponent (e) fields for the TMS320C3X format
|
|
|
|
can be derived from the normalised mantissa (m) and exponent (x) using:
|
|
|
|
|
|
|
|
f = m - 1, e = x if s = 0
|
|
|
|
f = 2 - m, e = x if s = 1 and m != 1.0
|
|
|
|
f = 0, e = x - 1 if s = 1 and m = 1.0
|
|
|
|
f = 0, e = -8 if m = 0
|
|
|
|
|
|
|
|
|
|
|
|
OK, the other issue we have to consider is rounding since the
|
|
|
|
mantissa has a much higher potential precision than what we can
|
|
|
|
represent. To do this we add half the smallest storable fraction.
|
|
|
|
We then have to renormalise the number to allow for overflow.
|
|
|
|
|
|
|
|
To convert a generic flonum into a TMS320C3X floating point
|
|
|
|
number, here's what we try to do....
|
|
|
|
|
|
|
|
The first thing is to generate a normalised mantissa (m) where
|
|
|
|
1.0 <= m < 2 and to convert the exponent from base 16 to base 2.
|
|
|
|
We desire the binary point to be placed after the most significant
|
|
|
|
non zero bit. This process is done in two steps: firstly, the
|
|
|
|
littlenum with the most significant non zero bit is located (this
|
|
|
|
is done for us since leader points to this littlenum) and the
|
|
|
|
binary point (which is currently after the LSB of the littlenum
|
|
|
|
pointed to by low) is moved to before the MSB of the littlenum
|
|
|
|
pointed to by leader. This requires the exponent to be adjusted
|
|
|
|
by leader - low + 1. In the earlier example, the new exponent is
|
|
|
|
thus -4 + (5 - 2 + 1) = 0 (base 65536). We now need to convert
|
|
|
|
the exponent to base 2 by multiplying the exponent by 16 (log2
|
|
|
|
65536). The exponent base 2 is thus also zero.
|
|
|
|
|
|
|
|
The second step is to hunt for the most significant non zero bit
|
|
|
|
in the leader littlenum. We do this by left shifting a copy of
|
|
|
|
the leader littlenum until bit 16 is set (0x10000) and counting
|
|
|
|
the number of shifts, S, required. The number of shifts then has to
|
|
|
|
be added to correct the exponent (base 2). For our example, this
|
|
|
|
will require 9 shifts and thus our normalised exponent (base 2) is
|
|
|
|
0 + 9 = 9. Note that the worst case scenario is when the leader
|
|
|
|
littlenum is 1, thus requiring 16 shifts.
|
|
|
|
|
|
|
|
We now have to left shift the other littlenums by the same amount,
|
|
|
|
propagating the shifted bits into the more significant littlenums.
|
2003-11-22 23:32:28 +08:00
|
|
|
To save a lot of unnecessary shifting we only have to consider
|
2002-08-28 18:38:51 +08:00
|
|
|
two or three littlenums, since the greatest number of mantissa
|
|
|
|
bits required is 24 + 1 rounding bit. While two littlenums
|
|
|
|
provide 32 bits of precision, the most significant littlenum
|
|
|
|
may only contain a single significant bit and thus an extra
|
|
|
|
littlenum is required.
|
|
|
|
|
|
|
|
Denoting the number of bits in the fraction field as F, we require
|
|
|
|
G = F + 2 bits (one extra bit is for rounding, the other gets
|
|
|
|
suppressed). Say we required S shifts to find the most
|
|
|
|
significant bit in the leader littlenum, the number of left shifts
|
|
|
|
required to move this bit into bit position G - 1 is L = G + S - 17.
|
|
|
|
Note that this shift count may be negative for the short floating
|
|
|
|
point flavour (where F = 11 and thus G = 13 and potentially S < 3).
|
|
|
|
If L > 0 we have to shunt the next littlenum into position. Bit
|
|
|
|
15 (the MSB) of the next littlenum needs to get moved into position
|
|
|
|
L - 1 (If L > 15 we need all the bits of this littlenum and
|
|
|
|
some more from the next one.). We subtract 16 from L and use this
|
|
|
|
as the left shift count; the resultant value we or with the
|
|
|
|
previous result. If L > 0, we repeat this operation. */
|
|
|
|
|
|
|
|
if (precision != S_PRECISION)
|
|
|
|
words[1] = 0x0000;
|
2002-11-11 22:29:01 +08:00
|
|
|
if (precision == E_PRECISION)
|
|
|
|
words[2] = words[3] = 0x0000;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
/* 0.0e0 or NaN seen. */
|
|
|
|
if (flonum.low > flonum.leader /* = 0.0e0 */
|
2021-08-11 15:44:40 +08:00
|
|
|
|| flonum.sign == 0 /* = NaN */
|
gas: support NaN flavors
Like for infinity, there isn't just a single NaN. The sign bit may be
of interest and, going beyond infinity, whether the value is quiet or
signalling may be even more relevant to be able to encode.
Note that an anomaly with x86'es double extended precision NaN values
gets taken care of at the same time: For all other formats a positive
value with all mantissa bits set was used, while here a negative value
with all non-significant mantissa bits clear was chose for an unknown
reason.
For m68k, since I don't know their X_PRECISION floating point value
layout, a warning gets issued if any of the new flavors was attempted
to be encoded that way. However likely it may be that, given that the
code lives in a source file supposedly implementing IEEE-compliant
formats, the bit patterns of the individual words match x86'es, I didn't
want to guess so. And my very, very old paper doc doesn't even mention
floating point formats other than single and double.
2021-08-11 14:36:28 +08:00
|
|
|
|| flonum.sign == 'Q' || flonum.sign == 'q' /* = QNaN */
|
2021-08-11 15:44:40 +08:00
|
|
|
|| flonum.sign == 'S' || flonum.sign == 's') /* = SNaN */
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
gas: support NaN flavors
Like for infinity, there isn't just a single NaN. The sign bit may be
of interest and, going beyond infinity, whether the value is quiet or
signalling may be even more relevant to be able to encode.
Note that an anomaly with x86'es double extended precision NaN values
gets taken care of at the same time: For all other formats a positive
value with all mantissa bits set was used, while here a negative value
with all non-significant mantissa bits clear was chose for an unknown
reason.
For m68k, since I don't know their X_PRECISION floating point value
layout, a warning gets issued if any of the new flavors was attempted
to be encoded that way. However likely it may be that, given that the
code lives in a source file supposedly implementing IEEE-compliant
formats, the bit patterns of the individual words match x86'es, I didn't
want to guess so. And my very, very old paper doc doesn't even mention
floating point formats other than single and double.
2021-08-11 14:36:28 +08:00
|
|
|
if (flonum.sign != '+' && flonum.sign != '-')
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Nan, using zero."));
|
2002-08-28 18:38:51 +08:00
|
|
|
words[0] = 0x8000;
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
if (flonum.sign == 'P')
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* +INF: Replace with maximum float. */
|
|
|
|
if (precision == S_PRECISION)
|
|
|
|
words[0] = 0x77ff;
|
2015-08-12 19:40:42 +08:00
|
|
|
else
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
words[0] = 0x7f7f;
|
|
|
|
words[1] = 0xffff;
|
|
|
|
}
|
2002-11-11 22:29:01 +08:00
|
|
|
if (precision == E_PRECISION)
|
|
|
|
{
|
|
|
|
words[2] = 0x7fff;
|
|
|
|
words[3] = 0xffff;
|
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
else if (flonum.sign == 'N')
|
|
|
|
{
|
|
|
|
/* -INF: Replace with maximum float. */
|
|
|
|
if (precision == S_PRECISION)
|
|
|
|
words[0] = 0x7800;
|
2015-08-12 19:40:42 +08:00
|
|
|
else
|
2002-11-11 22:29:01 +08:00
|
|
|
words[0] = 0x7f80;
|
|
|
|
if (precision == E_PRECISION)
|
|
|
|
words[2] = 0x8000;
|
2002-08-28 18:38:51 +08:00
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
exponent = (flonum.exponent + flonum.leader - flonum.low + 1) * 16;
|
|
|
|
|
|
|
|
if (!(tmp = *flonum.leader))
|
|
|
|
abort (); /* Hmmm. */
|
|
|
|
shift = 0; /* Find position of first sig. bit. */
|
|
|
|
while (tmp >>= 1)
|
|
|
|
shift++;
|
|
|
|
exponent -= (16 - shift); /* Adjust exponent. */
|
|
|
|
|
|
|
|
if (precision == S_PRECISION) /* Allow 1 rounding bit. */
|
|
|
|
{
|
|
|
|
exponent_bits = 4;
|
2002-11-11 22:29:01 +08:00
|
|
|
mantissa_bits = 11;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
2002-11-11 22:29:01 +08:00
|
|
|
else if(precision == F_PRECISION)
|
|
|
|
{
|
|
|
|
exponent_bits = 8;
|
|
|
|
mantissa_bits = 23;
|
|
|
|
}
|
|
|
|
else /* E_PRECISION */
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
exponent_bits = 8;
|
2002-11-11 22:29:01 +08:00
|
|
|
mantissa_bits = 31;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
shift = mantissa_bits - shift;
|
|
|
|
|
|
|
|
smant = 0;
|
2002-11-11 22:29:01 +08:00
|
|
|
mover = 0;
|
|
|
|
rbit = 0;
|
|
|
|
/* Store the mantissa data into smant and the roundbit into rbit */
|
2002-08-28 18:38:51 +08:00
|
|
|
for (p = flonum.leader; p >= flonum.low && shift > -16; p--)
|
|
|
|
{
|
2020-08-30 22:13:54 +08:00
|
|
|
tmp = shift >= 0 ? (unsigned) *p << shift : (unsigned) *p >> -shift;
|
|
|
|
rbit = shift < 0 ? (((unsigned) *p >> (-shift-1)) & 0x1) : 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
smant |= tmp;
|
|
|
|
shift -= 16;
|
|
|
|
}
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
/* OK, we've got our scaled mantissa so let's round it up */
|
|
|
|
if(rbit)
|
|
|
|
{
|
|
|
|
/* If the mantissa is going to overflow when added, lets store
|
2020-08-30 22:13:54 +08:00
|
|
|
the extra bit in mover. */
|
|
|
|
if (smant == (1u << mantissa_bits << 1) - 1)
|
2002-11-11 22:29:01 +08:00
|
|
|
mover=1;
|
|
|
|
smant++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the scaled one value */
|
2020-08-30 22:13:54 +08:00
|
|
|
sone = 1u << mantissa_bits;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* The number may be unnormalised so renormalise it... */
|
2002-11-11 22:29:01 +08:00
|
|
|
if(mover)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
smant >>= 1;
|
2002-11-11 22:29:01 +08:00
|
|
|
smant |= sone; /* Insert the bit from mover into smant */
|
2002-08-28 18:38:51 +08:00
|
|
|
exponent++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The binary point is now between bit positions 11 and 10 or 23 and 22,
|
|
|
|
i.e., between mantissa_bits - 1 and mantissa_bits - 2 and the
|
|
|
|
bit at mantissa_bits - 1 should be set. */
|
2002-11-11 22:29:01 +08:00
|
|
|
if (!(sone&smant))
|
|
|
|
abort (); /* Ooops. */
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
if (flonum.sign == '+')
|
|
|
|
sfract = smant - sone; /* smant - 1.0. */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* This seems to work. */
|
|
|
|
if (smant == sone)
|
|
|
|
{
|
|
|
|
exponent--;
|
|
|
|
sfract = 0;
|
|
|
|
}
|
|
|
|
else
|
2002-11-11 22:29:01 +08:00
|
|
|
{
|
|
|
|
sfract = -smant & (sone-1); /* 2.0 - smant. */
|
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
sfract |= sone; /* Insert sign bit. */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (abs (exponent) >= (1 << (exponent_bits - 1)))
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Cannot represent exponent in %d bits"), exponent_bits);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Force exponent to fit in desired field width. */
|
|
|
|
exponent &= (1 << (exponent_bits)) - 1;
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
if (precision == E_PRECISION)
|
|
|
|
{
|
|
|
|
/* Map the float part first (100% equal format as F_PRECISION) */
|
|
|
|
words[0] = exponent << (mantissa_bits+1-24);
|
|
|
|
words[0] |= sfract >> 24;
|
|
|
|
words[1] = sfract >> 8;
|
|
|
|
|
|
|
|
/* Map the mantissa in the next */
|
|
|
|
words[2] = sfract >> 16;
|
|
|
|
words[3] = sfract & 0xffff;
|
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
|
|
|
{
|
2002-11-11 22:29:01 +08:00
|
|
|
/* Insert the exponent data into the word */
|
2020-08-30 22:13:54 +08:00
|
|
|
sfract |= (unsigned) exponent << (mantissa_bits + 1);
|
2002-11-11 22:29:01 +08:00
|
|
|
|
|
|
|
if (precision == S_PRECISION)
|
|
|
|
words[0] = sfract;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
words[0] = sfract >> 16;
|
|
|
|
words[1] = sfract & 0xffff;
|
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns pointer past text consumed. */
|
2002-11-11 22:29:01 +08:00
|
|
|
static char *
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_atof (char *str, char what_kind, LITTLENUM_TYPE *words)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are
|
|
|
|
zeroed, the last contain flonum bits. */
|
|
|
|
static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
|
|
|
|
char *return_value;
|
|
|
|
/* Number of 16-bit words in the format. */
|
|
|
|
int precision;
|
|
|
|
FLONUM_TYPE save_gen_flonum;
|
|
|
|
|
|
|
|
/* We have to save the generic_floating_point_number because it
|
|
|
|
contains storage allocation about the array of LITTLENUMs where
|
|
|
|
the value is actually stored. We will allocate our own array of
|
|
|
|
littlenums below, but have to restore the global one on exit. */
|
|
|
|
save_gen_flonum = generic_floating_point_number;
|
|
|
|
|
|
|
|
return_value = str;
|
|
|
|
generic_floating_point_number.low = bits + MAX_PRECISION;
|
|
|
|
generic_floating_point_number.high = NULL;
|
|
|
|
generic_floating_point_number.leader = NULL;
|
|
|
|
generic_floating_point_number.exponent = 0;
|
|
|
|
generic_floating_point_number.sign = '\0';
|
|
|
|
|
|
|
|
/* Use more LittleNums than seems necessary: the highest flonum may
|
|
|
|
have 15 leading 0 bits, so could be useless. */
|
|
|
|
|
|
|
|
memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
|
|
|
|
|
|
|
|
switch (what_kind)
|
|
|
|
{
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
precision = S_PRECISION;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
case 'D':
|
|
|
|
case 'f':
|
|
|
|
case 'F':
|
|
|
|
precision = F_PRECISION;
|
|
|
|
break;
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
case 'E':
|
|
|
|
case 'e':
|
|
|
|
precision = E_PRECISION;
|
|
|
|
break;
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
default:
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid floating point number"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
generic_floating_point_number.high
|
|
|
|
= generic_floating_point_number.low + precision - 1 + GUARD;
|
|
|
|
|
|
|
|
if (atof_generic (&return_value, ".", EXP_CHARS,
|
|
|
|
&generic_floating_point_number))
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid floating point number"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_gen_to_words (generic_floating_point_number,
|
2002-08-28 18:38:51 +08:00
|
|
|
words, precision);
|
|
|
|
|
|
|
|
/* Restore the generic_floating_point_number's storage alloc (and
|
|
|
|
everything else). */
|
|
|
|
generic_floating_point_number = save_gen_flonum;
|
|
|
|
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2016-03-07 23:16:28 +08:00
|
|
|
tic4x_insert_reg (const char *regname, int regnum)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char buf[32];
|
|
|
|
int i;
|
|
|
|
|
2020-08-21 07:47:53 +08:00
|
|
|
symbol_table_insert (symbol_new (regname, reg_section,
|
|
|
|
&zero_address_frag, regnum));
|
2002-08-28 18:38:51 +08:00
|
|
|
for (i = 0; regname[i]; i++)
|
2005-02-17 21:46:05 +08:00
|
|
|
buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
|
2002-08-28 18:38:51 +08:00
|
|
|
buf[i] = '\0';
|
|
|
|
|
2020-08-21 07:47:53 +08:00
|
|
|
symbol_table_insert (symbol_new (buf, reg_section,
|
|
|
|
&zero_address_frag, regnum));
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2016-03-07 23:16:28 +08:00
|
|
|
tic4x_insert_sym (const char *symname, int value)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
|
|
|
symbolP = symbol_new (symname, absolute_section,
|
2020-08-21 07:47:53 +08:00
|
|
|
&zero_address_frag, value);
|
2002-08-28 18:38:51 +08:00
|
|
|
SF_SET_LOCAL (symbolP);
|
|
|
|
symbol_table_insert (symbolP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_expression (char *str, expressionS *exp)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
char *t;
|
|
|
|
|
|
|
|
t = input_line_pointer; /* Save line pointer. */
|
|
|
|
input_line_pointer = str;
|
|
|
|
expression (exp);
|
gas: equates of registers
There are two problems: symbol_equated_p() doesn't recognize equates of
registers, and S_CAN_BE_REDEFINED() goes by section rather than by
expression type. Both together undermine .eqv and .equiv clearly meaning
to guard the involved symbols against re-definition (both ways).
To compensate pseudo_set() now using O_symbol and S_CAN_BE_REDEFINED()
now checking for O_register,
- for targets creating register symbols through symbol_{new,create}() ->
symbol_init() -> S_SET_VALUE() (alpha, arc, dlx, ia64, m68k, mips,
mmix, tic4x, tic54x, plus anything using cgen or itbl-ops), have
symbol_init() set their expressions to O_register,
- x86'es parse_register() also can't go by section anymore when
trying to "look through" equates; probably symbol_equated_p() should
have been used there from the beginning, if only that had worked for
equates of registers,
- various targets need to "look through" equates when parsing insn
operands (which also helps transitive forward equates); perhaps even
more ought to, but many don't look to consider the possibility of
register equates in the first place.
This was uncovered by code reported in PR gas/30274 (duplicating
PR gas/30272), except that there .eqv was used when really .equ was
meant. Therefore that bug report is addressed here only in so far as
gas wouldn't crash anymore; the code there still won't assemble
successfully, just that now the issues there are properly diagnosed.
2023-05-12 14:55:48 +08:00
|
|
|
resolve_register (exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
s = input_line_pointer;
|
|
|
|
input_line_pointer = t; /* Restore line pointer. */
|
|
|
|
return s; /* Return pointer to where parsing stopped. */
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_expression_abs (char *str, offsetT *value)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
char *t;
|
|
|
|
|
|
|
|
t = input_line_pointer; /* Save line pointer. */
|
|
|
|
input_line_pointer = str;
|
|
|
|
*value = get_absolute_expression ();
|
|
|
|
s = input_line_pointer;
|
|
|
|
input_line_pointer = t; /* Restore line pointer. */
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_emit_char (char c, int b)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
exp.X_op = O_constant;
|
|
|
|
exp.X_add_number = c;
|
2002-11-11 22:29:01 +08:00
|
|
|
emit_expr (&exp, b);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_seg_alloc (char *name ATTRIBUTE_UNUSED,
|
|
|
|
segT seg ATTRIBUTE_UNUSED,
|
|
|
|
int size,
|
|
|
|
symbolS *symbolP)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* Note that the size is in words
|
|
|
|
so we multiply it by 4 to get the number of bytes to allocate. */
|
|
|
|
|
|
|
|
/* If we have symbol: .usect ".fred", size etc.,
|
|
|
|
the symbol needs to point to the first location reserved
|
|
|
|
by the pseudo op. */
|
|
|
|
|
|
|
|
if (size)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0,
|
|
|
|
(symbolS *) symbolP,
|
|
|
|
size * OCTETS_PER_BYTE, (char *) 0);
|
|
|
|
*p = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* .asg ["]character-string["], symbol */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_asg (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char c;
|
|
|
|
char *name;
|
|
|
|
char *str;
|
2022-07-06 08:24:21 +08:00
|
|
|
size_t len;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
str = input_line_pointer;
|
|
|
|
|
|
|
|
/* Skip string expression. */
|
|
|
|
while (*input_line_pointer != ',' && *input_line_pointer)
|
|
|
|
input_line_pointer++;
|
|
|
|
if (*input_line_pointer != ',')
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Comma expected\n"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return;
|
|
|
|
}
|
2022-07-06 08:24:21 +08:00
|
|
|
len = input_line_pointer - str;
|
|
|
|
str = notes_memdup (str, len, len + 1);
|
|
|
|
input_line_pointer++;
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (&name); /* Get terminator. */
|
2022-07-06 08:24:21 +08:00
|
|
|
name = notes_strdup (name);
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
str_hash_insert (tic4x_asg_hash, name, str, 1);
|
2015-08-21 23:42:14 +08:00
|
|
|
(void) restore_line_pointer (c);
|
2002-08-28 18:38:51 +08:00
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* .bss symbol, size */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_bss (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char c;
|
|
|
|
char *name;
|
|
|
|
char *p;
|
2005-02-23 20:28:06 +08:00
|
|
|
offsetT size;
|
2002-08-28 18:38:51 +08:00
|
|
|
segT current_seg;
|
|
|
|
subsegT current_subseg;
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
|
|
|
current_seg = now_seg; /* Save current seg. */
|
|
|
|
current_subseg = now_subseg; /* Save current subseg. */
|
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (&name); /* Get terminator. */
|
|
|
|
if (c == '"')
|
|
|
|
c = * ++ input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
if (c != ',')
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_(".bss size argument missing\n"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (++input_line_pointer, &size);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (size < 0)
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_(".bss size %ld < 0!"), (long) size);
|
2002-08-28 18:38:51 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
subseg_set (bss_section, 0);
|
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
|
|
|
|
if (S_GET_SEGMENT (symbolP) == bss_section)
|
|
|
|
symbol_get_frag (symbolP)->fr_symbol = 0;
|
|
|
|
|
|
|
|
symbol_set_frag (symbolP, frag_now);
|
|
|
|
|
|
|
|
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
|
|
|
|
size * OCTETS_PER_BYTE, (char *) 0);
|
|
|
|
*p = 0; /* Fill char. */
|
|
|
|
|
|
|
|
S_SET_SEGMENT (symbolP, bss_section);
|
|
|
|
|
|
|
|
/* The symbol may already have been created with a preceding
|
|
|
|
".globl" directive -- be careful not to step on storage class
|
|
|
|
in that case. Otherwise, set it to static. */
|
|
|
|
if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
|
|
|
|
S_SET_STORAGE_CLASS (symbolP, C_STAT);
|
|
|
|
|
|
|
|
subseg_set (current_seg, current_subseg); /* Restore current seg. */
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_globl (int ignore ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int c;
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (&name);
|
2002-08-28 18:38:51 +08:00
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
*input_line_pointer = c;
|
2015-08-21 23:42:14 +08:00
|
|
|
SKIP_WHITESPACE_AFTER_NAME ();
|
2002-08-28 18:38:51 +08:00
|
|
|
S_SET_STORAGE_CLASS (symbolP, C_EXT);
|
2008-09-30 18:50:03 +08:00
|
|
|
S_SET_EXTERNAL (symbolP);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (c == ',')
|
|
|
|
{
|
|
|
|
input_line_pointer++;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '\n')
|
|
|
|
c = '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (c == ',');
|
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle .byte, .word. .int, .long */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_cons (int bytes)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
Don't use register keyword
* expr.c (expr_symbol_where): Don't use register keyword.
* app.c (app_push, app_pop, do_scrub_chars): Likewise.
* ecoff.c (add_string, add_ecoff_symbol, add_aux_sym_symint,
add_aux_sym_rndx, add_aux_sym_tir, add_procedure, add_file,
ecoff_build_lineno, ecoff_setup_ext, allocate_cluster.
allocate_scope, allocate_vlinks, allocate_shash,
allocate_thash, allocate_tag, allocate_forward, allocate_thead,
allocate_lineno_list): Likewise.
* frags.c (frag_more, frag_var, frag_variant, frag_wane): Likewise.
* input-file.c (input_file_push, input_file_pop): Likewise.
* input-scrub.c (input_scrub_push, input_scrub_next_buffer): Likewise.
* subsegs.c (subseg_change): Likewise.
* symbols.c (colon, symbol_table_insert, symbol_find_or_make)
(dollar_label_name, fb_label_name): Likewise.
* write.c (relax_align): Likewise.
* config/tc-alpha.c (s_alpha_pdesc): Likewise.
* config/tc-bfin.c (bfin_s_bss): Likewise.
* config/tc-i860.c (md_estimate_size_before_relax): Likewise.
* config/tc-m68hc11.c (md_convert_frag): Likewise.
* config/tc-m68k.c (m68k_ip, crack_operand): Likewise.
(md_convert_frag_1, s_even): Likewise.
* config/tc-mips.c (mips_clear_insn_labels): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sh.c (sh_elf_cons): Likewise.
* config/tc-tic4x.c (tic4x_cons, tic4x_stringer): Likewise.
* config/m68k-parse.y (m68k_reg_parse): Likewise. Convert from K&R.
(yylex, m68k_ip_op, yyerror): Convert from K&R.
2014-11-04 13:01:09 +08:00
|
|
|
unsigned int c;
|
2002-08-28 18:38:51 +08:00
|
|
|
do
|
|
|
|
{
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '"')
|
|
|
|
{
|
|
|
|
input_line_pointer++;
|
|
|
|
while (is_a_char (c = next_char_of_string ()))
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_emit_char (c, 4);
|
2002-08-28 18:38:51 +08:00
|
|
|
know (input_line_pointer[-1] == '\"');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
expressionS exp;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (input_line_pointer, &exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp.X_op == O_constant)
|
|
|
|
{
|
|
|
|
switch (bytes)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
exp.X_add_number &= 255;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
exp.X_add_number &= 65535;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Perhaps we should disallow .byte and .hword with
|
|
|
|
a non constant expression that will require relocation. */
|
|
|
|
emit_expr (&exp, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (*input_line_pointer++ == ',');
|
|
|
|
|
|
|
|
input_line_pointer--; /* Put terminator back into stream. */
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
/* Handle .ascii, .asciz, .string */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_stringer (int append_zero)
|
2002-11-11 22:29:01 +08:00
|
|
|
{
|
|
|
|
int bytes;
|
Don't use register keyword
* expr.c (expr_symbol_where): Don't use register keyword.
* app.c (app_push, app_pop, do_scrub_chars): Likewise.
* ecoff.c (add_string, add_ecoff_symbol, add_aux_sym_symint,
add_aux_sym_rndx, add_aux_sym_tir, add_procedure, add_file,
ecoff_build_lineno, ecoff_setup_ext, allocate_cluster.
allocate_scope, allocate_vlinks, allocate_shash,
allocate_thash, allocate_tag, allocate_forward, allocate_thead,
allocate_lineno_list): Likewise.
* frags.c (frag_more, frag_var, frag_variant, frag_wane): Likewise.
* input-file.c (input_file_push, input_file_pop): Likewise.
* input-scrub.c (input_scrub_push, input_scrub_next_buffer): Likewise.
* subsegs.c (subseg_change): Likewise.
* symbols.c (colon, symbol_table_insert, symbol_find_or_make)
(dollar_label_name, fb_label_name): Likewise.
* write.c (relax_align): Likewise.
* config/tc-alpha.c (s_alpha_pdesc): Likewise.
* config/tc-bfin.c (bfin_s_bss): Likewise.
* config/tc-i860.c (md_estimate_size_before_relax): Likewise.
* config/tc-m68hc11.c (md_convert_frag): Likewise.
* config/tc-m68k.c (m68k_ip, crack_operand): Likewise.
(md_convert_frag_1, s_even): Likewise.
* config/tc-mips.c (mips_clear_insn_labels): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sh.c (sh_elf_cons): Likewise.
* config/tc-tic4x.c (tic4x_cons, tic4x_stringer): Likewise.
* config/m68k-parse.y (m68k_reg_parse): Likewise. Convert from K&R.
(yylex, m68k_ip_op, yyerror): Convert from K&R.
2014-11-04 13:01:09 +08:00
|
|
|
unsigned int c;
|
2002-11-11 22:29:01 +08:00
|
|
|
|
|
|
|
bytes = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '"')
|
|
|
|
{
|
|
|
|
input_line_pointer++;
|
|
|
|
while (is_a_char (c = next_char_of_string ()))
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_emit_char (c, 1);
|
2002-11-11 22:29:01 +08:00
|
|
|
bytes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (append_zero)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_emit_char (c, 1);
|
2002-11-11 22:29:01 +08:00
|
|
|
bytes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
know (input_line_pointer[-1] == '\"');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
expressionS exp;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (input_line_pointer, &exp);
|
2002-11-11 22:29:01 +08:00
|
|
|
if (exp.X_op != O_constant)
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Non-constant symbols not allowed\n"));
|
2002-11-11 22:29:01 +08:00
|
|
|
return;
|
|
|
|
}
|
2017-01-23 23:23:07 +08:00
|
|
|
exp.X_add_number &= 255; /* Limit number to 8-bit */
|
2002-11-11 22:29:01 +08:00
|
|
|
emit_expr (&exp, 1);
|
|
|
|
bytes++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (*input_line_pointer++ == ',');
|
|
|
|
|
|
|
|
/* Fill out the rest of the expression with 0's to fill up a full word */
|
|
|
|
if ( bytes&0x3 )
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_emit_char (0, 4-(bytes&0x3));
|
2002-11-11 22:29:01 +08:00
|
|
|
|
|
|
|
input_line_pointer--; /* Put terminator back into stream. */
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
/* .eval expression, symbol */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_eval (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char c;
|
2005-02-23 20:28:06 +08:00
|
|
|
offsetT value;
|
2002-08-28 18:38:51 +08:00
|
|
|
char *name;
|
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (input_line_pointer, &value);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (*input_line_pointer++ != ',')
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Symbol missing\n"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return;
|
|
|
|
}
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (&name); /* Get terminator. */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_insert_sym (name, value);
|
2015-08-21 23:42:14 +08:00
|
|
|
(void) restore_line_pointer (c);
|
* config/obj-evax.h (S_SET_OTHER, S_SET_TYPE, S_SET_DESC): Don't define.
* config/tc-crx.c (gettrap): Constify arg.
(handle_LoadStor, get_cinv_parameters): Likewise.
(getreg_image): Fix enum warning
(md_assemble): Restore input line char.
* config/tc-hppa.c (tc_gen_reloc): Fix enum warning.
* config/tc-i960.c (mem_fmt): Rename var to fix shadow warning.
* config/tc-sh.c (sh_fdpic): Only define when OBJ_ELF.
(build_Mytes): Fix build failure for non-elf targets.
* config/tc-tic4x.c (tic4x_eval): Restore terminator char.
* config/tc-xtensa.c (xtensa_end_directive): Fix switch enum warning.
* cgen.c (gas_cgen_md_apply_fix): Avoid set but unused warning.
* ecoff.c (add_ecoff_symbol): Likewise.
* itbl-ops.c (append_insns_as_macros): Likewise.
* listing.c (debugging_pseudo): Likewise.
* read.c (s_mri_common, stringer): Likewise.
* config/obj-coff.c (coff_frob_section): Likewise.
* config/tc-alpha.c (emit_ldgp, s_alpha_proc): Likewise.
* config/tc-arm.c (my_get_expression): Likewise.
* config/tc-hppa.c (process_exit, pa_type_args): Likewise.
* config/tc-m32c.c (md_assemble): Likewise.
* config/tc-microblaze.c (md_convert_frag): Likewise.
* config/tc-mips.c (s_change_section): Likewise.
* config/tc-mt.c (mt_fix_adjustable): Likewise.
* config/tc-xtensa.c (xtensa_literal_pseudo): Likewise.
* config/obj-aout.c (obj_aout_frob_symbol): Delete set but otherwise
unused vars.
* config/tc-alpha.c (load_expression): Likewise.
(s_alpha_rdata, s_alpha_section, s_alpha_prologue): Likewise.
* config/tc-arm.c (parse_neon_el_struct_list): Likewise.
* config/tc-avr.c (extract_word): Likewise.
* config/tc-cris.c (cris_get_expression): Likewise.
* config/tc-d30v.c (build_insn, find_format): Likewise.
* config/tc-dlx.c (machine_ip): Likewise.
* config/tc-hppa.c (pa_get_absolute_expression): Likewise.
* config/tc-i370.c (md_assemble): Likewise.
* config/tc-i960.c (brtab_emit): Likewise.
* config/tc-iq2000.c (s_iq2000_ent): Likewise.
* config/tc-m32c.c (md_convert_frag): Likewise.
* config/tc-m68hc11.c (fixup24, build_jump_insn): Likewise.
(md_estimate_size_before_relax, md_apply_fix): Likewise.
* config/tc-m68k.c (md_show_usage): Likewise.
* config/tc-microblaze.c (microblaze_s_lcomm): Likewise.
* config/tc-mips.c (s_mips_end): Likewise.
* config/tc-mmix.c (mmix_byte, mmix_cons): Likewise.
* config/tc-mn10300.c (md_assemble): Likewise.
* config/tc-msp430.c (extract_word): Likewise.
* config/tc-mt.c (md_assemble): Likewise.
* config/tc-or32.c (machine_ip): Likewise.
* config/tc-pj.c (md_apply_fix): Likewise.
* config/tc-s390.c (md_gather_operands): Likewise.
* config/tc-sh.c (sh_cons_align): Likewise.
* config/tc-sparc.c (sparc_cons_align): Likewise.
* config/tc-tic4x.c (tic4x_sect): Likewise.
* config/tc-tic54x.c (tic54x_stringer): Likewise.
* config/tc-vax.c (vip_op): Likewise.
* config/tc-xstormy16.c (xstormy16_cons_fix_new): Likewise.
* config/tc-xtensa.c (md_assemble): Likewise.
(xtensa_fix_short_loop_frags, convert_frag_immed): Likewise.
(xtensa_move_literals): Likewise.
2010-06-28 22:06:57 +08:00
|
|
|
demand_empty_rest_of_line ();
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset local labels. */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_newblock (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
dollar_label_clear ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* .sect "section-name" [, value] */
|
|
|
|
/* .sect ["]section-name[:subsection-name]["] [, value] */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_sect (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char c;
|
|
|
|
char *section_name;
|
|
|
|
char *name;
|
|
|
|
segT seg;
|
2005-02-23 20:28:06 +08:00
|
|
|
offsetT num;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '"')
|
|
|
|
input_line_pointer++;
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (§ion_name); /* Get terminator. */
|
|
|
|
if (c == '"')
|
|
|
|
c = * ++ input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
input_line_pointer++; /* Skip null symbol terminator. */
|
2016-04-02 21:27:18 +08:00
|
|
|
name = xstrdup (section_name);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* TI C from version 5.0 allows a section name to contain a
|
|
|
|
subsection name as well. The subsection name is separated by a
|
|
|
|
':' from the section name. Currently we scan the subsection
|
|
|
|
name and discard it.
|
|
|
|
Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>. */
|
|
|
|
if (c == ':')
|
|
|
|
{
|
2015-08-21 23:42:14 +08:00
|
|
|
char *subname;
|
|
|
|
c = get_symbol_name (&subname); /* Get terminator. */
|
|
|
|
if (c == '"')
|
|
|
|
c = * ++ input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
input_line_pointer++; /* Skip null symbol terminator. */
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_(".sect: subsection name ignored"));
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We might still have a '"' to discard, but the character after a
|
2015-08-21 23:42:14 +08:00
|
|
|
symbol name will be overwritten with a \0 by get_symbol_name()
|
2002-08-28 18:38:51 +08:00
|
|
|
[VK]. */
|
|
|
|
|
|
|
|
if (c == ',')
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (input_line_pointer, &num);
|
2002-08-28 18:38:51 +08:00
|
|
|
else if (*input_line_pointer == ',')
|
|
|
|
{
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (++input_line_pointer, &num);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
num = 0;
|
|
|
|
|
|
|
|
seg = subseg_new (name, num);
|
|
|
|
if (line_label != NULL)
|
|
|
|
{
|
|
|
|
S_SET_SEGMENT (line_label, seg);
|
|
|
|
symbol_set_frag (line_label, frag_now);
|
|
|
|
}
|
|
|
|
|
bfd_section_* macros
This large patch removes the unnecessary bfd parameter from various
bfd section macros and functions. The bfd is hardly ever used and if
needed for the bfd_set_section_* or bfd_rename_section functions can
be found via section->owner except for the com, und, abs, and ind
std_section special sections. Those sections shouldn't be modified
anyway.
The patch also removes various bfd_get_section_<field> macros,
replacing their use with bfd_section_<field>, and adds
bfd_set_section_lma. I've also fixed a minor bug in gas where
compressed section renaming was done directly rather than calling
bfd_rename_section. This would have broken bfd_get_section_by_name
and similar functions, but that hardly mattered at such a late stage
in gas processing.
bfd/
* bfd-in.h (bfd_get_section_name, bfd_get_section_vma),
(bfd_get_section_lma, bfd_get_section_alignment),
(bfd_get_section_size, bfd_get_section_flags),
(bfd_get_section_userdata): Delete.
(bfd_section_name, bfd_section_size, bfd_section_vma),
(bfd_section_lma, bfd_section_alignment): Lose bfd parameter.
(bfd_section_flags, bfd_section_userdata): New.
(bfd_is_com_section): Rename parameter.
* section.c (bfd_set_section_userdata, bfd_set_section_vma),
(bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section),
(bfd_set_section_size): Delete bfd parameter, rename section parameter.
(bfd_set_section_lma): New.
* bfd-in2.h: Regenerate.
* mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param,
update callers.
* aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c,
* coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c,
* compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h,
* elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c,
* elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c,
* elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c,
* elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c,
* elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c,
* elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c,
* elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c,
* elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c,
* elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c,
* elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c,
* elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c,
* elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c,
* elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c,
* elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c,
* elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c,
* elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c,
* elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c,
* elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c,
* elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c,
* elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c,
* mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c,
* peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c,
* xcofflink.c: Update throughout for bfd section macro and function
changes.
binutils/
* addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c,
* objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c,
* od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c,
* resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update
throughout for bfd section macro and function changes.
gas/
* as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c,
* read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c,
* config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c,
* config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c,
* config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c,
* config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c,
* config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c,
* config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c,
* config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c,
* config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c,
* config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c,
* config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c,
* config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c,
* config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c,
* config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c,
* config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c,
* config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c,
* config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for
bfd section macro and function changes.
* write.c (compress_debug): Use bfd_rename_section.
gdb/
* aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c,
* coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c,
* dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c,
* exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h,
* hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c,
* i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c,
* maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c,
* mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c,
* objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c,
* ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c,
* rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c,
* s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c,
* solib-spu.c, * solib-svr4.c, * solib-target.c,
* spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c,
* symmisc.c, * symtab.c, * target.c, * windows-nat.c,
* xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c,
* mi/mi-interp.c: Update throughout for bfd section macro and
function changes.
* gcore (gcore_create_callback): Use bfd_set_section_lma.
* spu-tdep.c (spu_overlay_new_objfile): Likewise.
gprof/
* corefile.c, * symtab.c: Update throughout for bfd section
macro and function changes.
ld/
* ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c,
* emultempl/aarch64elf.em, * emultempl/aix.em,
* emultempl/armcoff.em, * emultempl/armelf.em,
* emultempl/cr16elf.em, * emultempl/cskyelf.em,
* emultempl/m68hc1xelf.em, * emultempl/m68kelf.em,
* emultempl/mipself.em, * emultempl/mmix-elfnmmo.em,
* emultempl/mmo.em, * emultempl/msp430.em,
* emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em,
* emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update
throughout for bfd section macro and function changes.
libctf/
* ctf-open-bfd.c: Update throughout for bfd section macro changes.
opcodes/
* arc-ext.c: Update throughout for bfd section macro changes.
sim/
* common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c,
* erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c,
* m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c,
* rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c,
* rx/trace.c: Update throughout for bfd section macro changes.
2019-09-16 18:55:17 +08:00
|
|
|
if (bfd_section_flags (seg) == SEC_NO_FLAGS)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
bfd_section_* macros
This large patch removes the unnecessary bfd parameter from various
bfd section macros and functions. The bfd is hardly ever used and if
needed for the bfd_set_section_* or bfd_rename_section functions can
be found via section->owner except for the com, und, abs, and ind
std_section special sections. Those sections shouldn't be modified
anyway.
The patch also removes various bfd_get_section_<field> macros,
replacing their use with bfd_section_<field>, and adds
bfd_set_section_lma. I've also fixed a minor bug in gas where
compressed section renaming was done directly rather than calling
bfd_rename_section. This would have broken bfd_get_section_by_name
and similar functions, but that hardly mattered at such a late stage
in gas processing.
bfd/
* bfd-in.h (bfd_get_section_name, bfd_get_section_vma),
(bfd_get_section_lma, bfd_get_section_alignment),
(bfd_get_section_size, bfd_get_section_flags),
(bfd_get_section_userdata): Delete.
(bfd_section_name, bfd_section_size, bfd_section_vma),
(bfd_section_lma, bfd_section_alignment): Lose bfd parameter.
(bfd_section_flags, bfd_section_userdata): New.
(bfd_is_com_section): Rename parameter.
* section.c (bfd_set_section_userdata, bfd_set_section_vma),
(bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section),
(bfd_set_section_size): Delete bfd parameter, rename section parameter.
(bfd_set_section_lma): New.
* bfd-in2.h: Regenerate.
* mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param,
update callers.
* aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c,
* coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c,
* compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h,
* elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c,
* elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c,
* elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c,
* elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c,
* elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c,
* elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c,
* elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c,
* elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c,
* elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c,
* elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c,
* elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c,
* elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c,
* elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c,
* elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c,
* elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c,
* elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c,
* elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c,
* elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c,
* elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c,
* elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c,
* mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c,
* peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c,
* xcofflink.c: Update throughout for bfd section macro and function
changes.
binutils/
* addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c,
* objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c,
* od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c,
* resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update
throughout for bfd section macro and function changes.
gas/
* as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c,
* read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c,
* config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c,
* config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c,
* config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c,
* config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c,
* config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c,
* config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c,
* config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c,
* config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c,
* config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c,
* config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c,
* config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c,
* config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c,
* config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c,
* config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c,
* config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c,
* config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for
bfd section macro and function changes.
* write.c (compress_debug): Use bfd_rename_section.
gdb/
* aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c,
* coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c,
* dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c,
* exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h,
* hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c,
* i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c,
* maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c,
* mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c,
* objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c,
* ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c,
* rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c,
* s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c,
* solib-spu.c, * solib-svr4.c, * solib-target.c,
* spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c,
* symmisc.c, * symtab.c, * target.c, * windows-nat.c,
* xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c,
* mi/mi-interp.c: Update throughout for bfd section macro and
function changes.
* gcore (gcore_create_callback): Use bfd_set_section_lma.
* spu-tdep.c (spu_overlay_new_objfile): Likewise.
gprof/
* corefile.c, * symtab.c: Update throughout for bfd section
macro and function changes.
ld/
* ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c,
* emultempl/aarch64elf.em, * emultempl/aix.em,
* emultempl/armcoff.em, * emultempl/armelf.em,
* emultempl/cr16elf.em, * emultempl/cskyelf.em,
* emultempl/m68hc1xelf.em, * emultempl/m68kelf.em,
* emultempl/mipself.em, * emultempl/mmix-elfnmmo.em,
* emultempl/mmo.em, * emultempl/msp430.em,
* emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em,
* emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update
throughout for bfd section macro and function changes.
libctf/
* ctf-open-bfd.c: Update throughout for bfd section macro changes.
opcodes/
* arc-ext.c: Update throughout for bfd section macro changes.
sim/
* common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c,
* erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c,
* m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c,
* rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c,
* rx/trace.c: Update throughout for bfd section macro changes.
2019-09-16 18:55:17 +08:00
|
|
|
if (!bfd_set_section_flags (seg, SEC_DATA))
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Error setting flags for \"%s\": %s"), name,
|
2002-08-28 18:38:51 +08:00
|
|
|
bfd_errmsg (bfd_get_error ()));
|
|
|
|
}
|
|
|
|
|
2015-08-21 23:42:14 +08:00
|
|
|
/* If the last character overwritten by get_symbol_name() was an
|
2002-08-28 18:38:51 +08:00
|
|
|
end-of-line, we must restore it or the end of the line will not be
|
|
|
|
recognised and scanning extends into the next line, stopping with
|
|
|
|
an error (blame Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>
|
|
|
|
if this is not true). */
|
|
|
|
if (is_end_of_line[(unsigned char) c])
|
|
|
|
*(--input_line_pointer) = c;
|
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* symbol[:] .set value or .set symbol, value */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_set (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if ((symbolP = line_label) == NULL)
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
char *name;
|
|
|
|
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (&name); /* Get terminator. */
|
|
|
|
if (c == '"')
|
|
|
|
c = * ++ input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
if (c != ',')
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_(".set syntax invalid\n"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
2005-09-30 23:48:24 +08:00
|
|
|
++input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
symbol_table_insert (symbolP);
|
|
|
|
|
|
|
|
pseudo_set (symbolP);
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_usect (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char c;
|
|
|
|
char *name;
|
|
|
|
char *section_name;
|
|
|
|
segT seg;
|
2005-02-23 20:28:06 +08:00
|
|
|
offsetT size, alignment_flag;
|
2002-08-28 18:38:51 +08:00
|
|
|
segT current_seg;
|
|
|
|
subsegT current_subseg;
|
|
|
|
|
|
|
|
current_seg = now_seg; /* save current seg. */
|
|
|
|
current_subseg = now_subseg; /* save current subseg. */
|
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '"')
|
|
|
|
input_line_pointer++;
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (§ion_name); /* Get terminator. */
|
|
|
|
if (c == '"')
|
|
|
|
c = * ++ input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
input_line_pointer++; /* Skip null symbol terminator. */
|
2016-04-02 21:27:18 +08:00
|
|
|
name = xstrdup (section_name);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
if (c == ',')
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (input_line_pointer, &size);
|
2002-08-28 18:38:51 +08:00
|
|
|
else if (*input_line_pointer == ',')
|
|
|
|
{
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (++input_line_pointer, &size);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
size = 0;
|
|
|
|
|
|
|
|
/* Read a possibly present third argument (alignment flag) [VK]. */
|
|
|
|
if (*input_line_pointer == ',')
|
|
|
|
{
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (++input_line_pointer, &alignment_flag);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
alignment_flag = 0;
|
|
|
|
if (alignment_flag)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_(".usect: non-zero alignment flag ignored"));
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
seg = subseg_new (name, 0);
|
|
|
|
if (line_label != NULL)
|
|
|
|
{
|
|
|
|
S_SET_SEGMENT (line_label, seg);
|
|
|
|
symbol_set_frag (line_label, frag_now);
|
|
|
|
S_SET_VALUE (line_label, frag_now_fix ());
|
|
|
|
}
|
|
|
|
seg_info (seg)->bss = 1; /* Uninitialised data. */
|
bfd_section_* macros
This large patch removes the unnecessary bfd parameter from various
bfd section macros and functions. The bfd is hardly ever used and if
needed for the bfd_set_section_* or bfd_rename_section functions can
be found via section->owner except for the com, und, abs, and ind
std_section special sections. Those sections shouldn't be modified
anyway.
The patch also removes various bfd_get_section_<field> macros,
replacing their use with bfd_section_<field>, and adds
bfd_set_section_lma. I've also fixed a minor bug in gas where
compressed section renaming was done directly rather than calling
bfd_rename_section. This would have broken bfd_get_section_by_name
and similar functions, but that hardly mattered at such a late stage
in gas processing.
bfd/
* bfd-in.h (bfd_get_section_name, bfd_get_section_vma),
(bfd_get_section_lma, bfd_get_section_alignment),
(bfd_get_section_size, bfd_get_section_flags),
(bfd_get_section_userdata): Delete.
(bfd_section_name, bfd_section_size, bfd_section_vma),
(bfd_section_lma, bfd_section_alignment): Lose bfd parameter.
(bfd_section_flags, bfd_section_userdata): New.
(bfd_is_com_section): Rename parameter.
* section.c (bfd_set_section_userdata, bfd_set_section_vma),
(bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section),
(bfd_set_section_size): Delete bfd parameter, rename section parameter.
(bfd_set_section_lma): New.
* bfd-in2.h: Regenerate.
* mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param,
update callers.
* aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c,
* coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c,
* compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h,
* elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c,
* elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c,
* elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c,
* elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c,
* elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c,
* elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c,
* elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c,
* elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c,
* elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c,
* elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c,
* elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c,
* elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c,
* elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c,
* elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c,
* elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c,
* elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c,
* elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c,
* elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c,
* elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c,
* elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c,
* mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c,
* peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c,
* xcofflink.c: Update throughout for bfd section macro and function
changes.
binutils/
* addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c,
* objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c,
* od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c,
* resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update
throughout for bfd section macro and function changes.
gas/
* as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c,
* read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c,
* config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c,
* config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c,
* config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c,
* config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c,
* config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c,
* config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c,
* config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c,
* config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c,
* config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c,
* config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c,
* config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c,
* config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c,
* config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c,
* config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c,
* config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c,
* config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for
bfd section macro and function changes.
* write.c (compress_debug): Use bfd_rename_section.
gdb/
* aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c,
* coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c,
* dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c,
* exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h,
* hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c,
* i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c,
* maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c,
* mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c,
* objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c,
* ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c,
* rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c,
* s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c,
* solib-spu.c, * solib-svr4.c, * solib-target.c,
* spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c,
* symmisc.c, * symtab.c, * target.c, * windows-nat.c,
* xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c,
* mi/mi-interp.c: Update throughout for bfd section macro and
function changes.
* gcore (gcore_create_callback): Use bfd_set_section_lma.
* spu-tdep.c (spu_overlay_new_objfile): Likewise.
gprof/
* corefile.c, * symtab.c: Update throughout for bfd section
macro and function changes.
ld/
* ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c,
* emultempl/aarch64elf.em, * emultempl/aix.em,
* emultempl/armcoff.em, * emultempl/armelf.em,
* emultempl/cr16elf.em, * emultempl/cskyelf.em,
* emultempl/m68hc1xelf.em, * emultempl/m68kelf.em,
* emultempl/mipself.em, * emultempl/mmix-elfnmmo.em,
* emultempl/mmo.em, * emultempl/msp430.em,
* emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em,
* emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update
throughout for bfd section macro and function changes.
libctf/
* ctf-open-bfd.c: Update throughout for bfd section macro changes.
opcodes/
* arc-ext.c: Update throughout for bfd section macro changes.
sim/
* common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c,
* erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c,
* m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c,
* rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c,
* rx/trace.c: Update throughout for bfd section macro changes.
2019-09-16 18:55:17 +08:00
|
|
|
if (!bfd_set_section_flags (seg, SEC_ALLOC))
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Error setting flags for \"%s\": %s"), name,
|
2002-08-28 18:38:51 +08:00
|
|
|
bfd_errmsg (bfd_get_error ()));
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_seg_alloc (name, seg, size, line_label);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
|
|
|
|
S_SET_STORAGE_CLASS (line_label, C_STAT);
|
|
|
|
|
|
|
|
subseg_set (current_seg, current_subseg); /* Restore current seg. */
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* .version cpu-version. */
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_version (int x ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2005-02-23 20:28:06 +08:00
|
|
|
offsetT temp;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
input_line_pointer =
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_expression_abs (input_line_pointer, &temp);
|
|
|
|
if (!IS_CPU_TIC3X (temp) && !IS_CPU_TIC4X (temp))
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("This assembler does not support processor generation %ld"),
|
2005-02-23 20:28:06 +08:00
|
|
|
(long) temp);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2005-02-23 20:28:06 +08:00
|
|
|
if (tic4x_cpu && temp != (offsetT) tic4x_cpu)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Changing processor generation on fly not supported..."));
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_cpu = temp;
|
2002-08-28 18:38:51 +08:00
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_init_regtable (void)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
for (i = 0; i < tic3x_num_registers; i++)
|
|
|
|
tic4x_insert_reg (tic3x_registers[i].name,
|
|
|
|
tic3x_registers[i].regno);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
if (IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
/* Add additional Tic4x registers, overriding some C3x ones. */
|
|
|
|
for (i = 0; i < tic4x_num_registers; i++)
|
|
|
|
tic4x_insert_reg (tic4x_registers[i].name,
|
|
|
|
tic4x_registers[i].regno);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_init_symbols (void)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* The TI tools accept case insensitive versions of these symbols,
|
|
|
|
we don't !
|
|
|
|
|
|
|
|
For TI C/Asm 5.0
|
|
|
|
|
|
|
|
.TMS320xx 30,31,32,40,or 44 set according to -v flag
|
|
|
|
.C3X or .C3x 1 or 0 1 if -v30,-v31,or -v32
|
|
|
|
.C30 1 or 0 1 if -v30
|
|
|
|
.C31 1 or 0 1 if -v31
|
|
|
|
.C32 1 or 0 1 if -v32
|
|
|
|
.C4X or .C4x 1 or 0 1 if -v40, or -v44
|
|
|
|
.C40 1 or 0 1 if -v40
|
|
|
|
.C44 1 or 0 1 if -v44
|
|
|
|
|
|
|
|
.REGPARM 1 or 0 1 if -mr option used
|
|
|
|
.BIGMODEL 1 or 0 1 if -mb option used
|
|
|
|
|
|
|
|
These symbols are currently supported but will be removed in a
|
|
|
|
later version:
|
|
|
|
.TMS320C30 1 or 0 1 if -v30,-v31,or -v32
|
|
|
|
.TMS320C31 1 or 0 1 if -v31
|
|
|
|
.TMS320C32 1 or 0 1 if -v32
|
|
|
|
.TMS320C40 1 or 0 1 if -v40, or -v44
|
|
|
|
.TMS320C44 1 or 0 1 if -v44
|
|
|
|
|
|
|
|
Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide,
|
|
|
|
1997, SPRU035C, p. 3-17/3-18. */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_insert_sym (".REGPARM", tic4x_reg_args);
|
2015-08-12 19:40:42 +08:00
|
|
|
tic4x_insert_sym (".MEMPARM", !tic4x_reg_args);
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_insert_sym (".BIGMODEL", tic4x_big_model);
|
|
|
|
tic4x_insert_sym (".C30INTERRUPT", 0);
|
|
|
|
tic4x_insert_sym (".TMS320xx", tic4x_cpu == 0 ? 40 : tic4x_cpu);
|
|
|
|
tic4x_insert_sym (".C3X", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
|
|
|
|
tic4x_insert_sym (".C3x", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
|
|
|
|
tic4x_insert_sym (".C4X", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
|
|
|
|
tic4x_insert_sym (".C4x", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
|
2002-08-28 18:38:51 +08:00
|
|
|
/* Do we need to have the following symbols also in lower case? */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_insert_sym (".TMS320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
|
|
|
|
tic4x_insert_sym (".tms320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
|
|
|
|
tic4x_insert_sym (".TMS320C31", tic4x_cpu == 31);
|
|
|
|
tic4x_insert_sym (".tms320C31", tic4x_cpu == 31);
|
|
|
|
tic4x_insert_sym (".TMS320C32", tic4x_cpu == 32);
|
|
|
|
tic4x_insert_sym (".tms320C32", tic4x_cpu == 32);
|
|
|
|
tic4x_insert_sym (".TMS320C33", tic4x_cpu == 33);
|
|
|
|
tic4x_insert_sym (".tms320C33", tic4x_cpu == 33);
|
|
|
|
tic4x_insert_sym (".TMS320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
|
|
|
|
tic4x_insert_sym (".tms320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
|
|
|
|
tic4x_insert_sym (".TMS320C44", tic4x_cpu == 44);
|
|
|
|
tic4x_insert_sym (".tms320C44", tic4x_cpu == 44);
|
|
|
|
tic4x_insert_sym (".TMX320C40", 0); /* C40 first pass silicon ? */
|
|
|
|
tic4x_insert_sym (".tmx320C40", 0);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Insert a new instruction template into hash table. */
|
2020-08-18 16:57:21 +08:00
|
|
|
static void
|
2008-02-12 16:37:08 +08:00
|
|
|
tic4x_inst_insert (const tic4x_inst_t *inst)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
static char prev_name[16];
|
|
|
|
|
|
|
|
/* Only insert the first name if have several similar entries. */
|
|
|
|
if (!strcmp (inst->name, prev_name) || inst->name[0] == '\0')
|
2020-08-18 16:57:21 +08:00
|
|
|
return;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
if (str_hash_insert (tic4x_op_hash, inst->name, inst, 0) != NULL)
|
|
|
|
as_fatal (_("duplicate %s"), inst->name);
|
|
|
|
|
2020-08-18 16:57:21 +08:00
|
|
|
strcpy (prev_name, inst->name);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make a new instruction template. */
|
2003-04-04 16:15:15 +08:00
|
|
|
static tic4x_inst_t *
|
2016-03-20 13:34:02 +08:00
|
|
|
tic4x_inst_make (const char *name, unsigned long opcode, const char *args)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
static tic4x_inst_t *insts = NULL;
|
2002-08-28 18:38:51 +08:00
|
|
|
static char *names = NULL;
|
2009-12-11 21:42:17 +08:00
|
|
|
static int iindex = 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
if (insts == NULL)
|
|
|
|
{
|
|
|
|
/* Allocate memory to store name strings. */
|
2016-04-01 21:26:30 +08:00
|
|
|
names = XNEWVEC (char, 8192);
|
2002-08-28 18:38:51 +08:00
|
|
|
/* Allocate memory for additional insts. */
|
2016-04-01 21:26:30 +08:00
|
|
|
insts = XNEWVEC (tic4x_inst_t, 1024);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
insts[iindex].name = names;
|
|
|
|
insts[iindex].opcode = opcode;
|
|
|
|
insts[iindex].opmask = 0xffffffff;
|
|
|
|
insts[iindex].args = args;
|
|
|
|
iindex++;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2020-08-25 15:26:07 +08:00
|
|
|
while (*name)
|
2002-08-28 18:38:51 +08:00
|
|
|
*names++ = *name++;
|
|
|
|
*names++ = '\0';
|
|
|
|
|
2009-12-11 21:42:17 +08:00
|
|
|
return &insts[iindex - 1];
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add instruction template, creating dynamic templates as required. */
|
2020-08-18 16:57:21 +08:00
|
|
|
static void
|
2008-02-12 16:37:08 +08:00
|
|
|
tic4x_inst_add (const tic4x_inst_t *insts)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2016-03-07 23:16:28 +08:00
|
|
|
const char *s = insts->name;
|
2002-08-28 18:38:51 +08:00
|
|
|
char *d;
|
|
|
|
unsigned int i;
|
|
|
|
char name[16];
|
|
|
|
|
|
|
|
d = name;
|
|
|
|
|
2002-11-18 17:09:35 +08:00
|
|
|
/* We do not care about INSNs that is not a part of our
|
Add support for Xilinx MicroBlaze processor.
* bfd/Makefile.am: Add cpu-microblaze.{lo,c}, elf32-microblaze.{lo,c}.
* bfd/Makefile.in: Same.
* bfd/archures.c: Add bfd_arch_microblaze.
* bfd/bfd-in2.h: Regenerate.
* bfd/config.bfd: Add microblaze target.
* bfd/configure: Add bfd_elf32_microblaze_vec target.
* bfd/configure.in: Same.
* bfd/cpu-microblaze.c: New.
* bfd/elf32-microblaze.c: New.
* bfd/libbfd-in.h: Add prototype _bfd_dwarf2_fixup_section_debug_loc().
* bfd/libbfd.h: Regenerate.
* bfd/reloc.c: Add MICROBLAZE relocations.
* bfd/section.c: Add struct relax_table and relax_count to section.
* bfd/targets.c: Add bfd_elf32_microblaze_vec.
* binutils/MAINTAINERS: Add self as maintainer.
* binutils/readelf.c: Include elf/microblaze.h, add EM_MICROBLAZE &
EM_MICROBLAZE_OLD to guess_is_rela(), dump_relocations(),
get_machine_name().
* config.sub: Add microblaze target.
* configure: Same.
* configure.ac: Same.
* gas/Makefile.am: add microblaze to CPU_TYPES, config/tc-microblaze.c to
TARGET_CPU_CFILES, config/tc-microblaze.h to TARGET_CPU_HFILES, add
DEP_microblaze_elf target.
* gas/Makefile.in: Same.
* gas/config/tc-microblaze.c: Add MicroBlaze assembler.
* gas/config/tc-microblaze.h: Add header for tc-microblaze.c.
* gas/configure: Add microblaze target.
* gas/configure.in: Same.
* gas/configure.tgt: Same.
* gas/doc/Makefile.am: Add c-microblaze.texi to CPU_DOCS.
* gas/doc/Makefile.in: Same.
* gas/doc/all.texi: Set MICROBLAZE.
* gas/doc/as.texinfo: Add MicroBlaze doc links.
* gas/doc/c-microblaze.texi: New MicroBlaze docs.
* include/dis-asm.h: Decl print_insn_microblaze().
* include/elf/common.h: Define EM_MICROBLAZE & EM_MICROBLAZE_OLD.
* include/elf/microblaze.h: New reloc definitions.
* ld/Makefile.am: Add eelf32mb_linux.o, eelf32microblaze.o to
ALL_EMULATIONS, targets.
* ld/Makefile.in: Same.
* ld/configure.tgt: Add microblaze*-linux*, microblaze* targets.
* ld/emulparams/elf32mb_linux.sh: New.
* ld/emulparams/elf32microblaze.sh. New.
* ld/scripttempl/elfmicroblaze.sc: New.
* opcodes/Makefile.am: Add microblaze-opc.h to HFILES, microblaze-dis.c to
CFILES, microblaze-dis.lo to ALL_MACHINES, targets.
* opcodes/Makefile.in: Same.
* opcodes/configure: Add bfd_microblaze_arch target.
* opcodes/configure.in: Same.
* opcodes/disassemble.c: Define ARCH_microblaze, return
print_insn_microblaze().
* opcodes/microblaze-dis.c: New MicroBlaze disassembler.
* opcodes/microblaze-opc.h: New MicroBlaze opcode definitions.
* opcodes/microblaze-opcm.h: New MicroBlaze opcode types.
2009-08-07 01:38:04 +08:00
|
|
|
oplevel setting. */
|
|
|
|
if ((insts->oplevel & tic4x_oplevel) == 0)
|
2020-08-18 16:57:21 +08:00
|
|
|
return;
|
2002-11-18 17:09:35 +08:00
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
switch (*s)
|
|
|
|
{
|
|
|
|
case 'B':
|
|
|
|
case 'C':
|
|
|
|
/* Dynamically create all the conditional insts. */
|
2003-04-04 16:15:15 +08:00
|
|
|
for (i = 0; i < tic4x_num_conds; i++)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_inst_t *inst;
|
2002-08-28 18:38:51 +08:00
|
|
|
int k = 0;
|
2016-03-07 23:16:28 +08:00
|
|
|
const char *c = tic4x_conds[i].name;
|
2002-08-28 18:38:51 +08:00
|
|
|
char *e = d;
|
|
|
|
|
|
|
|
while (*c)
|
|
|
|
*e++ = *c++;
|
|
|
|
c = s + 1;
|
|
|
|
while (*c)
|
|
|
|
*e++ = *c++;
|
|
|
|
*e = '\0';
|
|
|
|
|
|
|
|
/* If instruction found then have already processed it. */
|
2020-08-18 16:57:21 +08:00
|
|
|
if (str_hash_find (tic4x_op_hash, name))
|
|
|
|
return;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
inst = tic4x_inst_make (name, insts[k].opcode +
|
|
|
|
(tic4x_conds[i].cond <<
|
2002-08-28 18:38:51 +08:00
|
|
|
(*s == 'B' ? 16 : 23)),
|
|
|
|
insts[k].args);
|
|
|
|
if (k == 0) /* Save strcmp() with following func. */
|
2020-08-18 16:57:21 +08:00
|
|
|
tic4x_inst_insert (inst);
|
2002-08-28 18:38:51 +08:00
|
|
|
k++;
|
|
|
|
}
|
|
|
|
while (!strcmp (insts->name,
|
|
|
|
insts[k].name));
|
|
|
|
}
|
2020-08-18 16:57:21 +08:00
|
|
|
return;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
case '\0':
|
2020-08-18 16:57:21 +08:00
|
|
|
tic4x_inst_insert (insts);
|
|
|
|
return;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
*d++ = *s++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called once, at assembler startup time. It should
|
|
|
|
set up all the tables, etc., that the MD part of the assembler will
|
|
|
|
need. */
|
2015-08-12 19:40:42 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_begin (void)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
2002-11-18 17:09:35 +08:00
|
|
|
/* Setup the proper opcode level according to the
|
|
|
|
commandline parameters */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_oplevel = OP_C3X;
|
|
|
|
|
|
|
|
if ( IS_CPU_TIC4X(tic4x_cpu) )
|
|
|
|
tic4x_oplevel |= OP_C4X;
|
|
|
|
|
|
|
|
if ( ( tic4x_cpu == 31 && tic4x_revision >= 6)
|
|
|
|
|| (tic4x_cpu == 32 && tic4x_revision >= 2)
|
|
|
|
|| (tic4x_cpu == 33)
|
|
|
|
|| tic4x_enhanced )
|
|
|
|
tic4x_oplevel |= OP_ENH;
|
|
|
|
|
|
|
|
if ( ( tic4x_cpu == 30 && tic4x_revision >= 7)
|
|
|
|
|| (tic4x_cpu == 31 && tic4x_revision >= 5)
|
|
|
|
|| (tic4x_cpu == 32)
|
|
|
|
|| tic4x_lowpower )
|
|
|
|
tic4x_oplevel |= OP_LPWR;
|
|
|
|
|
|
|
|
if ( ( tic4x_cpu == 30 && tic4x_revision >= 7)
|
|
|
|
|| (tic4x_cpu == 31 && tic4x_revision >= 5)
|
|
|
|
|| (tic4x_cpu == 32)
|
|
|
|
|| (tic4x_cpu == 33)
|
|
|
|
|| (tic4x_cpu == 40 && tic4x_revision >= 5)
|
|
|
|
|| (tic4x_cpu == 44)
|
|
|
|
|| tic4x_idle2 )
|
|
|
|
tic4x_oplevel |= OP_IDLE2;
|
2002-11-18 17:09:35 +08:00
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
/* Create hash table for mnemonics. */
|
2020-08-18 16:57:21 +08:00
|
|
|
tic4x_op_hash = str_htab_create ();
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Create hash table for asg pseudo. */
|
2020-08-18 16:57:21 +08:00
|
|
|
tic4x_asg_hash = str_htab_create ();
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Add mnemonics to hash table, expanding conditional mnemonics on fly. */
|
2003-04-04 16:15:15 +08:00
|
|
|
for (i = 0; i < tic4x_num_insts; i++)
|
2020-08-18 16:57:21 +08:00
|
|
|
tic4x_inst_add (tic4x_insts + i);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Create dummy inst to avoid errors accessing end of table. */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_inst_make ("", 0, "");
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Add registers to symbol table. */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_init_regtable ();
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Add predefined symbols to symbol table. */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_init_symbols ();
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
void
|
gas: rename md_end to md_finish
Currently md_end is typically used for some final actions rather than
freeing memory like other *_end functions. Rename it to md_finish,
and rename target implementation. The renaming of target functions
makes it possible to find them all with "grep md_finish",
eg. md_mips_end is renamed to mips_md_finish, not md_mips_finish.
This patch leaves a number of md_end functions unchanged, those that
either do nothing or deallocate memory, and calls them late.
The idea here is that target maintainers implement md_end functions to
tidy memory, if anyone cares. Freeing persistent memory in gas is
not at all important, except that it can hide more important memory
leaks, those that happen once per some frequent gas operation, amongst
these unimportant memory leaks.
* as.c (main): Rename md_end to md_finish.
* config/tc-alpha.c, * config/tc-alpha.h,
* config/tc-arc.c, * config/tc-arc.h,
* config/tc-arm.c, * config/tc-arm.h,
* config/tc-csky.c, * config/tc-csky.h,
* config/tc-ia64.c, * config/tc-ia64.h,
* config/tc-mcore.c, * config/tc-mcore.h,
* config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mmix.h,
* config/tc-msp430.c, * config/tc-msp430.h,
* config/tc-nds32.c, * config/tc-nds32.h,
* config/tc-ppc.c, * config/tc-ppc.h,
* config/tc-pru.c, * config/tc-pru.h,
* config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-s390.c, * config/tc-s390.h,
* config/tc-sparc.c, * config/tc-sparc.h,
* config/tc-tic4x.c, * config/tc-tic4x.h,
* config/tc-tic6x.c, * config/tc-tic6x.h,
* config/tc-v850.c, * config/tc-v850.h,
* config/tc-xtensa.c, * config/tc-xtensa.h,
* config/tc-z80.c, * config/tc-z80.h: Similarly.
* output-file.c (output_file_close): Call md_end.
2022-07-05 11:56:38 +08:00
|
|
|
tic4x_md_finish (void)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2015-08-12 19:40:42 +08:00
|
|
|
bfd_set_arch_mach (stdoutput, bfd_arch_tic4x,
|
2003-04-04 16:15:15 +08:00
|
|
|
IS_CPU_TIC4X (tic4x_cpu) ? bfd_mach_tic4x : bfd_mach_tic3x);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static int
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_indirect_parse (tic4x_operand_t *operand,
|
|
|
|
const tic4x_indirect_t *indirect)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2016-03-07 23:16:28 +08:00
|
|
|
const char *n = indirect->name;
|
2002-08-28 18:38:51 +08:00
|
|
|
char *s = input_line_pointer;
|
|
|
|
char *b;
|
|
|
|
symbolS *symbolP;
|
|
|
|
char name[32];
|
|
|
|
|
|
|
|
operand->disp = 0;
|
|
|
|
for (; *n; n++)
|
|
|
|
{
|
|
|
|
switch (*n)
|
|
|
|
{
|
|
|
|
case 'a': /* Need to match aux register. */
|
|
|
|
b = name;
|
2003-04-04 16:15:15 +08:00
|
|
|
#ifdef TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
if (*s == '%')
|
|
|
|
s++;
|
|
|
|
#endif
|
2003-07-14 18:06:06 +08:00
|
|
|
while (ISALNUM (*s))
|
2002-08-28 18:38:51 +08:00
|
|
|
*b++ = *s++;
|
|
|
|
*b++ = '\0';
|
|
|
|
if (!(symbolP = symbol_find (name)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (S_GET_SEGMENT (symbolP) != reg_section)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
operand->aregno = S_GET_VALUE (symbolP);
|
|
|
|
if (operand->aregno >= REG_AR0 && operand->aregno <= REG_AR7)
|
|
|
|
break;
|
|
|
|
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Auxiliary register AR0--AR7 required for indirect"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
case 'd': /* Need to match constant for disp. */
|
2003-04-04 16:15:15 +08:00
|
|
|
#ifdef TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
if (*s == '%') /* expr() will die if we don't skip this. */
|
|
|
|
s++;
|
|
|
|
#endif
|
2003-04-04 16:15:15 +08:00
|
|
|
s = tic4x_expression (s, &operand->expr);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (operand->expr.X_op != O_constant)
|
|
|
|
return 0;
|
|
|
|
operand->disp = operand->expr.X_add_number;
|
|
|
|
if (operand->disp < 0 || operand->disp > 255)
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Bad displacement %d (require 0--255)\n"),
|
2002-08-28 18:38:51 +08:00
|
|
|
operand->disp);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'y': /* Need to match IR0. */
|
|
|
|
case 'z': /* Need to match IR1. */
|
2003-04-04 16:15:15 +08:00
|
|
|
#ifdef TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
if (*s == '%')
|
|
|
|
s++;
|
|
|
|
#endif
|
2003-04-04 16:15:15 +08:00
|
|
|
s = tic4x_expression (s, &operand->expr);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (operand->expr.X_op != O_register)
|
|
|
|
return 0;
|
|
|
|
if (operand->expr.X_add_number != REG_IR0
|
|
|
|
&& operand->expr.X_add_number != REG_IR1)
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Index register IR0,IR1 required for displacement"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*n == 'y' && operand->expr.X_add_number == REG_IR0)
|
|
|
|
break;
|
|
|
|
if (*n == 'z' && operand->expr.X_add_number == REG_IR1)
|
|
|
|
break;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case '(':
|
|
|
|
if (*s != '(') /* No displacement, assume to be 1. */
|
|
|
|
{
|
|
|
|
operand->disp = 1;
|
|
|
|
while (*n != ')')
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
s++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-07-14 18:06:06 +08:00
|
|
|
if (TOLOWER (*s) != *n)
|
2002-08-28 18:38:51 +08:00
|
|
|
return 0;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*s != ' ' && *s != ',' && *s != '\0')
|
|
|
|
return 0;
|
|
|
|
input_line_pointer = s;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
static char *
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_operand_parse (char *s, tic4x_operand_t *operand)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
char c;
|
|
|
|
int ret;
|
|
|
|
expressionS *exp = &operand->expr;
|
|
|
|
char *save = input_line_pointer;
|
|
|
|
char *str;
|
Updated sources to avoid using the identifier name "new", which is a
keyword in c++.
* bfd/aoutx.h (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol.
* bfd/coffgen.c (coff_make_empty_symbol)
(coff_bfd_make_debug_symbol): Rename variable new to new_symbol.
* bfd/cpu-ia64-opc.c (ext_reg, ins_imms_scaled): Rename variable
new to new_insn.
* bfd/doc/chew.c (newentry, add_intrinsic): Rename variable new to
new_d.
* bfd/ecoff.c (_bfd_ecoff_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/elf32-m68k.c (elf_m68k_get_got_entry_type): Rename argument
new to new_reloc.
* bfd/hash.c (bfd_hash_lookup): Rename variable new to new_string.
* bfd/ieee.c (ieee_make_empty_symbol): Rename variable new to
new_symbol.
* bfd/linker.c (bfd_new_link_order): Rename variable new to
new_lo.
* bfd/mach-o.c (bfd_mach_o_sizeof_headers): Rename variable new to
symbol.
* bfd/oasys.c (oasys_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/pdp11.c (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol_type.
* bfd/plugin.c (bfd_plugin_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/rs6000-core.c (CoreHdr, VmInfo): Rename union member new to
new_dump.
(read_hdr, rs6000coff_core_p)
(rs6000coff_core_file_matches_executable_p)
(rs6000coff_core_file_failing_command)
(rs6000coff_core_file_failing_signal): Updated function to use new
union member name.
* bfd/som.c (som_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/syms.c (_bfd_generic_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/tekhex.c (first_phase, tekhex_make_empty_symbol): Rename
variable new to new_symbol.
* binutils/nlmconv.c (main): Rename variable new to new_name.
* gas/config/tc-arm.c (insert_reg_alias): Rename variable new to
new_reg.
* gas/config/tc-dlx.c (parse_operand): Rename variable new to
new_pos.
* gas/config/tc-ia64.c (ia64_gen_real_reloc_type): Rename variable
new to newr.
* gas/config/tc-mcore.c (parse_exp, parse_imm): Rename variable
new to new_pointer.
* gas/config/tc-microblaze.c (parse_exp, parse_imm, check_got):
Change name from new to new_pointer.
* gas/config/tc-or32.c (parse_operand): Rename variable new to
new_pointer.
* gas/config/tc-pdp11.c (md_assemble): Rename variable new to
new_pointer.
* gas/config/tc-pj.c (alias): Change argument new to new_name.
* gas/config/tc-score.c (s3_build_score_ops_hsh): Rename variable
new to new_opcode. (s3_build_dependency_insn_hsh) Rename variable
new to new_i2n. (s3_convert): Rename variables old and new to
r_old and r_new.
* gas/config/tc-score7.c (s7_build_score_ops_hsh): Rename variable
new to new_opcode. (s7_build_dependency_insn_hsh): Rename variable
new to new_i2d. (s7_b32_relax_to_b16, s7_convert_frag): Rename
variables old and new to r_old and r_new.
* gas/config/tc-sh.c (parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-sh64.c (shmedia_parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-tic4x.c (tic4x_operand_parse): Rename variable new
to new_pointer.
* gas/config/tc-z8k.c (parse_exp): Rename variable new to
new_pointer.
* gas/listing.c (listing_newline): Rename variable new to new_i.
* ld/ldexp.c (exp_intop, exp_bigintop, exp_relop, exp_binop)
(exp_trinop, exp_unop, exp_nameop, exp_assop): Rename variable new
to new_e.
* ld/ldfile.c (ldfile_add_library_path): Rename variable new to
new_dirs. (ldfile_add_arch): Rename variable new to new_arch.
* ld/ldlang.c (new_statement, lang_final, lang_add_wild)
(lang_target, lang_add_fill, lang_add_data, lang_add_assignment)
(lang_add_insert): Rename variable new to new_stmt. (new_afile):
Added missing cast. (lang_memory_region_lookup): Rename variable
new to new_region. (init_os): Rename variable new to
new_userdata. (lang_add_section): Rename variable new to
new_section. (ldlang_add_undef): Rename variable new to
new_undef. (realsymbol): Rename variable new to new_name.
* opcodes/z8kgen.c (internal, gas): Rename variable new to new_op.
Updated sources to avoid using the identifier name "template",
which is a keyword in c++.
* bfd/elf32-arm.c (struct stub_def): Rename member template to
template_sequence. (arm_build_one_stub,
find_stub_size_and_template, arm_size_one_stub, arm_map_one_stub):
Rename variable template to template_sequence.
* bfd/elfxx-ia64.c (elfNN_ia64_relax_br, elfNN_ia64_relax_brl):
Rename variable template to template_val.
* gas/config/tc-arm.c (struct asm_cond, struct asm_psr, struct
asm_barrier_opt): Change member template to
template_name. (md_begin): Update code to reflect new member
names.
* gas/config/tc-i386.c (struct templates, struct _i386_insn)
(match_template, cpu_flags_match, match_reg_size, match_mem_size)
(operand_size_match, md_begin, i386_print_statistics, pi)
(build_vex_prefix, md_assemble, parse_insn, optimize_imm)
(optimize_disp): Updated code to use new names. (parse_insn):
Added casts.
* gas/config/tc-ia64.c (dot_template, emit_one_bundle): Updated
code to use new names.
* gas/config/tc-score.c (struct s3_asm_opcode): Renamed member
template to template_name. (s3_parse_16_32_inst, s3_parse_48_inst,
s3_do_macro_ldst_label, s3_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-score7.c (struct s7_asm_opcode): Renamed member
template to template_name. (s7_parse_16_32_inst,
s7_do_macro_ldst_label, s7_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-tic30.c (md_begin, struct tic30_insn)
(md_assemble): Update code to use new names.
* gas/config/tc-tic54x.c (struct _tic54x_insn, md_begin)
(optimize_insn, tic54x_parse_insn, next_line_shows_parallel):
Update code to use new names.
* include/opcode/tic30.h (template): Rename type template to
insn_template. Updated code to use new name.
* include/opcode/tic54x.h (template): Rename type template to
insn_template.
* opcodes/cris-dis.c (bytes_to_skip): Update code to use new name.
* opcodes/i386-dis.c (putop): Update code to use new name.
* opcodes/i386-gen.c (process_i386_opcodes): Update code to use
new name.
* opcodes/i386-opc.h (struct template): Rename struct template to
insn_template. Update code accordingly.
* opcodes/i386-tbl.h (i386_optab): Update type to use new name.
* opcodes/ia64-dis.c (print_insn_ia64): Rename variable template
to template_val.
* opcodes/tic30-dis.c (struct instruction, get_tic30_instruction):
Update code to use new name.
* opcodes/tic54x-dis.c (has_lkaddr, get_insn_size)
(print_parallel_instruction, print_insn_tic54x, tic54x_get_insn):
Update code to use new name.
* opcodes/tic54x-opc.c (tic54x_unknown_opcode, tic54x_optab):
Update type to new name.
2009-08-30 06:11:02 +08:00
|
|
|
char *new_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
struct hash_entry *entry = NULL;
|
|
|
|
|
|
|
|
input_line_pointer = s;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
|
2015-08-21 23:42:14 +08:00
|
|
|
c = get_symbol_name (&str); /* Get terminator. */
|
Updated sources to avoid using the identifier name "new", which is a
keyword in c++.
* bfd/aoutx.h (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol.
* bfd/coffgen.c (coff_make_empty_symbol)
(coff_bfd_make_debug_symbol): Rename variable new to new_symbol.
* bfd/cpu-ia64-opc.c (ext_reg, ins_imms_scaled): Rename variable
new to new_insn.
* bfd/doc/chew.c (newentry, add_intrinsic): Rename variable new to
new_d.
* bfd/ecoff.c (_bfd_ecoff_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/elf32-m68k.c (elf_m68k_get_got_entry_type): Rename argument
new to new_reloc.
* bfd/hash.c (bfd_hash_lookup): Rename variable new to new_string.
* bfd/ieee.c (ieee_make_empty_symbol): Rename variable new to
new_symbol.
* bfd/linker.c (bfd_new_link_order): Rename variable new to
new_lo.
* bfd/mach-o.c (bfd_mach_o_sizeof_headers): Rename variable new to
symbol.
* bfd/oasys.c (oasys_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/pdp11.c (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol_type.
* bfd/plugin.c (bfd_plugin_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/rs6000-core.c (CoreHdr, VmInfo): Rename union member new to
new_dump.
(read_hdr, rs6000coff_core_p)
(rs6000coff_core_file_matches_executable_p)
(rs6000coff_core_file_failing_command)
(rs6000coff_core_file_failing_signal): Updated function to use new
union member name.
* bfd/som.c (som_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/syms.c (_bfd_generic_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/tekhex.c (first_phase, tekhex_make_empty_symbol): Rename
variable new to new_symbol.
* binutils/nlmconv.c (main): Rename variable new to new_name.
* gas/config/tc-arm.c (insert_reg_alias): Rename variable new to
new_reg.
* gas/config/tc-dlx.c (parse_operand): Rename variable new to
new_pos.
* gas/config/tc-ia64.c (ia64_gen_real_reloc_type): Rename variable
new to newr.
* gas/config/tc-mcore.c (parse_exp, parse_imm): Rename variable
new to new_pointer.
* gas/config/tc-microblaze.c (parse_exp, parse_imm, check_got):
Change name from new to new_pointer.
* gas/config/tc-or32.c (parse_operand): Rename variable new to
new_pointer.
* gas/config/tc-pdp11.c (md_assemble): Rename variable new to
new_pointer.
* gas/config/tc-pj.c (alias): Change argument new to new_name.
* gas/config/tc-score.c (s3_build_score_ops_hsh): Rename variable
new to new_opcode. (s3_build_dependency_insn_hsh) Rename variable
new to new_i2n. (s3_convert): Rename variables old and new to
r_old and r_new.
* gas/config/tc-score7.c (s7_build_score_ops_hsh): Rename variable
new to new_opcode. (s7_build_dependency_insn_hsh): Rename variable
new to new_i2d. (s7_b32_relax_to_b16, s7_convert_frag): Rename
variables old and new to r_old and r_new.
* gas/config/tc-sh.c (parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-sh64.c (shmedia_parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-tic4x.c (tic4x_operand_parse): Rename variable new
to new_pointer.
* gas/config/tc-z8k.c (parse_exp): Rename variable new to
new_pointer.
* gas/listing.c (listing_newline): Rename variable new to new_i.
* ld/ldexp.c (exp_intop, exp_bigintop, exp_relop, exp_binop)
(exp_trinop, exp_unop, exp_nameop, exp_assop): Rename variable new
to new_e.
* ld/ldfile.c (ldfile_add_library_path): Rename variable new to
new_dirs. (ldfile_add_arch): Rename variable new to new_arch.
* ld/ldlang.c (new_statement, lang_final, lang_add_wild)
(lang_target, lang_add_fill, lang_add_data, lang_add_assignment)
(lang_add_insert): Rename variable new to new_stmt. (new_afile):
Added missing cast. (lang_memory_region_lookup): Rename variable
new to new_region. (init_os): Rename variable new to
new_userdata. (lang_add_section): Rename variable new to
new_section. (ldlang_add_undef): Rename variable new to
new_undef. (realsymbol): Rename variable new to new_name.
* opcodes/z8kgen.c (internal, gas): Rename variable new to new_op.
Updated sources to avoid using the identifier name "template",
which is a keyword in c++.
* bfd/elf32-arm.c (struct stub_def): Rename member template to
template_sequence. (arm_build_one_stub,
find_stub_size_and_template, arm_size_one_stub, arm_map_one_stub):
Rename variable template to template_sequence.
* bfd/elfxx-ia64.c (elfNN_ia64_relax_br, elfNN_ia64_relax_brl):
Rename variable template to template_val.
* gas/config/tc-arm.c (struct asm_cond, struct asm_psr, struct
asm_barrier_opt): Change member template to
template_name. (md_begin): Update code to reflect new member
names.
* gas/config/tc-i386.c (struct templates, struct _i386_insn)
(match_template, cpu_flags_match, match_reg_size, match_mem_size)
(operand_size_match, md_begin, i386_print_statistics, pi)
(build_vex_prefix, md_assemble, parse_insn, optimize_imm)
(optimize_disp): Updated code to use new names. (parse_insn):
Added casts.
* gas/config/tc-ia64.c (dot_template, emit_one_bundle): Updated
code to use new names.
* gas/config/tc-score.c (struct s3_asm_opcode): Renamed member
template to template_name. (s3_parse_16_32_inst, s3_parse_48_inst,
s3_do_macro_ldst_label, s3_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-score7.c (struct s7_asm_opcode): Renamed member
template to template_name. (s7_parse_16_32_inst,
s7_do_macro_ldst_label, s7_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-tic30.c (md_begin, struct tic30_insn)
(md_assemble): Update code to use new names.
* gas/config/tc-tic54x.c (struct _tic54x_insn, md_begin)
(optimize_insn, tic54x_parse_insn, next_line_shows_parallel):
Update code to use new names.
* include/opcode/tic30.h (template): Rename type template to
insn_template. Updated code to use new name.
* include/opcode/tic54x.h (template): Rename type template to
insn_template.
* opcodes/cris-dis.c (bytes_to_skip): Update code to use new name.
* opcodes/i386-dis.c (putop): Update code to use new name.
* opcodes/i386-gen.c (process_i386_opcodes): Update code to use
new name.
* opcodes/i386-opc.h (struct template): Rename struct template to
insn_template. Update code accordingly.
* opcodes/i386-tbl.h (i386_optab): Update type to use new name.
* opcodes/ia64-dis.c (print_insn_ia64): Rename variable template
to template_val.
* opcodes/tic30-dis.c (struct instruction, get_tic30_instruction):
Update code to use new name.
* opcodes/tic54x-dis.c (has_lkaddr, get_insn_size)
(print_parallel_instruction, print_insn_tic54x, tic54x_get_insn):
Update code to use new name.
* opcodes/tic54x-opc.c (tic54x_unknown_opcode, tic54x_optab):
Update type to new name.
2009-08-30 06:11:02 +08:00
|
|
|
new_pointer = input_line_pointer;
|
2020-08-18 16:57:21 +08:00
|
|
|
if (strlen (str) && (entry = str_hash_find (tic4x_asg_hash, str)) != NULL)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2015-08-21 23:42:14 +08:00
|
|
|
(void) restore_line_pointer (c);
|
2002-08-28 18:38:51 +08:00
|
|
|
input_line_pointer = (char *) entry;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-08-21 23:42:14 +08:00
|
|
|
(void) restore_line_pointer (c);
|
2002-08-28 18:38:51 +08:00
|
|
|
input_line_pointer = str;
|
|
|
|
}
|
|
|
|
|
|
|
|
operand->mode = M_UNKNOWN;
|
|
|
|
switch (*input_line_pointer)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
#ifdef TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
case '%':
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (++input_line_pointer, exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp->X_op != O_register)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Expecting a register name"));
|
2002-08-28 18:38:51 +08:00
|
|
|
operand->mode = M_REGISTER;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '^':
|
|
|
|
/* Denotes high 16 bits. */
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (++input_line_pointer, exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
operand->mode = M_IMMED;
|
|
|
|
else if (exp->X_op == O_big)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Number too large")); /* bignum required */
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_gen_to_words (generic_floating_point_number,
|
2002-08-28 18:38:51 +08:00
|
|
|
operand->fwords, S_PRECISION);
|
|
|
|
operand->mode = M_IMMED_F;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0 */
|
|
|
|
/* WARNING : The TI C40 assembler cannot do this. */
|
|
|
|
else if (exp->X_op == O_symbol)
|
2016-10-05 14:22:24 +08:00
|
|
|
operand->mode = M_HI;
|
|
|
|
else
|
|
|
|
as_bad (_("Expecting a constant value"));
|
|
|
|
break;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
case '#':
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (++input_line_pointer, exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
operand->mode = M_IMMED;
|
|
|
|
else if (exp->X_op == O_big)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number > 0)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Number too large")); /* bignum required. */
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_gen_to_words (generic_floating_point_number,
|
2002-08-28 18:38:51 +08:00
|
|
|
operand->fwords, S_PRECISION);
|
|
|
|
operand->mode = M_IMMED_F;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0 */
|
|
|
|
/* WARNING : The TI C40 assembler cannot do this. */
|
|
|
|
else if (exp->X_op == O_symbol)
|
2016-10-05 14:22:24 +08:00
|
|
|
operand->mode = M_IMMED;
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Expecting a constant value"));
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2016-10-05 14:22:24 +08:00
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case '\\':
|
|
|
|
#endif
|
|
|
|
case '@':
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (++input_line_pointer, exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp->X_op != O_constant && exp->X_op != O_symbol)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Bad direct addressing construct %s"), s);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number < 0)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Direct value of %ld is not suitable"),
|
2002-08-28 18:38:51 +08:00
|
|
|
(long) exp->X_add_number);
|
|
|
|
}
|
|
|
|
operand->mode = M_DIRECT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
ret = -1;
|
2003-04-04 16:15:15 +08:00
|
|
|
for (i = 0; i < tic4x_num_indirects; i++)
|
|
|
|
if ((ret = tic4x_indirect_parse (operand, &tic4x_indirects[i])))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
2003-04-04 16:15:15 +08:00
|
|
|
if (i < tic4x_num_indirects)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
operand->mode = M_INDIRECT;
|
|
|
|
/* Indirect addressing mode number. */
|
2003-04-04 16:15:15 +08:00
|
|
|
operand->expr.X_add_number = tic4x_indirects[i].modn;
|
2002-08-28 18:38:51 +08:00
|
|
|
/* Convert *+ARn(0) to *ARn etc. Maybe we should
|
|
|
|
squeal about silly ones? */
|
|
|
|
if (operand->expr.X_add_number < 0x08 && !operand->disp)
|
|
|
|
operand->expr.X_add_number = 0x18;
|
|
|
|
}
|
|
|
|
else
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Unknown indirect addressing mode"));
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
operand->mode = M_IMMED; /* Assume immediate. */
|
|
|
|
str = input_line_pointer;
|
2003-04-04 16:15:15 +08:00
|
|
|
input_line_pointer = tic4x_expression (input_line_pointer, exp);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (exp->X_op == O_register)
|
|
|
|
{
|
|
|
|
know (exp->X_add_symbol == 0);
|
|
|
|
know (exp->X_op_symbol == 0);
|
|
|
|
operand->mode = M_REGISTER;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (exp->X_op == O_big)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number > 0)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Number too large")); /* bignum required. */
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_gen_to_words (generic_floating_point_number,
|
2002-08-28 18:38:51 +08:00
|
|
|
operand->fwords, S_PRECISION);
|
|
|
|
operand->mode = M_IMMED_F;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-04-04 16:15:15 +08:00
|
|
|
#ifdef TIC4X_ALT_SYNTAX
|
2002-08-28 18:38:51 +08:00
|
|
|
/* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0. */
|
|
|
|
else if (exp->X_op == O_symbol)
|
|
|
|
{
|
|
|
|
operand->mode = M_DIRECT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
if (entry == NULL)
|
Updated sources to avoid using the identifier name "new", which is a
keyword in c++.
* bfd/aoutx.h (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol.
* bfd/coffgen.c (coff_make_empty_symbol)
(coff_bfd_make_debug_symbol): Rename variable new to new_symbol.
* bfd/cpu-ia64-opc.c (ext_reg, ins_imms_scaled): Rename variable
new to new_insn.
* bfd/doc/chew.c (newentry, add_intrinsic): Rename variable new to
new_d.
* bfd/ecoff.c (_bfd_ecoff_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/elf32-m68k.c (elf_m68k_get_got_entry_type): Rename argument
new to new_reloc.
* bfd/hash.c (bfd_hash_lookup): Rename variable new to new_string.
* bfd/ieee.c (ieee_make_empty_symbol): Rename variable new to
new_symbol.
* bfd/linker.c (bfd_new_link_order): Rename variable new to
new_lo.
* bfd/mach-o.c (bfd_mach_o_sizeof_headers): Rename variable new to
symbol.
* bfd/oasys.c (oasys_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/pdp11.c (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol_type.
* bfd/plugin.c (bfd_plugin_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/rs6000-core.c (CoreHdr, VmInfo): Rename union member new to
new_dump.
(read_hdr, rs6000coff_core_p)
(rs6000coff_core_file_matches_executable_p)
(rs6000coff_core_file_failing_command)
(rs6000coff_core_file_failing_signal): Updated function to use new
union member name.
* bfd/som.c (som_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/syms.c (_bfd_generic_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/tekhex.c (first_phase, tekhex_make_empty_symbol): Rename
variable new to new_symbol.
* binutils/nlmconv.c (main): Rename variable new to new_name.
* gas/config/tc-arm.c (insert_reg_alias): Rename variable new to
new_reg.
* gas/config/tc-dlx.c (parse_operand): Rename variable new to
new_pos.
* gas/config/tc-ia64.c (ia64_gen_real_reloc_type): Rename variable
new to newr.
* gas/config/tc-mcore.c (parse_exp, parse_imm): Rename variable
new to new_pointer.
* gas/config/tc-microblaze.c (parse_exp, parse_imm, check_got):
Change name from new to new_pointer.
* gas/config/tc-or32.c (parse_operand): Rename variable new to
new_pointer.
* gas/config/tc-pdp11.c (md_assemble): Rename variable new to
new_pointer.
* gas/config/tc-pj.c (alias): Change argument new to new_name.
* gas/config/tc-score.c (s3_build_score_ops_hsh): Rename variable
new to new_opcode. (s3_build_dependency_insn_hsh) Rename variable
new to new_i2n. (s3_convert): Rename variables old and new to
r_old and r_new.
* gas/config/tc-score7.c (s7_build_score_ops_hsh): Rename variable
new to new_opcode. (s7_build_dependency_insn_hsh): Rename variable
new to new_i2d. (s7_b32_relax_to_b16, s7_convert_frag): Rename
variables old and new to r_old and r_new.
* gas/config/tc-sh.c (parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-sh64.c (shmedia_parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-tic4x.c (tic4x_operand_parse): Rename variable new
to new_pointer.
* gas/config/tc-z8k.c (parse_exp): Rename variable new to
new_pointer.
* gas/listing.c (listing_newline): Rename variable new to new_i.
* ld/ldexp.c (exp_intop, exp_bigintop, exp_relop, exp_binop)
(exp_trinop, exp_unop, exp_nameop, exp_assop): Rename variable new
to new_e.
* ld/ldfile.c (ldfile_add_library_path): Rename variable new to
new_dirs. (ldfile_add_arch): Rename variable new to new_arch.
* ld/ldlang.c (new_statement, lang_final, lang_add_wild)
(lang_target, lang_add_fill, lang_add_data, lang_add_assignment)
(lang_add_insert): Rename variable new to new_stmt. (new_afile):
Added missing cast. (lang_memory_region_lookup): Rename variable
new to new_region. (init_os): Rename variable new to
new_userdata. (lang_add_section): Rename variable new to
new_section. (ldlang_add_undef): Rename variable new to
new_undef. (realsymbol): Rename variable new to new_name.
* opcodes/z8kgen.c (internal, gas): Rename variable new to new_op.
Updated sources to avoid using the identifier name "template",
which is a keyword in c++.
* bfd/elf32-arm.c (struct stub_def): Rename member template to
template_sequence. (arm_build_one_stub,
find_stub_size_and_template, arm_size_one_stub, arm_map_one_stub):
Rename variable template to template_sequence.
* bfd/elfxx-ia64.c (elfNN_ia64_relax_br, elfNN_ia64_relax_brl):
Rename variable template to template_val.
* gas/config/tc-arm.c (struct asm_cond, struct asm_psr, struct
asm_barrier_opt): Change member template to
template_name. (md_begin): Update code to reflect new member
names.
* gas/config/tc-i386.c (struct templates, struct _i386_insn)
(match_template, cpu_flags_match, match_reg_size, match_mem_size)
(operand_size_match, md_begin, i386_print_statistics, pi)
(build_vex_prefix, md_assemble, parse_insn, optimize_imm)
(optimize_disp): Updated code to use new names. (parse_insn):
Added casts.
* gas/config/tc-ia64.c (dot_template, emit_one_bundle): Updated
code to use new names.
* gas/config/tc-score.c (struct s3_asm_opcode): Renamed member
template to template_name. (s3_parse_16_32_inst, s3_parse_48_inst,
s3_do_macro_ldst_label, s3_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-score7.c (struct s7_asm_opcode): Renamed member
template to template_name. (s7_parse_16_32_inst,
s7_do_macro_ldst_label, s7_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-tic30.c (md_begin, struct tic30_insn)
(md_assemble): Update code to use new names.
* gas/config/tc-tic54x.c (struct _tic54x_insn, md_begin)
(optimize_insn, tic54x_parse_insn, next_line_shows_parallel):
Update code to use new names.
* include/opcode/tic30.h (template): Rename type template to
insn_template. Updated code to use new name.
* include/opcode/tic54x.h (template): Rename type template to
insn_template.
* opcodes/cris-dis.c (bytes_to_skip): Update code to use new name.
* opcodes/i386-dis.c (putop): Update code to use new name.
* opcodes/i386-gen.c (process_i386_opcodes): Update code to use
new name.
* opcodes/i386-opc.h (struct template): Rename struct template to
insn_template. Update code accordingly.
* opcodes/i386-tbl.h (i386_optab): Update type to use new name.
* opcodes/ia64-dis.c (print_insn_ia64): Rename variable template
to template_val.
* opcodes/tic30-dis.c (struct instruction, get_tic30_instruction):
Update code to use new name.
* opcodes/tic54x-dis.c (has_lkaddr, get_insn_size)
(print_parallel_instruction, print_insn_tic54x, tic54x_get_insn):
Update code to use new name.
* opcodes/tic54x-opc.c (tic54x_unknown_opcode, tic54x_optab):
Update type to new name.
2009-08-30 06:11:02 +08:00
|
|
|
new_pointer = input_line_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
input_line_pointer = save;
|
Updated sources to avoid using the identifier name "new", which is a
keyword in c++.
* bfd/aoutx.h (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol.
* bfd/coffgen.c (coff_make_empty_symbol)
(coff_bfd_make_debug_symbol): Rename variable new to new_symbol.
* bfd/cpu-ia64-opc.c (ext_reg, ins_imms_scaled): Rename variable
new to new_insn.
* bfd/doc/chew.c (newentry, add_intrinsic): Rename variable new to
new_d.
* bfd/ecoff.c (_bfd_ecoff_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/elf32-m68k.c (elf_m68k_get_got_entry_type): Rename argument
new to new_reloc.
* bfd/hash.c (bfd_hash_lookup): Rename variable new to new_string.
* bfd/ieee.c (ieee_make_empty_symbol): Rename variable new to
new_symbol.
* bfd/linker.c (bfd_new_link_order): Rename variable new to
new_lo.
* bfd/mach-o.c (bfd_mach_o_sizeof_headers): Rename variable new to
symbol.
* bfd/oasys.c (oasys_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/pdp11.c (NAME (aout, make_empty_symbol)): Rename variable
new to new_symbol_type.
* bfd/plugin.c (bfd_plugin_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/rs6000-core.c (CoreHdr, VmInfo): Rename union member new to
new_dump.
(read_hdr, rs6000coff_core_p)
(rs6000coff_core_file_matches_executable_p)
(rs6000coff_core_file_failing_command)
(rs6000coff_core_file_failing_signal): Updated function to use new
union member name.
* bfd/som.c (som_make_empty_symbol): Rename variable new to
new_symbol_type.
* bfd/syms.c (_bfd_generic_make_empty_symbol): Rename variable new
to new_symbol.
* bfd/tekhex.c (first_phase, tekhex_make_empty_symbol): Rename
variable new to new_symbol.
* binutils/nlmconv.c (main): Rename variable new to new_name.
* gas/config/tc-arm.c (insert_reg_alias): Rename variable new to
new_reg.
* gas/config/tc-dlx.c (parse_operand): Rename variable new to
new_pos.
* gas/config/tc-ia64.c (ia64_gen_real_reloc_type): Rename variable
new to newr.
* gas/config/tc-mcore.c (parse_exp, parse_imm): Rename variable
new to new_pointer.
* gas/config/tc-microblaze.c (parse_exp, parse_imm, check_got):
Change name from new to new_pointer.
* gas/config/tc-or32.c (parse_operand): Rename variable new to
new_pointer.
* gas/config/tc-pdp11.c (md_assemble): Rename variable new to
new_pointer.
* gas/config/tc-pj.c (alias): Change argument new to new_name.
* gas/config/tc-score.c (s3_build_score_ops_hsh): Rename variable
new to new_opcode. (s3_build_dependency_insn_hsh) Rename variable
new to new_i2n. (s3_convert): Rename variables old and new to
r_old and r_new.
* gas/config/tc-score7.c (s7_build_score_ops_hsh): Rename variable
new to new_opcode. (s7_build_dependency_insn_hsh): Rename variable
new to new_i2d. (s7_b32_relax_to_b16, s7_convert_frag): Rename
variables old and new to r_old and r_new.
* gas/config/tc-sh.c (parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-sh64.c (shmedia_parse_exp): Rename variable new to
new_pointer.
* gas/config/tc-tic4x.c (tic4x_operand_parse): Rename variable new
to new_pointer.
* gas/config/tc-z8k.c (parse_exp): Rename variable new to
new_pointer.
* gas/listing.c (listing_newline): Rename variable new to new_i.
* ld/ldexp.c (exp_intop, exp_bigintop, exp_relop, exp_binop)
(exp_trinop, exp_unop, exp_nameop, exp_assop): Rename variable new
to new_e.
* ld/ldfile.c (ldfile_add_library_path): Rename variable new to
new_dirs. (ldfile_add_arch): Rename variable new to new_arch.
* ld/ldlang.c (new_statement, lang_final, lang_add_wild)
(lang_target, lang_add_fill, lang_add_data, lang_add_assignment)
(lang_add_insert): Rename variable new to new_stmt. (new_afile):
Added missing cast. (lang_memory_region_lookup): Rename variable
new to new_region. (init_os): Rename variable new to
new_userdata. (lang_add_section): Rename variable new to
new_section. (ldlang_add_undef): Rename variable new to
new_undef. (realsymbol): Rename variable new to new_name.
* opcodes/z8kgen.c (internal, gas): Rename variable new to new_op.
Updated sources to avoid using the identifier name "template",
which is a keyword in c++.
* bfd/elf32-arm.c (struct stub_def): Rename member template to
template_sequence. (arm_build_one_stub,
find_stub_size_and_template, arm_size_one_stub, arm_map_one_stub):
Rename variable template to template_sequence.
* bfd/elfxx-ia64.c (elfNN_ia64_relax_br, elfNN_ia64_relax_brl):
Rename variable template to template_val.
* gas/config/tc-arm.c (struct asm_cond, struct asm_psr, struct
asm_barrier_opt): Change member template to
template_name. (md_begin): Update code to reflect new member
names.
* gas/config/tc-i386.c (struct templates, struct _i386_insn)
(match_template, cpu_flags_match, match_reg_size, match_mem_size)
(operand_size_match, md_begin, i386_print_statistics, pi)
(build_vex_prefix, md_assemble, parse_insn, optimize_imm)
(optimize_disp): Updated code to use new names. (parse_insn):
Added casts.
* gas/config/tc-ia64.c (dot_template, emit_one_bundle): Updated
code to use new names.
* gas/config/tc-score.c (struct s3_asm_opcode): Renamed member
template to template_name. (s3_parse_16_32_inst, s3_parse_48_inst,
s3_do_macro_ldst_label, s3_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-score7.c (struct s7_asm_opcode): Renamed member
template to template_name. (s7_parse_16_32_inst,
s7_do_macro_ldst_label, s7_build_score_ops_hsh): Update code to
use new names.
* gas/config/tc-tic30.c (md_begin, struct tic30_insn)
(md_assemble): Update code to use new names.
* gas/config/tc-tic54x.c (struct _tic54x_insn, md_begin)
(optimize_insn, tic54x_parse_insn, next_line_shows_parallel):
Update code to use new names.
* include/opcode/tic30.h (template): Rename type template to
insn_template. Updated code to use new name.
* include/opcode/tic54x.h (template): Rename type template to
insn_template.
* opcodes/cris-dis.c (bytes_to_skip): Update code to use new name.
* opcodes/i386-dis.c (putop): Update code to use new name.
* opcodes/i386-gen.c (process_i386_opcodes): Update code to use
new name.
* opcodes/i386-opc.h (struct template): Rename struct template to
insn_template. Update code accordingly.
* opcodes/i386-tbl.h (i386_optab): Update type to use new name.
* opcodes/ia64-dis.c (print_insn_ia64): Rename variable template
to template_val.
* opcodes/tic30-dis.c (struct instruction, get_tic30_instruction):
Update code to use new name.
* opcodes/tic54x-dis.c (has_lkaddr, get_insn_size)
(print_parallel_instruction, print_insn_tic54x, tic54x_get_insn):
Update code to use new name.
* opcodes/tic54x-opc.c (tic54x_unknown_opcode, tic54x_optab):
Update type to new name.
2009-08-30 06:11:02 +08:00
|
|
|
return new_pointer;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static int
|
2009-12-11 21:42:17 +08:00
|
|
|
tic4x_operands_match (tic4x_inst_t *inst, tic4x_insn_t *tinsn, int check)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
const char *args = inst->args;
|
|
|
|
unsigned long opcode = inst->opcode;
|
2009-12-11 21:42:17 +08:00
|
|
|
int num_operands = tinsn->num_operands;
|
|
|
|
tic4x_operand_t *operand = tinsn->operands;
|
2002-08-28 18:38:51 +08:00
|
|
|
expressionS *exp = &operand->expr;
|
|
|
|
int ret = 1;
|
|
|
|
int reg;
|
|
|
|
|
|
|
|
/* Build the opcode, checking as we go to make sure that the
|
|
|
|
operands match.
|
|
|
|
|
|
|
|
If an operand matches, we modify insn or opcode appropriately,
|
|
|
|
and do a "continue". If an operand fails to match, we "break". */
|
|
|
|
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->nchars = 4; /* Instructions always 4 bytes. */
|
|
|
|
tinsn->reloc = NO_RELOC;
|
|
|
|
tinsn->pcrel = 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
if (*args == '\0')
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->opcode = opcode;
|
2002-08-28 18:38:51 +08:00
|
|
|
return num_operands == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;; ++args)
|
|
|
|
{
|
|
|
|
switch (*args)
|
|
|
|
{
|
|
|
|
|
|
|
|
case '\0': /* End of args. */
|
|
|
|
if (num_operands == 1)
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->opcode = opcode;
|
2002-08-28 18:38:51 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
break; /* Too many operands. */
|
|
|
|
|
|
|
|
case '#': /* This is only used for ldp. */
|
|
|
|
if (operand->mode != M_DIRECT && operand->mode != M_IMMED)
|
|
|
|
break;
|
|
|
|
/* While this looks like a direct addressing mode, we actually
|
|
|
|
use an immediate mode form of ldiu or ldpk instruction. */
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
if( ( IS_CPU_TIC4X (tic4x_cpu) && exp->X_add_number <= 65535 )
|
|
|
|
|| ( IS_CPU_TIC3X (tic4x_cpu) && exp->X_add_number <= 255 ) )
|
2002-11-16 20:23:23 +08:00
|
|
|
{
|
|
|
|
INSERTS (opcode, exp->X_add_number, 15, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Immediate value of %ld is too large for ldf"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-11-16 20:23:23 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else if (exp->X_op == O_symbol)
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_HI16;
|
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break; /* Not direct (dp) addressing. */
|
|
|
|
|
|
|
|
case '@': /* direct. */
|
|
|
|
if (operand->mode != M_DIRECT)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_constant)
|
2002-11-25 17:01:30 +08:00
|
|
|
{
|
|
|
|
/* Store only the 16 LSBs of the number. */
|
|
|
|
INSERTS (opcode, exp->X_add_number, 15, 0);
|
|
|
|
continue;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else if (exp->X_op == O_symbol)
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_LO16;
|
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break; /* Not direct addressing. */
|
|
|
|
|
|
|
|
case 'A':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_AR0 && reg <= REG_AR7)
|
|
|
|
INSERTU (opcode, reg - REG_AR0, 24, 22);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Destination register must be ARn"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'B': /* Unsigned integer immediate. */
|
|
|
|
/* Allow br label or br @label. */
|
|
|
|
if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number < (1 << 24))
|
|
|
|
{
|
|
|
|
INSERTU (opcode, exp->X_add_number, 23, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Immediate value of %ld is too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2003-04-04 16:15:15 +08:00
|
|
|
if (IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_24_PCREL;
|
|
|
|
tinsn->pcrel = 1;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_24;
|
|
|
|
tinsn->pcrel = 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'C':
|
2003-04-04 16:15:15 +08:00
|
|
|
if (!IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
if (operand->mode != M_INDIRECT)
|
|
|
|
break;
|
2002-11-16 20:23:23 +08:00
|
|
|
/* Require either *+ARn(disp) or *ARn. */
|
2002-08-28 18:38:51 +08:00
|
|
|
if (operand->expr.X_add_number != 0
|
|
|
|
&& operand->expr.X_add_number != 0x18)
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid indirect addressing mode"));
|
2002-11-18 17:09:35 +08:00
|
|
|
ret = -1;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
|
|
|
|
INSERTU (opcode, operand->disp, 7, 3);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
if (!(operand->mode == M_REGISTER))
|
|
|
|
break;
|
|
|
|
INSERTU (opcode, exp->X_add_number, 7, 0);
|
|
|
|
continue;
|
|
|
|
|
2002-11-16 20:23:23 +08:00
|
|
|
case 'e':
|
|
|
|
if (!(operand->mode == M_REGISTER))
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
2015-08-12 19:40:42 +08:00
|
|
|
if ( (reg >= REG_R0 && reg <= REG_R7)
|
2003-04-04 16:15:15 +08:00
|
|
|
|| (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
|
2002-11-16 20:23:23 +08:00
|
|
|
INSERTU (opcode, reg, 7, 0);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be Rn"));
|
2002-11-16 20:23:23 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'F':
|
|
|
|
if (operand->mode != M_IMMED_F
|
|
|
|
&& !(operand->mode == M_IMMED && exp->X_op == O_constant))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (operand->mode != M_IMMED_F)
|
|
|
|
{
|
|
|
|
/* OK, we 've got something like cmpf 0, r0
|
|
|
|
Why can't they stick in a bloody decimal point ?! */
|
|
|
|
char string[16];
|
|
|
|
|
|
|
|
/* Create floating point number string. */
|
|
|
|
sprintf (string, "%d.0", (int) exp->X_add_number);
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_atof (string, 's', operand->fwords);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
INSERTU (opcode, operand->fwords[0], 15, 0);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'G':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
INSERTU (opcode, exp->X_add_number, 15, 8);
|
|
|
|
continue;
|
|
|
|
|
2002-11-16 20:23:23 +08:00
|
|
|
case 'g':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
2015-08-12 19:40:42 +08:00
|
|
|
if ( (reg >= REG_R0 && reg <= REG_R7)
|
2003-04-04 16:15:15 +08:00
|
|
|
|| (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
|
2002-11-16 20:23:23 +08:00
|
|
|
INSERTU (opcode, reg, 15, 8);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be Rn"));
|
2002-11-16 20:23:23 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'H':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_R0 && reg <= REG_R7)
|
|
|
|
INSERTU (opcode, reg - REG_R0, 18, 16);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be R0--R7"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2002-11-18 17:09:35 +08:00
|
|
|
case 'i':
|
|
|
|
if ( operand->mode == M_REGISTER
|
2003-04-04 16:15:15 +08:00
|
|
|
&& tic4x_oplevel & OP_ENH )
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
INSERTU (opcode, reg, 4, 0);
|
|
|
|
INSERTU (opcode, 7, 7, 5);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Fallthrough */
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'I':
|
|
|
|
if (operand->mode != M_INDIRECT)
|
|
|
|
break;
|
|
|
|
if (operand->disp != 0 && operand->disp != 1)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
if (IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid indirect addressing mode displacement %d"),
|
2002-11-18 17:09:35 +08:00
|
|
|
operand->disp);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
|
|
|
|
INSERTU (opcode, operand->expr.X_add_number, 7, 3);
|
|
|
|
continue;
|
|
|
|
|
2002-11-18 17:09:35 +08:00
|
|
|
case 'j':
|
|
|
|
if ( operand->mode == M_REGISTER
|
2003-04-04 16:15:15 +08:00
|
|
|
&& tic4x_oplevel & OP_ENH )
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
INSERTU (opcode, reg, 12, 8);
|
|
|
|
INSERTU (opcode, 7, 15, 13);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Fallthrough */
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'J':
|
|
|
|
if (operand->mode != M_INDIRECT)
|
|
|
|
break;
|
|
|
|
if (operand->disp != 0 && operand->disp != 1)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
if (IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid indirect addressing mode displacement %d"),
|
2002-11-18 17:09:35 +08:00
|
|
|
operand->disp);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
|
|
|
|
INSERTU (opcode, operand->expr.X_add_number, 15, 11);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'K':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_R0 && reg <= REG_R7)
|
|
|
|
INSERTU (opcode, reg - REG_R0, 21, 19);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be R0--R7"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'L':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_R0 && reg <= REG_R7)
|
|
|
|
INSERTU (opcode, reg - REG_R0, 24, 22);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be R0--R7"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'M':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg == REG_R2 || reg == REG_R3)
|
|
|
|
INSERTU (opcode, reg - REG_R2, 22, 22);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Destination register must be R2 or R3"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'N':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg == REG_R0 || reg == REG_R1)
|
|
|
|
INSERTU (opcode, reg - REG_R0, 23, 23);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Destination register must be R0 or R1"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'O':
|
2003-04-04 16:15:15 +08:00
|
|
|
if (!IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
if (operand->mode != M_INDIRECT)
|
|
|
|
break;
|
|
|
|
/* Require either *+ARn(disp) or *ARn. */
|
|
|
|
if (operand->expr.X_add_number != 0
|
|
|
|
&& operand->expr.X_add_number != 0x18)
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid indirect addressing mode"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
|
|
|
|
INSERTU (opcode, operand->disp, 15, 11);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'P': /* PC relative displacement. */
|
|
|
|
/* Allow br label or br @label. */
|
|
|
|
if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number >= -32768 && exp->X_add_number <= 32767)
|
|
|
|
{
|
|
|
|
INSERTS (opcode, exp->X_add_number, 15, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Displacement value of %ld is too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_16_PCREL;
|
|
|
|
tinsn->pcrel = 1;
|
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'Q':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
INSERTU (opcode, reg, 15, 0);
|
|
|
|
continue;
|
|
|
|
|
2002-11-16 20:23:23 +08:00
|
|
|
case 'q':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
2015-08-12 19:40:42 +08:00
|
|
|
if ( (reg >= REG_R0 && reg <= REG_R7)
|
2003-04-04 16:15:15 +08:00
|
|
|
|| (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
|
2002-11-16 20:23:23 +08:00
|
|
|
INSERTU (opcode, reg, 15, 0);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be Rn"));
|
2002-11-16 20:23:23 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'R':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
INSERTU (opcode, reg, 20, 16);
|
|
|
|
continue;
|
|
|
|
|
2002-11-16 20:23:23 +08:00
|
|
|
case 'r':
|
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
2015-08-12 19:40:42 +08:00
|
|
|
if ( (reg >= REG_R0 && reg <= REG_R7)
|
2003-04-04 16:15:15 +08:00
|
|
|
|| (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
|
2002-11-16 20:23:23 +08:00
|
|
|
INSERTU (opcode, reg, 20, 16);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be Rn"));
|
2002-11-16 20:23:23 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'S': /* Short immediate int. */
|
|
|
|
if (operand->mode != M_IMMED && operand->mode != M_HI)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_big)
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Floating point number not valid in expression"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number >= -32768 && exp->X_add_number <= 65535)
|
|
|
|
{
|
|
|
|
INSERTS (opcode, exp->X_add_number, 15, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Signed immediate value %ld too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (exp->X_op == O_symbol)
|
|
|
|
{
|
|
|
|
if (operand->mode == M_HI)
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_HI16;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_LO16;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Handle cases like ldi foo - $, ar0 where foo
|
|
|
|
is a forward reference. Perhaps we should check
|
|
|
|
for X_op == O_symbol and disallow things like
|
|
|
|
ldi foo, ar0. */
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_16;
|
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
case 'T': /* 5-bit immediate value for tic4x stik. */
|
|
|
|
if (!IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
if (operand->mode != M_IMMED)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number < 16 && exp->X_add_number >= -16)
|
|
|
|
{
|
|
|
|
INSERTS (opcode, exp->X_add_number, 20, 16);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Immediate value of %ld is too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break; /* No relocations allowed. */
|
|
|
|
|
|
|
|
case 'U': /* Unsigned integer immediate. */
|
|
|
|
if (operand->mode != M_IMMED && operand->mode != M_HI)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number < (1 << 16) && exp->X_add_number >= 0)
|
|
|
|
{
|
|
|
|
INSERTU (opcode, exp->X_add_number, 15, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Unsigned immediate value %ld too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (exp->X_op == O_symbol)
|
|
|
|
{
|
|
|
|
if (operand->mode == M_HI)
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_HI16;
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_LO16;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_16;
|
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
case 'V': /* Trap numbers (immediate field). */
|
|
|
|
if (operand->mode != M_IMMED)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
if (exp->X_add_number < 512 && IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
INSERTU (opcode, exp->X_add_number, 8, 0);
|
|
|
|
continue;
|
|
|
|
}
|
2003-04-04 16:15:15 +08:00
|
|
|
else if (exp->X_add_number < 32 && IS_CPU_TIC3X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2020-01-12 17:46:22 +08:00
|
|
|
INSERTU (opcode, exp->X_add_number | 0x20, 5, 0);
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Immediate value of %ld is too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break; /* No relocations allowed. */
|
|
|
|
|
|
|
|
case 'W': /* Short immediate int (0--7). */
|
2003-04-04 16:15:15 +08:00
|
|
|
if (!IS_CPU_TIC4X (tic4x_cpu))
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
if (operand->mode != M_IMMED)
|
|
|
|
break;
|
|
|
|
if (exp->X_op == O_big)
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Floating point number not valid in expression"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (exp->X_op == O_constant)
|
|
|
|
{
|
|
|
|
if (exp->X_add_number >= -256 && exp->X_add_number <= 127)
|
|
|
|
{
|
|
|
|
INSERTS (opcode, exp->X_add_number, 7, 0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Immediate value %ld too large"),
|
2002-11-18 17:09:35 +08:00
|
|
|
(long) exp->X_add_number);
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->reloc = BFD_RELOC_16;
|
|
|
|
tinsn->exp = *exp;
|
2002-08-28 18:38:51 +08:00
|
|
|
continue;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
case 'X': /* Expansion register for tic4x. */
|
2002-08-28 18:38:51 +08:00
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_IVTP && reg <= REG_TVTP)
|
|
|
|
INSERTU (opcode, reg - REG_IVTP, 4, 0);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be ivtp or tvtp"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
case 'Y': /* Address register for tic4x lda. */
|
2002-08-28 18:38:51 +08:00
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_AR0 && reg <= REG_SP)
|
|
|
|
INSERTU (opcode, reg, 20, 16);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be address register"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
case 'Z': /* Expansion register for tic4x. */
|
2002-08-28 18:38:51 +08:00
|
|
|
if (operand->mode != M_REGISTER)
|
|
|
|
break;
|
|
|
|
reg = exp->X_add_number;
|
|
|
|
if (reg >= REG_IVTP && reg <= REG_TVTP)
|
|
|
|
INSERTU (opcode, reg - REG_IVTP, 20, 16);
|
|
|
|
else
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
if (!check)
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Register must be ivtp or tvtp"));
|
2002-08-28 18:38:51 +08:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
if (operand->mode != M_INDIRECT)
|
|
|
|
break;
|
|
|
|
INSERTS (opcode, operand->disp, 7, 0);
|
|
|
|
INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
|
|
|
|
INSERTU (opcode, operand->expr.X_add_number, 15, 11);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case '|': /* treat as `,' if have ldi_ldi form. */
|
2009-12-11 21:42:17 +08:00
|
|
|
if (tinsn->parallel)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
if (--num_operands < 0)
|
|
|
|
break; /* Too few operands. */
|
|
|
|
operand++;
|
|
|
|
if (operand->mode != M_PARALLEL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Fall through. */
|
|
|
|
|
|
|
|
case ',': /* Another operand. */
|
|
|
|
if (--num_operands < 0)
|
|
|
|
break; /* Too few operands. */
|
|
|
|
operand++;
|
|
|
|
exp = &operand->expr;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case ';': /* Another optional operand. */
|
|
|
|
if (num_operands == 1 || operand[1].mode == M_PARALLEL)
|
|
|
|
continue;
|
|
|
|
if (--num_operands < 0)
|
|
|
|
break; /* Too few operands. */
|
|
|
|
operand++;
|
|
|
|
exp = &operand->expr;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
default:
|
|
|
|
BAD_CASE (*args);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-18 17:09:35 +08:00
|
|
|
static void
|
2009-12-11 21:42:17 +08:00
|
|
|
tic4x_insn_check (tic4x_insn_t *tinsn)
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2009-12-11 21:42:17 +08:00
|
|
|
if (!strcmp (tinsn->name, "lda"))
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
2009-12-11 21:42:17 +08:00
|
|
|
if (tinsn->num_operands < 2 || tinsn->num_operands > 2)
|
2002-11-18 17:09:35 +08:00
|
|
|
as_fatal ("Illegal internal LDA insn definition");
|
|
|
|
|
2009-12-11 21:42:17 +08:00
|
|
|
if (tinsn->operands[0].mode == M_REGISTER
|
|
|
|
&& tinsn->operands[1].mode == M_REGISTER
|
|
|
|
&& tinsn->operands[0].expr.X_add_number == tinsn->operands[1].expr.X_add_number )
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Source and destination register should not be equal"));
|
2002-11-18 17:09:35 +08:00
|
|
|
}
|
2009-12-11 21:42:17 +08:00
|
|
|
else if (!strcmp (tinsn->name, "ldi_ldi")
|
|
|
|
|| !strcmp (tinsn->name, "ldi1_ldi2")
|
|
|
|
|| !strcmp (tinsn->name, "ldi2_ldi1")
|
|
|
|
|| !strcmp (tinsn->name, "ldf_ldf")
|
|
|
|
|| !strcmp (tinsn->name, "ldf1_ldf2")
|
|
|
|
|| !strcmp (tinsn->name, "ldf2_ldf1") )
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
2015-08-11 16:40:02 +08:00
|
|
|
if (tinsn->num_operands < 4 || tinsn->num_operands > 5)
|
2009-12-11 21:42:17 +08:00
|
|
|
as_fatal ("Illegal internal %s insn definition", tinsn->name);
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2009-12-11 21:42:17 +08:00
|
|
|
if (tinsn->operands[1].mode == M_REGISTER
|
|
|
|
&& tinsn->operands[tinsn->num_operands-1].mode == M_REGISTER
|
|
|
|
&& tinsn->operands[1].expr.X_add_number == tinsn->operands[tinsn->num_operands-1].expr.X_add_number )
|
2017-07-18 23:58:14 +08:00
|
|
|
as_warn (_("Equal parallel destination registers, one result will be discarded"));
|
2002-11-18 17:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static void
|
2009-12-11 21:42:17 +08:00
|
|
|
tic4x_insn_output (tic4x_insn_t *tinsn)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char *dst;
|
|
|
|
|
|
|
|
/* Grab another fragment for opcode. */
|
2009-12-11 21:42:17 +08:00
|
|
|
dst = frag_more (tinsn->nchars);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Put out opcode word as a series of bytes in little endian order. */
|
2009-12-11 21:42:17 +08:00
|
|
|
md_number_to_chars (dst, tinsn->opcode, tinsn->nchars);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
/* Put out the symbol-dependent stuff. */
|
2009-12-11 21:42:17 +08:00
|
|
|
if (tinsn->reloc != NO_RELOC)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* Where is the offset into the fragment for this instruction. */
|
|
|
|
fix_new_exp (frag_now,
|
|
|
|
dst - frag_now->fr_literal, /* where */
|
2009-12-11 21:42:17 +08:00
|
|
|
tinsn->nchars, /* size */
|
|
|
|
&tinsn->exp,
|
|
|
|
tinsn->pcrel,
|
|
|
|
tinsn->reloc);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse the operands. */
|
2015-08-12 19:40:42 +08:00
|
|
|
static int
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_operands_parse (char *s, tic4x_operand_t *operands, int num_operands)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
if (!*s)
|
|
|
|
return num_operands;
|
|
|
|
|
|
|
|
do
|
2003-04-04 16:15:15 +08:00
|
|
|
s = tic4x_operand_parse (s, &operands[num_operands++]);
|
|
|
|
while (num_operands < TIC4X_OPERANDS_MAX && *s++ == ',');
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
if (num_operands > TIC4X_OPERANDS_MAX)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Too many operands scanned"));
|
2002-08-28 18:38:51 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return num_operands;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assemble a single instruction. Its label has already been handled
|
|
|
|
by the generic front end. We just parse mnemonic and operands, and
|
|
|
|
produce the bytes of data and relocation. */
|
2015-08-12 19:40:42 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_assemble (char *str)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
int ok = 0;
|
|
|
|
char *s;
|
|
|
|
int i;
|
|
|
|
int parsed = 0;
|
2014-12-09 14:32:54 +08:00
|
|
|
size_t len;
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_inst_t *inst; /* Instruction template. */
|
|
|
|
tic4x_inst_t *first_inst;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-05-19 06:23:15 +08:00
|
|
|
/* Scan for parallel operators */
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
s = str;
|
|
|
|
while (*s && *s != '|')
|
|
|
|
s++;
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2003-05-19 06:23:15 +08:00
|
|
|
if (*s && s[1]=='|')
|
|
|
|
{
|
|
|
|
if(insn->parallel)
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Parallel opcode cannot contain more than two instructions"));
|
2003-05-19 06:23:15 +08:00
|
|
|
insn->parallel = 0;
|
|
|
|
insn->in_use = 0;
|
|
|
|
return;
|
|
|
|
}
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2003-05-19 06:23:15 +08:00
|
|
|
/* Lets take care of the first part of the parallel insn */
|
|
|
|
*s++ = 0;
|
|
|
|
md_assemble(str);
|
|
|
|
insn->parallel = 1;
|
|
|
|
str = ++s;
|
|
|
|
/* .. and let the second run though here */
|
|
|
|
}
|
|
|
|
}
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
if (str && insn->parallel)
|
|
|
|
{
|
|
|
|
/* Find mnemonic (second part of parallel instruction). */
|
|
|
|
s = str;
|
|
|
|
/* Skip past instruction mnemonic. */
|
2003-05-19 06:23:15 +08:00
|
|
|
while (*s && *s != ' ')
|
2002-08-28 18:38:51 +08:00
|
|
|
s++;
|
2020-08-18 16:57:21 +08:00
|
|
|
if (*s) /* Null terminate for str_hash_find. */
|
2002-08-28 18:38:51 +08:00
|
|
|
*s++ = '\0'; /* and skip past null. */
|
2014-12-09 14:32:54 +08:00
|
|
|
len = strlen (insn->name);
|
|
|
|
snprintf (insn->name + len, TIC4X_NAME_MAX - len, "_%s", str);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
insn->operands[insn->num_operands++].mode = M_PARALLEL;
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
if ((i = tic4x_operands_parse
|
2002-08-28 18:38:51 +08:00
|
|
|
(s, insn->operands, insn->num_operands)) < 0)
|
|
|
|
{
|
|
|
|
insn->parallel = 0;
|
|
|
|
insn->in_use = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
insn->num_operands = i;
|
|
|
|
parsed = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (insn->in_use)
|
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
if ((insn->inst = (struct tic4x_inst *)
|
2020-08-18 16:57:21 +08:00
|
|
|
str_hash_find (tic4x_op_hash, insn->name)) == NULL)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Unknown opcode `%s'."), insn->name);
|
2002-08-28 18:38:51 +08:00
|
|
|
insn->parallel = 0;
|
|
|
|
insn->in_use = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
inst = insn->inst;
|
2002-11-18 17:09:35 +08:00
|
|
|
first_inst = NULL;
|
2002-08-28 18:38:51 +08:00
|
|
|
do
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
ok = tic4x_operands_match (inst, insn, 1);
|
2002-11-18 17:09:35 +08:00
|
|
|
if (ok < 0)
|
|
|
|
{
|
|
|
|
if (!first_inst)
|
|
|
|
first_inst = inst;
|
|
|
|
ok = 0;
|
|
|
|
}
|
2019-05-10 23:57:31 +08:00
|
|
|
}
|
|
|
|
while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
if (ok > 0)
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_insn_check (insn);
|
|
|
|
tic4x_insn_output (insn);
|
2002-11-18 17:09:35 +08:00
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
else if (!ok)
|
2002-11-18 17:09:35 +08:00
|
|
|
{
|
|
|
|
if (first_inst)
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_operands_match (first_inst, insn, 0);
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid operands for %s"), insn->name);
|
2002-11-18 17:09:35 +08:00
|
|
|
}
|
2002-08-28 18:38:51 +08:00
|
|
|
else
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Invalid instruction %s"), insn->name);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (str && !parsed)
|
|
|
|
{
|
|
|
|
/* Find mnemonic. */
|
|
|
|
s = str;
|
|
|
|
while (*s && *s != ' ') /* Skip past instruction mnemonic. */
|
|
|
|
s++;
|
2020-08-18 16:57:21 +08:00
|
|
|
if (*s) /* Null terminate for str_hash_find. */
|
2002-08-28 18:38:51 +08:00
|
|
|
*s++ = '\0'; /* and skip past null. */
|
2014-12-09 14:32:54 +08:00
|
|
|
strncpy (insn->name, str, TIC4X_NAME_MAX - 1);
|
|
|
|
insn->name[TIC4X_NAME_MAX - 1] = '\0';
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
if ((i = tic4x_operands_parse (s, insn->operands, 0)) < 0)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
* config/obj-coff.c, config/tc-arm.c, config/tc-bfin.c,
config/tc-cris.c, config/tc-crx.c, config/tc-i386.c,
config/tc-ia64.c, config/tc-maxq.c, config/tc-maxq.h,
config/tc-mips.c, config/tc-msp430.c, config/tc-sh.c,
config/tc-tic4x.c, config/tc-xtensa.c: Fix comment typos.
2006-04-24 06:12:43 +08:00
|
|
|
insn->inst = NULL; /* Flag that error occurred. */
|
2002-08-28 18:38:51 +08:00
|
|
|
insn->parallel = 0;
|
|
|
|
insn->in_use = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
insn->num_operands = i;
|
|
|
|
insn->in_use = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
insn->in_use = 0;
|
|
|
|
insn->parallel = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_cleanup (void)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
if (insn->in_use)
|
|
|
|
md_assemble (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Turn a string in input_line_pointer into a floating point constant
|
|
|
|
of type type, and store the appropriate bytes in *litP. The number
|
2007-10-18 00:45:56 +08:00
|
|
|
of chars emitted is stored in *sizeP. An error message is
|
2002-08-28 18:38:51 +08:00
|
|
|
returned, or NULL on OK. */
|
|
|
|
|
2016-04-01 20:07:50 +08:00
|
|
|
const char *
|
2007-10-18 00:45:56 +08:00
|
|
|
md_atof (int type, char *litP, int *sizeP)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
int prec;
|
|
|
|
int ieee;
|
|
|
|
LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
|
|
|
LITTLENUM_TYPE *wordP;
|
2005-02-23 20:28:06 +08:00
|
|
|
char *t;
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
2007-10-18 00:45:56 +08:00
|
|
|
case 's': /* .single */
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'S':
|
|
|
|
ieee = 0;
|
|
|
|
prec = 1;
|
|
|
|
break;
|
|
|
|
|
2007-10-18 00:45:56 +08:00
|
|
|
case 'd': /* .double */
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'D':
|
2007-10-18 00:45:56 +08:00
|
|
|
case 'f': /* .float */
|
2002-08-28 18:38:51 +08:00
|
|
|
case 'F':
|
|
|
|
ieee = 0;
|
2007-10-18 00:45:56 +08:00
|
|
|
prec = 2; /* 1 32-bit word */
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
|
2007-10-18 00:45:56 +08:00
|
|
|
case 'i': /* .ieee */
|
2002-11-11 22:29:01 +08:00
|
|
|
case 'I':
|
2002-08-28 18:38:51 +08:00
|
|
|
prec = 2;
|
|
|
|
ieee = 1;
|
2007-10-18 00:45:56 +08:00
|
|
|
type = 'f'; /* Rewrite type to be usable by atof_ieee(). */
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
|
2007-10-18 00:45:56 +08:00
|
|
|
case 'e': /* .ldouble */
|
2002-11-11 22:29:01 +08:00
|
|
|
case 'E':
|
2007-10-18 00:45:56 +08:00
|
|
|
prec = 4; /* 2 32-bit words */
|
2002-11-11 22:29:01 +08:00
|
|
|
ieee = 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
*sizeP = 0;
|
2007-10-18 00:45:56 +08:00
|
|
|
return _("Unrecognized or unsupported floating point constant");
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ieee)
|
|
|
|
t = atof_ieee (input_line_pointer, type, words);
|
|
|
|
else
|
2003-04-04 16:15:15 +08:00
|
|
|
t = tic4x_atof (input_line_pointer, type, words);
|
2002-08-28 18:38:51 +08:00
|
|
|
if (t)
|
|
|
|
input_line_pointer = t;
|
|
|
|
*sizeP = prec * sizeof (LITTLENUM_TYPE);
|
2005-02-23 20:28:06 +08:00
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
/* This loops outputs the LITTLENUMs in REVERSE order; in accord with
|
|
|
|
little endian byte order. */
|
2002-11-11 22:29:01 +08:00
|
|
|
/* SES: However it is required to put the words (32-bits) out in the
|
|
|
|
correct order, hence we write 2 and 2 littlenums in little endian
|
2007-10-18 00:45:56 +08:00
|
|
|
order, while we keep the original order on successive words. */
|
|
|
|
for (wordP = words; wordP<(words+prec) ; wordP+=2)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2007-10-18 00:45:56 +08:00
|
|
|
if (wordP < (words + prec - 1)) /* Dump wordP[1] (if we have one). */
|
2002-11-11 22:29:01 +08:00
|
|
|
{
|
|
|
|
md_number_to_chars (litP, (valueT) (wordP[1]),
|
|
|
|
sizeof (LITTLENUM_TYPE));
|
|
|
|
litP += sizeof (LITTLENUM_TYPE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Dump wordP[0] */
|
|
|
|
md_number_to_chars (litP, (valueT) (wordP[0]),
|
|
|
|
sizeof (LITTLENUM_TYPE));
|
2002-08-28 18:38:51 +08:00
|
|
|
litP += sizeof (LITTLENUM_TYPE);
|
|
|
|
}
|
2007-10-18 00:45:56 +08:00
|
|
|
return NULL;
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_apply_fix (fixS *fixP, valueT *value, segT seg ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
|
|
|
|
valueT val = *value;
|
|
|
|
|
|
|
|
switch (fixP->fx_r_type)
|
|
|
|
{
|
|
|
|
case BFD_RELOC_HI16:
|
|
|
|
val >>= 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BFD_RELOC_LO16:
|
|
|
|
val &= 0xffff;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (fixP->fx_r_type)
|
|
|
|
{
|
|
|
|
case BFD_RELOC_32:
|
|
|
|
buf[3] = val >> 24;
|
2016-10-05 15:47:02 +08:00
|
|
|
/* Fall through. */
|
2002-08-28 18:38:51 +08:00
|
|
|
case BFD_RELOC_24:
|
|
|
|
case BFD_RELOC_24_PCREL:
|
|
|
|
buf[2] = val >> 16;
|
2016-10-05 15:47:02 +08:00
|
|
|
/* Fall through. */
|
2002-08-28 18:38:51 +08:00
|
|
|
case BFD_RELOC_16:
|
|
|
|
case BFD_RELOC_16_PCREL:
|
|
|
|
case BFD_RELOC_LO16:
|
|
|
|
case BFD_RELOC_HI16:
|
|
|
|
buf[1] = val >> 8;
|
|
|
|
buf[0] = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NO_RELOC:
|
|
|
|
default:
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Bad relocation type: 0x%02x"), fixP->fx_r_type);
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1;
|
|
|
|
}
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
/* Should never be called for tic4x. */
|
2015-08-12 19:40:42 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
|
|
|
|
segT sec ATTRIBUTE_UNUSED,
|
|
|
|
fragS *fragP ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
as_fatal ("md_convert_frag");
|
|
|
|
}
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
/* Should never be called for tic4x. */
|
2002-08-28 18:38:51 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_create_short_jump (char *ptr ATTRIBUTE_UNUSED,
|
|
|
|
addressT from_addr ATTRIBUTE_UNUSED,
|
|
|
|
addressT to_addr ATTRIBUTE_UNUSED,
|
|
|
|
fragS *frag ATTRIBUTE_UNUSED,
|
|
|
|
symbolS *to_symbol ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
as_fatal ("md_create_short_jmp\n");
|
|
|
|
}
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
/* Should never be called for tic4x. */
|
2002-08-28 18:38:51 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_create_long_jump (char *ptr ATTRIBUTE_UNUSED,
|
|
|
|
addressT from_addr ATTRIBUTE_UNUSED,
|
|
|
|
addressT to_addr ATTRIBUTE_UNUSED,
|
|
|
|
fragS *frag ATTRIBUTE_UNUSED,
|
|
|
|
symbolS *to_symbol ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
as_fatal ("md_create_long_jump\n");
|
|
|
|
}
|
|
|
|
|
2003-04-04 16:15:15 +08:00
|
|
|
/* Should never be called for tic4x. */
|
2002-08-28 18:38:51 +08:00
|
|
|
int
|
2008-08-13 07:39:31 +08:00
|
|
|
md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
|
|
|
|
segT segtype ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
as_fatal ("md_estimate_size_before_relax\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2016-02-27 22:35:32 +08:00
|
|
|
md_parse_option (int c, const char *arg)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
case OPTION_CPU: /* cpu brand */
|
2003-07-14 18:06:06 +08:00
|
|
|
if (TOLOWER (*arg) == 'c')
|
2002-08-28 18:38:51 +08:00
|
|
|
arg++;
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_cpu = atoi (arg);
|
|
|
|
if (!IS_CPU_TIC3X (tic4x_cpu) && !IS_CPU_TIC4X (tic4x_cpu))
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Unsupported processor generation %d"), tic4x_cpu);
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2002-11-18 17:09:35 +08:00
|
|
|
|
|
|
|
case OPTION_REV: /* cpu revision */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_revision = atoi (arg);
|
2002-11-18 17:09:35 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'b':
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Option -b is depreciated, please use -mbig"));
|
2016-10-05 15:47:02 +08:00
|
|
|
/* Fall through. */
|
2002-11-18 17:09:35 +08:00
|
|
|
case OPTION_BIG: /* big model */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_big_model = 1;
|
2002-11-18 17:09:35 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'p':
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Option -p is depreciated, please use -mmemparm"));
|
2016-10-05 15:47:02 +08:00
|
|
|
/* Fall through. */
|
2002-11-18 17:09:35 +08:00
|
|
|
case OPTION_MEMPARM: /* push args */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_reg_args = 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2002-11-18 17:09:35 +08:00
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
case 'r':
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Option -r is depreciated, please use -mregparm"));
|
2016-10-05 15:47:02 +08:00
|
|
|
/* Fall through. */
|
2002-11-18 17:09:35 +08:00
|
|
|
case OPTION_REGPARM: /* register args */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_reg_args = 1;
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2002-11-18 17:09:35 +08:00
|
|
|
|
|
|
|
case 's':
|
2009-07-24 19:45:01 +08:00
|
|
|
as_warn (_("Option -s is depreciated, please use -msmall"));
|
2016-10-05 15:47:02 +08:00
|
|
|
/* Fall through. */
|
2002-11-18 17:09:35 +08:00
|
|
|
case OPTION_SMALL: /* small model */
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_big_model = 0;
|
2002-08-28 18:38:51 +08:00
|
|
|
break;
|
2002-11-18 17:09:35 +08:00
|
|
|
|
|
|
|
case OPTION_IDLE2:
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_idle2 = 1;
|
2002-11-18 17:09:35 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPTION_LOWPOWER:
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_lowpower = 1;
|
2002-11-18 17:09:35 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPTION_ENHANCED:
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_enhanced = 1;
|
2002-11-18 17:09:35 +08:00
|
|
|
break;
|
|
|
|
|
2002-08-28 18:38:51 +08:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_show_usage (FILE *stream)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2002-11-18 17:09:35 +08:00
|
|
|
fprintf (stream,
|
|
|
|
_("\nTIC4X options:\n"
|
|
|
|
" -mcpu=CPU -mCPU select architecture variant. CPU can be:\n"
|
|
|
|
" 30 - TMS320C30\n"
|
|
|
|
" 31 - TMS320C31, TMS320LC31\n"
|
|
|
|
" 32 - TMS320C32\n"
|
|
|
|
" 33 - TMS320VC33\n"
|
|
|
|
" 40 - TMS320C40\n"
|
|
|
|
" 44 - TMS320C44\n"
|
|
|
|
" -mrev=REV set cpu hardware revision (integer numbers).\n"
|
|
|
|
" Combinations of -mcpu and -mrev will enable/disable\n"
|
|
|
|
" the appropriate options (-midle2, -mlowpower and\n"
|
|
|
|
" -menhanced) according to the selected type\n"
|
|
|
|
" -mbig select big memory model\n"
|
|
|
|
" -msmall select small memory model (default)\n"
|
|
|
|
" -mregparm select register parameters (default)\n"
|
|
|
|
" -mmemparm select memory parameters\n"
|
|
|
|
" -midle2 enable IDLE2 support\n"
|
|
|
|
" -mlowpower enable LOPOWER and MAXSPEED support\n"
|
|
|
|
" -menhanced enable enhanced opcode support\n"));
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This is called when a line is unrecognized. This is used to handle
|
|
|
|
definitions of TI C3x tools style local labels $n where n is a single
|
|
|
|
decimal digit. */
|
2015-08-12 19:40:42 +08:00
|
|
|
int
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_unrecognized_line (int c)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
int lab;
|
|
|
|
char *s;
|
|
|
|
|
2003-07-14 18:06:06 +08:00
|
|
|
if (c != '$' || ! ISDIGIT (input_line_pointer[0]))
|
2002-08-28 18:38:51 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
s = input_line_pointer;
|
|
|
|
|
|
|
|
/* Let's allow multiple digit local labels. */
|
|
|
|
lab = 0;
|
2003-07-14 18:06:06 +08:00
|
|
|
while (ISDIGIT (*s))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
lab = lab * 10 + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dollar_label_defined (lab))
|
|
|
|
{
|
2009-07-24 19:45:01 +08:00
|
|
|
as_bad (_("Label \"$%d\" redefined"), lab);
|
2002-08-28 18:38:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
define_dollar_label (lab);
|
|
|
|
colon (dollar_label_name (lab, 0));
|
|
|
|
input_line_pointer = s + 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle local labels peculiar to us referred to in an expression. */
|
|
|
|
symbolS *
|
2008-08-13 07:39:31 +08:00
|
|
|
md_undefined_symbol (char *name)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* Look for local labels of the form $n. */
|
2003-07-14 18:06:06 +08:00
|
|
|
if (name[0] == '$' && ISDIGIT (name[1]))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
symbolS *symbolP;
|
|
|
|
char *s = name + 1;
|
|
|
|
int lab = 0;
|
|
|
|
|
2003-07-14 18:06:06 +08:00
|
|
|
while (ISDIGIT ((unsigned char) *s))
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
lab = lab * 10 + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (dollar_label_defined (lab))
|
|
|
|
{
|
|
|
|
name = dollar_label_name (lab, 0);
|
|
|
|
symbolP = symbol_find (name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
name = dollar_label_name (lab, 1);
|
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return symbolP;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse an operand that is machine-specific. */
|
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Round up a section size to the appropriate boundary---do we need this? */
|
|
|
|
valueT
|
2008-08-13 07:39:31 +08:00
|
|
|
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
return size; /* Byte (i.e., 32-bit) alignment is fine? */
|
|
|
|
}
|
|
|
|
|
2015-08-12 19:40:42 +08:00
|
|
|
static int
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_pc_offset (unsigned int op)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
/* Determine the PC offset for a C[34]x instruction.
|
|
|
|
This could be simplified using some boolean algebra
|
|
|
|
but at the expense of readability. */
|
|
|
|
switch (op >> 24)
|
|
|
|
{
|
|
|
|
case 0x60: /* br */
|
|
|
|
case 0x62: /* call (C4x) */
|
|
|
|
case 0x64: /* rptb (C4x) */
|
|
|
|
return 1;
|
|
|
|
case 0x61: /* brd */
|
|
|
|
case 0x63: /* laj */
|
|
|
|
case 0x65: /* rptbd (C4x) */
|
|
|
|
return 3;
|
|
|
|
case 0x66: /* swi */
|
|
|
|
case 0x67:
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ((op & 0xffe00000) >> 20)
|
|
|
|
{
|
|
|
|
case 0x6a0: /* bB */
|
|
|
|
case 0x720: /* callB */
|
|
|
|
case 0x740: /* trapB */
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case 0x6a2: /* bBd */
|
|
|
|
case 0x6a6: /* bBat */
|
|
|
|
case 0x6aa: /* bBaf */
|
|
|
|
case 0x722: /* lajB */
|
|
|
|
case 0x748: /* latB */
|
|
|
|
case 0x798: /* rptbd */
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ((op & 0xfe200000) >> 20)
|
|
|
|
{
|
|
|
|
case 0x6e0: /* dbB */
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case 0x6e2: /* dbBd */
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Exactly what point is a PC-relative offset relative TO?
|
|
|
|
With the C3x we have the following:
|
|
|
|
DBcond, Bcond disp + PC + 1 => PC
|
|
|
|
DBcondD, BcondD disp + PC + 3 => PC
|
|
|
|
*/
|
|
|
|
long
|
2008-08-13 07:39:31 +08:00
|
|
|
md_pcrel_from (fixS *fixP)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2005-02-23 20:28:06 +08:00
|
|
|
unsigned char *buf;
|
2002-08-28 18:38:51 +08:00
|
|
|
unsigned int op;
|
|
|
|
|
2005-02-23 20:28:06 +08:00
|
|
|
buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
|
2019-12-12 06:59:45 +08:00
|
|
|
op = ((unsigned) buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
|
2002-08-28 18:38:51 +08:00
|
|
|
|
|
|
|
return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) +
|
2003-04-04 16:15:15 +08:00
|
|
|
tic4x_pc_offset (op);
|
2002-08-28 18:38:51 +08:00
|
|
|
}
|
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
/* Fill the alignment area with NOP's on .text, unless fill-data
|
|
|
|
was specified. */
|
2015-08-12 19:40:42 +08:00
|
|
|
int
|
2012-02-27 14:52:20 +08:00
|
|
|
tic4x_do_align (int alignment,
|
|
|
|
const char *fill,
|
|
|
|
int len,
|
|
|
|
int max)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
2003-11-22 23:32:28 +08:00
|
|
|
/* Because we are talking lwords, not bytes, adjust alignment to do words */
|
2002-11-11 22:29:01 +08:00
|
|
|
alignment += 2;
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2002-11-11 22:29:01 +08:00
|
|
|
if (alignment != 0 && !need_pass_2)
|
|
|
|
{
|
|
|
|
if (fill == NULL)
|
|
|
|
{
|
2012-11-06 13:51:18 +08:00
|
|
|
if (subseg_text_p (now_seg))
|
2012-02-27 14:52:20 +08:00
|
|
|
{
|
|
|
|
char nop[4];
|
|
|
|
|
|
|
|
md_number_to_chars (nop, TIC_NOP_OPCODE, 4);
|
|
|
|
frag_align_pattern (alignment, nop, sizeof (nop), max);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
frag_align (alignment, 0, max);
|
2002-11-11 22:29:01 +08:00
|
|
|
}
|
|
|
|
else if (len <= 1)
|
|
|
|
frag_align (alignment, *fill, max);
|
|
|
|
else
|
|
|
|
frag_align_pattern (alignment, fill, len, max);
|
|
|
|
}
|
2015-08-12 19:40:42 +08:00
|
|
|
|
2003-11-22 23:32:28 +08:00
|
|
|
/* Return 1 to skip the default alignment function */
|
2002-08-28 18:38:51 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look for and remove parallel instruction operator ||. */
|
2015-08-12 19:40:42 +08:00
|
|
|
void
|
2008-08-13 07:39:31 +08:00
|
|
|
tic4x_start_line (void)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
char *s = input_line_pointer;
|
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
|
|
|
|
/* If parallel instruction prefix found at start of line, skip it. */
|
|
|
|
if (*input_line_pointer == '|' && input_line_pointer[1] == '|')
|
|
|
|
{
|
|
|
|
if (insn->in_use)
|
|
|
|
{
|
|
|
|
insn->parallel = 1;
|
2003-05-19 06:23:15 +08:00
|
|
|
input_line_pointer ++;
|
|
|
|
*input_line_pointer = ' ';
|
2002-08-28 18:38:51 +08:00
|
|
|
/* So line counters get bumped. */
|
|
|
|
input_line_pointer[-1] = '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-19 06:23:15 +08:00
|
|
|
/* Write out the previous insn here */
|
2002-08-28 18:38:51 +08:00
|
|
|
if (insn->in_use)
|
|
|
|
md_assemble (NULL);
|
|
|
|
input_line_pointer = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
arelent *
|
2008-08-13 07:39:31 +08:00
|
|
|
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixP)
|
2002-08-28 18:38:51 +08:00
|
|
|
{
|
|
|
|
arelent *reloc;
|
|
|
|
|
2016-04-01 21:26:30 +08:00
|
|
|
reloc = XNEW (arelent);
|
2002-08-28 18:38:51 +08:00
|
|
|
|
2016-04-01 21:26:30 +08:00
|
|
|
reloc->sym_ptr_ptr = XNEW (asymbol *);
|
2002-08-28 18:38:51 +08:00
|
|
|
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
|
|
|
|
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
|
|
|
|
reloc->address /= OCTETS_PER_BYTE;
|
|
|
|
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
|
|
|
|
if (reloc->howto == (reloc_howto_type *) NULL)
|
|
|
|
{
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
2009-07-24 19:45:01 +08:00
|
|
|
_("Reloc %d not supported by object file format"),
|
2002-08-28 18:38:51 +08:00
|
|
|
(int) fixP->fx_r_type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fixP->fx_r_type == BFD_RELOC_HI16)
|
|
|
|
reloc->addend = fixP->fx_offset;
|
|
|
|
else
|
|
|
|
reloc->addend = fixP->fx_addnumber;
|
|
|
|
|
|
|
|
return reloc;
|
|
|
|
}
|