/* tc-i370.c -- Assembler for the IBM 360/370/390 instruction set.
Loosely based on the ppc files by Linas Vepstas <linas@linas.org> 1998, 99
- Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GAS, the GNU Assembler.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ 02111-1307, USA. */
/* This assembler implements a very hacked version of an elf-like thing
* that gcc emits (when gcc is suitably hacked). To make it behave more
*/
#include <stdio.h>
-#include <ctype.h>
#include "as.h"
+#include "safe-ctype.h"
#include "subsegs.h"
#include "struc-symbol.h"
as in 0d1.0. */
const char FLT_CHARS[] = "dD";
-
void
md_show_usage (stream)
FILE *stream;
{
- fprintf(stream, "\
+ fprintf (stream, "\
S/370 options: (these have not yet been tested and may not work) \n\
-u ignored\n\
-mregnames Allow symbolic names for registers\n\
-mno-regnames Do not allow symbolic names for registers\n");
#ifdef OBJ_ELF
- fprintf(stream, "\
+ fprintf (stream, "\
-mrelocatable support for GCC's -mrelocatble option\n\
-mrelocatable-lib support for GCC's -mrelocatble-lib option\n\
-V print assembler version number\n");
static void i370_elf_validate_fix PARAMS ((fixS *, segT));
#endif
-
\f
/* The target specific pseudo-ops which we support. */
1. r<reg_num> which has the value <reg_num>.
2. r.<reg_num> which has the value <reg_num>.
-
Each floating point register has predefined names of the form:
1. f<reg_num> which has the value <reg_num>.
2. f.<reg_num> which has the value <reg_num>.
There are only four floating point registers, and these are
commonly labelled 0,2,4 and 6. Thus, there is no f1, f3, etc.
-
There are individual registers as well:
rbase or r.base has the value 3 (base register)
rpgt or r.pgt has the value 4 (page origin table pointer)
dsa or r.dsa has the value 13 (stack pointer)
lr has the value 14 (link reg)
- The table is sorted. Suitable for searching by a binary search. */
+ The table is sorted. Suitable for searching by a binary search. */
static const struct pd_reg pre_defined_registers[] =
{
{ "f4", 4 },
{ "f6", 6 },
-
{ "dsa",13 }, /* stack pointer */
{ "lr", 14 }, /* Link Register */
{ "pgt", 4 }, /* Page Origin Table Pointer */
};
-#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
+#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
/* Given NAME, find the register number associated with that name, return
the integer value associated with the given name or -1 on failure. */
*
* in: Input_line_pointer points to 1st char of operand.
*
- * out: A expressionS.
+ * out: An expressionS.
* The operand may have been a register: in this case, X_op == O_register,
* X_add_number is set to the register number, and truth is returned.
* Input_line_pointer->(next non-blank) char after operand, or is in its
char *start;
char c;
- /* Find the spelling of the operand */
+ /* Find the spelling of the operand. */
start = name = input_line_pointer;
- if (name[0] == '%' && isalpha (name[1]))
+ if (name[0] == '%' && ISALPHA (name[1]))
name = ++input_line_pointer;
else if (!reg_names_p)
while (' ' == *name)
name = ++input_line_pointer;
- /* if its a number, treat it as a number */
- /* if its alpha, look to see if it's in the register table */
- if (!isalpha (name[0]))
+ /* If it's a number, treat it as a number. If it's alpha, look to
+ see if it's in the register table. */
+ if (!ISALPHA (name[0]))
{
- reg_number = get_single_number();
- c = get_symbol_end ();
+ reg_number = get_single_number ();
}
else
{
c = get_symbol_end ();
reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
+
+ /* Put back the delimiting char. */
+ *input_line_pointer = c;
}
- /* if numeric, make sure its not out of bounds */
+ /* If numeric, make sure its not out of bounds. */
if ((0 <= reg_number) && (16 >= reg_number))
{
expressionP->X_op = O_register;
expressionP->X_add_number = reg_number;
- /* make the rest nice */
+ /* Make the rest nice. */
expressionP->X_add_symbol = NULL;
expressionP->X_op_symbol = NULL;
- *input_line_pointer = c; /* put back the delimiting char */
return true;
}
- /* reset the line as if we had not done anything */
- *input_line_pointer = c; /* put back the delimiting char */
- input_line_pointer = start; /* reset input_line pointer */
- return false;
+ /* Reset the line as if we had not done anything. */
+ input_line_pointer = start;
+ return false;
}
\f
/* Local variables. */
{
{NULL, no_argument, NULL, 0}
};
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (c, arg)
\f
/* Set i370_cpu if it is not already set.
Currently defaults to the reasonable superset;
- but can be made more fine grained if desred. */
+ but can be made more fine grained if desred. */
static void
i370_set_cpu ()
const char *default_os = TARGET_OS;
const char *default_cpu = TARGET_CPU;
- /* override with the superset for the moment. */
+ /* override with the superset for the moment. */
i370_cpu = I370_OPCODE_ESA390_SUPERSET;
if (i370_cpu == 0)
{
}
/* Figure out the BFD architecture to use. */
-// hack alert -- specify the different 370 architectures
+/* hack alert -- specify the different 370 architectures */
enum bfd_architecture
i370_arch ()
i370_set_cpu ();
#ifdef OBJ_ELF
- /* Set the ELF flags if desired. */
+ /* Set the ELF flags if desired. */
if (i370_flags)
bfd_set_private_flags (stdoutput, i370_flags);
#endif
\f
#ifdef OBJ_ELF
/* Parse @got, etc. and return the desired relocation.
- * Currently, i370 does not support (don't really need to support) any
- * of these fancier markups ... for example, no one is going to
- * write 'L 6,=V(bogus)@got' it just doesn't make sense (at least to me).
- * So basically, we could get away with this routine returning
- * BFD_RELOC_UNUSED in all circumstances. However, I'll leave
- * in for now in case someone ambitious finds a good use for this stuff ...
- * this routine was pretty much just copied from the powerpc code ...
- */
+ Currently, i370 does not support (don't really need to support) any
+ of these fancier markups ... for example, no one is going to
+ write 'L 6,=V(bogus)@got' it just doesn't make sense (at least to me).
+ So basically, we could get away with this routine returning
+ BFD_RELOC_UNUSED in all circumstances. However, I'll leave
+ in for now in case someone ambitious finds a good use for this stuff ...
+ this routine was pretty much just copied from the powerpc code ... */
static bfd_reloc_code_real_type
i370_elf_suffix (str_p, exp_p)
char **str_p;
int len;
struct map_bfd *ptr;
-#define MAP(str,reloc) { str, sizeof(str)-1, reloc }
+#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
static struct map_bfd mapping[] =
{
- // MAP ("l", BFD_RELOC_LO16),
- // MAP ("h", BFD_RELOC_HI16),
- // MAP ("ha", BFD_RELOC_HI16_S),
- MAP ("fixup", BFD_RELOC_CTOR), /* warnings with -mrelocatable */
- { (char *)0, 0, BFD_RELOC_UNUSED }
+#if 0
+ MAP ("l", BFD_RELOC_LO16),
+ MAP ("h", BFD_RELOC_HI16),
+ MAP ("ha", BFD_RELOC_HI16_S),
+#endif
+ /* warnings with -mrelocatable. */
+ MAP ("fixup", BFD_RELOC_CTOR),
+ { (char *)0, 0, BFD_RELOC_UNUSED }
};
if (*str++ != '@')
for (ch = *str, str2 = ident;
(str2 < ident + sizeof (ident) - 1
- && (isalnum (ch) || ch == '@'));
+ && (ISALNUM (ch) || ch == '@'));
ch = *++str)
{
- *str2++ = (islower (ch)) ? ch : tolower (ch);
+ *str2++ = TOLOWER (ch);
}
*str2 = '\0';
return BFD_RELOC_UNUSED;
}
-/* Like normal .long/.short/.word, except support @got, etc. */
-/* clobbers input_line_pointer, checks end-of-line. */
+/* Like normal .long/.short/.word, except support @got, etc. */
+/* clobbers input_line_pointer, checks end-of-line. */
static void
i370_elf_cons (nbytes)
register int nbytes; /* 1=.byte, 2=.word, 4=.long */
}
while (*input_line_pointer++ == ',');
- input_line_pointer--; /* Put terminator back into stream. */
+ input_line_pointer--; /* Put terminator back into stream. */
demand_empty_rest_of_line ();
}
p = frag_more (nbytes);
while (end > input_line_pointer)
{
- *p = ascebc [(unsigned char)(*input_line_pointer)];
+ *p = ascebc [(unsigned char) (*input_line_pointer)];
++p; ++input_line_pointer;
}
*p = '\0';
/* Pseudo op to make file scope bss items */
static void
-i370_elf_lcomm(unused)
+i370_elf_lcomm (unused)
int unused;
{
register char *name;
}
#endif /* OBJ_ELF */
-
\f
#define LITERAL_POOL_SUPPORT
#ifdef LITERAL_POOL_SUPPORT
-/* Provide support for literal pools within the text section. */
+/* Provide support for literal pools within the text section. */
/* Loosely based on similar code from tc-arm.c */
/*
* We will use four symbols to locate four parts of the literal pool.
/* start a new pool, if necessary */
if (8 == sz && NULL == longlong_poolP)
- longlong_poolP = symbol_make_empty();
+ longlong_poolP = symbol_make_empty ();
else if (4 == sz && NULL == word_poolP)
- word_poolP = symbol_make_empty();
+ word_poolP = symbol_make_empty ();
else if (2 == sz && NULL == short_poolP)
- short_poolP = symbol_make_empty();
+ short_poolP = symbol_make_empty ();
else if (1 == sz && NULL == byte_poolP)
- byte_poolP = symbol_make_empty();
+ byte_poolP = symbol_make_empty ();
/* Check if this literal value is already in the pool: */
/* hack alert -- we should probably be checking expressions
{
if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
{
- as_bad("Literal Pool Overflow");
+ as_bad ("Literal Pool Overflow");
}
literals[next_literal_pool_place].exp = *exx;
S_SET_SEGMENT (symbolP, segment);
S_SET_VALUE (symbolP, valu);
- symbol_clear_list_pointers(symbolP);
+ symbol_clear_list_pointers (symbolP);
symbol_set_frag (symbolP, frag);
lab = input_line_pointer;
while (*lab && (',' != *lab) && ('(' != *lab))
{
- if (isdigit(*lab))
+ if (ISDIGIT (*lab))
{
all_digits = 1;
}
- else if (isalpha(*lab))
+ else if (ISALPHA (*lab))
{
if (!all_digits)
{
expression (exx);
/* OK, now we have to subtract the "using" location */
- /* normally branches appear in the text section only... */
+ /* normally branches appear in the text section only... */
if (0 == strncmp (now_seg->name, ".text", 5) || 0 > i370_using_other_regno)
{
i370_make_relative (exx, &i370_using_text_baseaddr);
name = input_line_pointer;
sym_name = input_line_pointer;
/* Find the spelling of the operand */
- if (name[0] == '=' && isalpha (name[1]))
+ if (name[0] == '=' && ISALPHA (name[1]))
{
name = ++input_line_pointer;
}
save = input_line_pointer;
while (*save)
{
- if (isxdigit(*save))
+ if (ISXDIGIT (*save))
hex_len++;
save++;
}
else as_bad ("bad alignment of %d bytes in literal pool", biggest_literal_size);
if (0 == biggest_align) biggest_align = 1;
-
/* Align pool for short, word, double word accesses */
frag_align (biggest_align, 0, 0);
record_alignment (now_seg, biggest_align);
/* Note that the gas listing will print only the first five
* entries in the pool .... wonder how to make it print more ...
*/
- /* output largest literals first, then the smaller ones. */
+ /* output largest literals first, then the smaller ones. */
for (litsize=8; litsize; litsize /=2)
{
symbolS *current_poolP = NULL;
*/
if (literals[lit_count].sym_name)
{
- symbolS * symP = symbol_make_empty();
+ symbolS * symP = symbol_make_empty ();
symbol_locate (symP, literals[lit_count].sym_name, now_seg,
(valueT) frag_now_fix (), frag_now);
symbol_table_insert (symP);
char *star;
/* if "*" appears in a using, it means "." */
- /* replace it with "." so that expr doesn't get confused. */
+ /* replace it with "." so that expr doesn't get confused. */
star = strchr (input_line_pointer, '*');
if (star)
*star = '.';
/* the first arg to using will usually be ".", but it can
- * be a more complex exprsssion too ... */
+ * be a more complex exprsssion too ... */
expression (&baseaddr);
if (star)
*star = '*';
#endif
/* Get the opcode. */
- for (s = str; *s != '\0' && ! isspace (*s); s++)
+ for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
;
if (*s != '\0')
*s++ = '\0';
insn = opcode->opcode;
str = s;
- while (isspace (*str))
+ while (ISSPACE (*str))
++str;
/* I370 operands are either expressions or address constants.
hold = input_line_pointer;
input_line_pointer = str;
- /* register names are only allowed where there are registers ... */
+ /* register names are only allowed where there are registers ... */
if ((operand->flags & I370_OPERAND_GPR) != 0)
{
/* quickie hack to get past things like (,r13) */
}
}
- /* check for a address constant expression */
+ /* Check for an address constant expression. */
/* We will put PSW-relative addresses in the text section,
- * and adress literals in the .data (or other) section. */
+ * and adress literals in the .data (or other) section. */
else if (i370_addr_cons (&ex))
use_other=1;
else if (i370_addr_offset (&ex))
/* Allow @HA, @L, @H on constants.
* Well actually, no we don't; there really don't make sense
* (at least not to me) for the i370. However, this code is
- * left here for any dubious future expansion reasons ... */
+ * left here for any dubious future expansion reasons ... */
char *orig_str = str;
if ((reloc = i370_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
++str;
}
- while (isspace (*str))
+ while (ISSPACE (*str))
++str;
if (*str != '\0')
size = bfd_get_reloc_size (reloc_howto);
if (size < 1 || size > 4)
- abort();
+ abort ();
printf (" gwana doo fixup %d \n", i);
fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
if (letter == 'e')
return SHF_EXCLUDE;
- *ptr_msg = "Bad .section directive: want a,w,x,e in string";
+ *ptr_msg = "Bad .section directive: want a,e,w,x,M,S in string";
return 0;
}
}
/* 360/370/390 have two float formats: an old, funky 360 single-precision
- * format, and the ieee format. Support only the ieee format. */
+ * format, and the ieee format. Support only the ieee format. */
t = atof_ieee (input_line_pointer, type, words);
if (t)
input_line_pointer = t;
/* We have no need to default values of symbols. */
-/*ARGSUSED*/
symbolS *
md_undefined_symbol (name)
char *name;
return fixp->fx_frag->fr_address + fixp->fx_where;
}
-
/* Apply a fixup to the object code. This is called for all the
fixups we generated by the call to fix_new_exp, above. In the call
above we used a reloc code which was the largest legal reloc code
#endif
/* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again.
- fisxp->fx_size is the length of the instruction. */
+ fisxp->fx_size is the length of the instruction. */
where = fixp->fx_frag->fr_literal + fixp->fx_where;
insn.i[0] = bfd_getb32 ((unsigned char *) where);
if (6 <= fixp->fx_size)
relocs. In fact, we support *zero* operand relocations ...
Why? Because we are not expecting the compiler to generate
any operands that need relocation. Due to the 12-bit naturew of
- i370 addressing, this would be unusual. */
+ i370 addressing, this would be unusual. */
#if 0
if ((operand->flags & I370_OPERAND_RELATIVE) != 0
&& operand->bits == 12
break;
default:
- fprintf(stderr,
+ fprintf (stderr,
"Gas failure, reloc value %d\n", fixp->fx_r_type);
- fflush(stderr);
+ fflush (stderr);
abort ();
}
}