133965Sjdp/* read.c - read a source file - 278828Sobrien Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 3218822Sdim 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 4218822Sdim Free Software Foundation, Inc. 533965Sjdp 633965SjdpThis file is part of GAS, the GNU Assembler. 733965Sjdp 833965SjdpGAS is free software; you can redistribute it and/or modify 933965Sjdpit under the terms of the GNU General Public License as published by 1033965Sjdpthe Free Software Foundation; either version 2, or (at your option) 1133965Sjdpany later version. 1233965Sjdp 1333965SjdpGAS is distributed in the hope that it will be useful, 1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965SjdpGNU General Public License for more details. 1733965Sjdp 1833965SjdpYou should have received a copy of the GNU General Public License 1933965Sjdpalong with GAS; see the file COPYING. If not, write to the Free 20218822SdimSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim02110-1301, USA. */ 2233965Sjdp 23218822Sdim/* If your chars aren't 8 bits, you will change this a bit (eg. to 0xFF). 2477298Sobrien But then, GNU isn't spozed to run on your machine anyway. 2577298Sobrien (RMS is so shortsighted sometimes.) */ 2677298Sobrien#define MASK_CHAR ((int)(unsigned char) -1) 2733965Sjdp 2833965Sjdp/* This is the largest known floating point format (for now). It will 2977298Sobrien grow when we do 4361 style flonums. */ 3033965Sjdp#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) 3133965Sjdp 32130561Sobrien/* Routines that read assembler source text to build spaghetti in memory. 3333965Sjdp Another group of these functions is in the expr.c module. */ 3433965Sjdp 3533965Sjdp#include "as.h" 3689857Sobrien#include "safe-ctype.h" 3733965Sjdp#include "subsegs.h" 3833965Sjdp#include "sb.h" 3933965Sjdp#include "macro.h" 4033965Sjdp#include "obstack.h" 4133965Sjdp#include "ecoff.h" 42130561Sobrien#include "dw2gencfi.h" 4333965Sjdp 4433965Sjdp#ifndef TC_START_LABEL 45104834Sobrien#define TC_START_LABEL(x,y) (x == ':') 4633965Sjdp#endif 4733965Sjdp 4860484Sobrien/* Set by the object-format or the target. */ 4960484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT 50130561Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ 5177298Sobrien do \ 52130561Sobrien { \ 53130561Sobrien if ((SIZE) >= 8) \ 54130561Sobrien (P2VAR) = 3; \ 55130561Sobrien else if ((SIZE) >= 4) \ 56130561Sobrien (P2VAR) = 2; \ 57130561Sobrien else if ((SIZE) >= 2) \ 58130561Sobrien (P2VAR) = 1; \ 59130561Sobrien else \ 60130561Sobrien (P2VAR) = 0; \ 6177298Sobrien } \ 6277298Sobrien while (0) 6360484Sobrien#endif 6460484Sobrien 6577298Sobrienchar *input_line_pointer; /*->next char of source file to parse. */ 6633965Sjdp 6733965Sjdp#if BITS_PER_CHAR != 8 6833965Sjdp/* The following table is indexed by[(char)] and will break if 6933965Sjdp a char does not have exactly 256 states (hopefully 0:255!)! */ 7033965Sjdpdie horribly; 7133965Sjdp#endif 7233965Sjdp 7333965Sjdp#ifndef LEX_AT 7433965Sjdp#define LEX_AT 0 7533965Sjdp#endif 7633965Sjdp 7733965Sjdp#ifndef LEX_BR 7833965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */ 7933965Sjdp#define LEX_BR 0 8033965Sjdp#endif 8133965Sjdp 8233965Sjdp#ifndef LEX_PCT 8333965Sjdp/* The Delta 68k assembler permits % inside label names. */ 8433965Sjdp#define LEX_PCT 0 8533965Sjdp#endif 8633965Sjdp 8733965Sjdp#ifndef LEX_QM 8833965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names. */ 8933965Sjdp#define LEX_QM 0 9033965Sjdp#endif 9133965Sjdp 9260484Sobrien#ifndef LEX_HASH 9377298Sobrien/* The IA-64 assembler uses # as a suffix designating a symbol. We include 9477298Sobrien it in the symbol and strip it out in tc_canonicalize_symbol_name. */ 9560484Sobrien#define LEX_HASH 0 9660484Sobrien#endif 9760484Sobrien 9833965Sjdp#ifndef LEX_DOLLAR 9933965Sjdp#define LEX_DOLLAR 3 10033965Sjdp#endif 10133965Sjdp 10233965Sjdp#ifndef LEX_TILDE 10333965Sjdp/* The Delta 68k assembler permits ~ at start of label names. */ 10433965Sjdp#define LEX_TILDE 0 10533965Sjdp#endif 10633965Sjdp 10777298Sobrien/* Used by is_... macros. our ctype[]. */ 10877298Sobrienchar lex_type[256] = { 10933965Sjdp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ 11033965Sjdp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ 11160484Sobrien 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ 11233965Sjdp 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */ 11333965Sjdp LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ 11433965Sjdp 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */ 11533965Sjdp 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ 11677298Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */ 11760484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 11860484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 11960484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12060484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12160484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12260484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12360484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12460484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 12533965Sjdp}; 12633965Sjdp 12777298Sobrien/* In: a character. 12877298Sobrien Out: 1 if this character ends a line. */ 12977298Sobrienchar is_end_of_line[256] = { 13033965Sjdp#ifdef CR_EOL 13177298Sobrien 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, /* @abcdefghijklmno */ 13233965Sjdp#else 13377298Sobrien 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* @abcdefghijklmno */ 13433965Sjdp#endif 13577298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 13677298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* _!"#$%&'()*+,-./ */ 13777298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ 13877298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 13977298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14077298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14177298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14277298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14377298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14477298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14577298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14677298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14777298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14877298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14977298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* */ 15033965Sjdp}; 15133965Sjdp 152130561Sobrien#ifndef TC_CASE_SENSITIVE 15377298Sobrienchar original_case_string[128]; 15477298Sobrien#endif 15533965Sjdp 15677298Sobrien/* Functions private to this file. */ 15733965Sjdp 15877298Sobrienstatic char *buffer; /* 1st char of each buffer of lines is here. */ 15977298Sobrienstatic char *buffer_limit; /*->1 + last char in buffer. */ 16077298Sobrien 16177298Sobrien/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 16277298Sobrien in the tc-<CPU>.h file. See the "Porting GAS" section of the 16377298Sobrien internals manual. */ 16433965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN; 16533965Sjdp 16677298Sobrien/* Variables for handling include file directory table. */ 16733965Sjdp 16877298Sobrien/* Table of pointers to directories to search for .include's. */ 16977298Sobrienchar **include_dirs; 17033965Sjdp 17177298Sobrien/* How many are in the table. */ 17277298Sobrienint include_dir_count; 17377298Sobrien 17477298Sobrien/* Length of longest in table. */ 17577298Sobrienint include_dir_maxlen = 1; 17677298Sobrien 17733965Sjdp#ifndef WORKING_DOT_WORD 17833965Sjdpstruct broken_word *broken_words; 17933965Sjdpint new_broken_words; 18033965Sjdp#endif 18133965Sjdp 18233965Sjdp/* The current offset into the absolute section. We don't try to 18333965Sjdp build frags in the absolute section, since no data can be stored 18433965Sjdp there. We just keep track of the current offset. */ 18533965SjdpaddressT abs_section_offset; 18633965Sjdp 18733965Sjdp/* If this line had an MRI style label, it is stored in this variable. 18833965Sjdp This is used by some of the MRI pseudo-ops. */ 18933965SjdpsymbolS *line_label; 19033965Sjdp 19133965Sjdp/* This global variable is used to support MRI common sections. We 19233965Sjdp translate such sections into a common symbol. This variable is 19333965Sjdp non-NULL when we are in an MRI common section. */ 19433965SjdpsymbolS *mri_common_symbol; 19533965Sjdp 19633965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we 19733965Sjdp need to align to an even byte boundary unless the next pseudo-op is 19833965Sjdp dc.b, ds.b, or dcb.b. This variable is set to 1 if an alignment 19933965Sjdp may be needed. */ 20033965Sjdpstatic int mri_pending_align; 20133965Sjdp 20238889Sjdp#ifndef NO_LISTING 20338889Sjdp#ifdef OBJ_ELF 20438889Sjdp/* This variable is set to be non-zero if the next string we see might 20538889Sjdp be the name of the source file in DWARF debugging information. See 20638889Sjdp the comment in emit_expr for the format we look for. */ 20738889Sjdpstatic int dwarf_file_string; 20838889Sjdp#endif 20938889Sjdp#endif 21038889Sjdp 211218822Sdimstatic void do_s_func (int end_p, const char *default_prefix); 212130561Sobrienstatic void do_align (int, char *, int, int); 213130561Sobrienstatic void s_align (int, int); 214218822Sdimstatic void s_altmacro (int); 215218822Sdimstatic void s_bad_end (int); 216218822Sdim#ifdef OBJ_ELF 217218822Sdimstatic void s_gnu_attribute (int); 218218822Sdim#endif 219218822Sdimstatic void s_reloc (int); 220130561Sobrienstatic int hex_float (int, char *); 221130561Sobrienstatic segT get_known_segmented_expression (expressionS * expP); 222130561Sobrienstatic void pobegin (void); 223130561Sobrienstatic int get_line_sb (sb *); 224130561Sobrienstatic void generate_file_debug (void); 225218822Sdimstatic char *_find_end_of_line (char *, int, int); 22633965Sjdp 22733965Sjdpvoid 228130561Sobrienread_begin (void) 22933965Sjdp{ 23033965Sjdp const char *p; 23133965Sjdp 23233965Sjdp pobegin (); 23333965Sjdp obj_read_begin_hook (); 23433965Sjdp 23533965Sjdp /* Something close -- but not too close -- to a multiple of 1024. 23633965Sjdp The debugging malloc I'm using has 24 bytes of overhead. */ 23733965Sjdp obstack_begin (¬es, chunksize); 23833965Sjdp obstack_begin (&cond_obstack, chunksize); 23933965Sjdp 24077298Sobrien /* Use machine dependent syntax. */ 24133965Sjdp for (p = line_separator_chars; *p; p++) 24233965Sjdp is_end_of_line[(unsigned char) *p] = 1; 24377298Sobrien /* Use more. FIXME-SOMEDAY. */ 24433965Sjdp 24533965Sjdp if (flag_mri) 24633965Sjdp lex_type['?'] = 3; 24733965Sjdp} 24833965Sjdp 249218822Sdim#ifndef TC_ADDRESS_BYTES 250218822Sdim#define TC_ADDRESS_BYTES address_bytes 251218822Sdim 252218822Sdimstatic inline int 253218822Sdimaddress_bytes (void) 254218822Sdim{ 255218822Sdim /* Choose smallest of 1, 2, 4, 8 bytes that is large enough to 256218822Sdim contain an address. */ 257218822Sdim int n = (stdoutput->arch_info->bits_per_address - 1) / 8; 258218822Sdim n |= n >> 1; 259218822Sdim n |= n >> 2; 260218822Sdim n += 1; 261218822Sdim return n; 262218822Sdim} 263218822Sdim#endif 264218822Sdim 26577298Sobrien/* Set up pseudo-op tables. */ 26633965Sjdp 26733965Sjdpstatic struct hash_control *po_hash; 26833965Sjdp 26977298Sobrienstatic const pseudo_typeS potable[] = { 27033965Sjdp {"abort", s_abort, 0}, 27133965Sjdp {"align", s_align_ptwo, 0}, 272218822Sdim {"altmacro", s_altmacro, 1}, 27333965Sjdp {"ascii", stringer, 0}, 27433965Sjdp {"asciz", stringer, 1}, 27533965Sjdp {"balign", s_align_bytes, 0}, 27633965Sjdp {"balignw", s_align_bytes, -2}, 27733965Sjdp {"balignl", s_align_bytes, -4}, 27877298Sobrien/* block */ 27933965Sjdp {"byte", cons, 1}, 28033965Sjdp {"comm", s_comm, 0}, 28133965Sjdp {"common", s_mri_common, 0}, 28233965Sjdp {"common.s", s_mri_common, 1}, 28333965Sjdp {"data", s_data, 0}, 28433965Sjdp {"dc", cons, 2}, 285218822Sdim#ifdef TC_ADDRESS_BYTES 286218822Sdim {"dc.a", cons, 0}, 287218822Sdim#endif 28833965Sjdp {"dc.b", cons, 1}, 28933965Sjdp {"dc.d", float_cons, 'd'}, 29033965Sjdp {"dc.l", cons, 4}, 29133965Sjdp {"dc.s", float_cons, 'f'}, 29233965Sjdp {"dc.w", cons, 2}, 29333965Sjdp {"dc.x", float_cons, 'x'}, 29433965Sjdp {"dcb", s_space, 2}, 29533965Sjdp {"dcb.b", s_space, 1}, 29633965Sjdp {"dcb.d", s_float_space, 'd'}, 29733965Sjdp {"dcb.l", s_space, 4}, 29833965Sjdp {"dcb.s", s_float_space, 'f'}, 29933965Sjdp {"dcb.w", s_space, 2}, 30033965Sjdp {"dcb.x", s_float_space, 'x'}, 30133965Sjdp {"ds", s_space, 2}, 30233965Sjdp {"ds.b", s_space, 1}, 30333965Sjdp {"ds.d", s_space, 8}, 30433965Sjdp {"ds.l", s_space, 4}, 30533965Sjdp {"ds.p", s_space, 12}, 30633965Sjdp {"ds.s", s_space, 4}, 30733965Sjdp {"ds.w", s_space, 2}, 30833965Sjdp {"ds.x", s_space, 12}, 30933965Sjdp {"debug", s_ignore, 0}, 31033965Sjdp#ifdef S_SET_DESC 31133965Sjdp {"desc", s_desc, 0}, 31233965Sjdp#endif 31377298Sobrien/* dim */ 31433965Sjdp {"double", float_cons, 'd'}, 31577298Sobrien/* dsect */ 31677298Sobrien {"eject", listing_eject, 0}, /* Formfeed listing. */ 31733965Sjdp {"else", s_else, 0}, 31833965Sjdp {"elsec", s_else, 0}, 31960484Sobrien {"elseif", s_elseif, (int) O_ne}, 32033965Sjdp {"end", s_end, 0}, 32133965Sjdp {"endc", s_endif, 0}, 32260484Sobrien {"endfunc", s_func, 1}, 32333965Sjdp {"endif", s_endif, 0}, 324218822Sdim {"endm", s_bad_end, 0}, 325218822Sdim {"endr", s_bad_end, 1}, 32677298Sobrien/* endef */ 32733965Sjdp {"equ", s_set, 0}, 32833965Sjdp {"equiv", s_set, 1}, 329218822Sdim {"eqv", s_set, -1}, 33033965Sjdp {"err", s_err, 0}, 331218822Sdim {"error", s_errwarn, 1}, 33233965Sjdp {"exitm", s_mexit, 0}, 33377298Sobrien/* extend */ 33477298Sobrien {"extern", s_ignore, 0}, /* We treat all undef as ext. */ 33533965Sjdp {"appfile", s_app_file, 1}, 336218822Sdim {"appline", s_app_line, 1}, 33733965Sjdp {"fail", s_fail, 0}, 33833965Sjdp {"file", s_app_file, 0}, 33933965Sjdp {"fill", s_fill, 0}, 34033965Sjdp {"float", float_cons, 'f'}, 34133965Sjdp {"format", s_ignore, 0}, 34260484Sobrien {"func", s_func, 0}, 34333965Sjdp {"global", s_globl, 0}, 34433965Sjdp {"globl", s_globl, 0}, 345218822Sdim#ifdef OBJ_ELF 346218822Sdim {"gnu_attribute", s_gnu_attribute, 0}, 347218822Sdim#endif 34833965Sjdp {"hword", cons, 2}, 34933965Sjdp {"if", s_if, (int) O_ne}, 350218822Sdim {"ifb", s_ifb, 1}, 35133965Sjdp {"ifc", s_ifc, 0}, 35233965Sjdp {"ifdef", s_ifdef, 0}, 35333965Sjdp {"ifeq", s_if, (int) O_eq}, 35433965Sjdp {"ifeqs", s_ifeqs, 0}, 35533965Sjdp {"ifge", s_if, (int) O_ge}, 35633965Sjdp {"ifgt", s_if, (int) O_gt}, 35733965Sjdp {"ifle", s_if, (int) O_le}, 35833965Sjdp {"iflt", s_if, (int) O_lt}, 359218822Sdim {"ifnb", s_ifb, 0}, 36033965Sjdp {"ifnc", s_ifc, 1}, 36133965Sjdp {"ifndef", s_ifdef, 1}, 36233965Sjdp {"ifne", s_if, (int) O_ne}, 36333965Sjdp {"ifnes", s_ifeqs, 1}, 36433965Sjdp {"ifnotdef", s_ifdef, 1}, 36589857Sobrien {"incbin", s_incbin, 0}, 36633965Sjdp {"include", s_include, 0}, 36733965Sjdp {"int", cons, 4}, 36833965Sjdp {"irp", s_irp, 0}, 36933965Sjdp {"irep", s_irp, 0}, 37033965Sjdp {"irpc", s_irp, 1}, 37133965Sjdp {"irepc", s_irp, 1}, 37233965Sjdp {"lcomm", s_lcomm, 0}, 37377298Sobrien {"lflags", listing_flags, 0}, /* Listing flags. */ 374218822Sdim {"linefile", s_app_line, 0}, 37533965Sjdp {"linkonce", s_linkonce, 0}, 37677298Sobrien {"list", listing_list, 1}, /* Turn listing on. */ 37733965Sjdp {"llen", listing_psize, 1}, 37833965Sjdp {"long", cons, 4}, 37933965Sjdp {"lsym", s_lsym, 0}, 38033965Sjdp {"macro", s_macro, 0}, 38133965Sjdp {"mexit", s_mexit, 0}, 38233965Sjdp {"mri", s_mri, 0}, 38333965Sjdp {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */ 38433965Sjdp {"name", s_ignore, 0}, 385218822Sdim {"noaltmacro", s_altmacro, 0}, 38633965Sjdp {"noformat", s_ignore, 0}, 38777298Sobrien {"nolist", listing_list, 0}, /* Turn listing off. */ 38833965Sjdp {"nopage", listing_nopage, 0}, 38933965Sjdp {"octa", cons, 16}, 39033965Sjdp {"offset", s_struct, 0}, 39133965Sjdp {"org", s_org, 0}, 39233965Sjdp {"p2align", s_align_ptwo, 0}, 39333965Sjdp {"p2alignw", s_align_ptwo, -2}, 39433965Sjdp {"p2alignl", s_align_ptwo, -4}, 39533965Sjdp {"page", listing_eject, 0}, 39633965Sjdp {"plen", listing_psize, 0}, 39733965Sjdp {"print", s_print, 0}, 39877298Sobrien {"psize", listing_psize, 0}, /* Set paper size. */ 39933965Sjdp {"purgem", s_purgem, 0}, 40033965Sjdp {"quad", cons, 8}, 401218822Sdim {"reloc", s_reloc, 0}, 40233965Sjdp {"rep", s_rept, 0}, 40333965Sjdp {"rept", s_rept, 0}, 40433965Sjdp {"rva", s_rva, 4}, 40577298Sobrien {"sbttl", listing_title, 1}, /* Subtitle of listing. */ 40677298Sobrien/* scl */ 40777298Sobrien/* sect */ 40833965Sjdp {"set", s_set, 0}, 40933965Sjdp {"short", cons, 2}, 41033965Sjdp {"single", float_cons, 'f'}, 41177298Sobrien/* size */ 41233965Sjdp {"space", s_space, 0}, 41333965Sjdp {"skip", s_space, 0}, 41438889Sjdp {"sleb128", s_leb128, 1}, 41533965Sjdp {"spc", s_ignore, 0}, 41633965Sjdp {"stabd", s_stab, 'd'}, 41733965Sjdp {"stabn", s_stab, 'n'}, 41833965Sjdp {"stabs", s_stab, 's'}, 41933965Sjdp {"string", stringer, 1}, 42033965Sjdp {"struct", s_struct, 0}, 42177298Sobrien/* tag */ 42233965Sjdp {"text", s_text, 0}, 42333965Sjdp 42433965Sjdp /* This is for gcc to use. It's only just been added (2/94), so gcc 42533965Sjdp won't be able to use it for a while -- probably a year or more. 42633965Sjdp But once this has been released, check with gcc maintainers 42733965Sjdp before deleting it or even changing the spelling. */ 42833965Sjdp {"this_GCC_requires_the_GNU_assembler", s_ignore, 0}, 42933965Sjdp /* If we're folding case -- done for some targets, not necessarily 43033965Sjdp all -- the above string in an input file will be converted to 43133965Sjdp this one. Match it either way... */ 43233965Sjdp {"this_gcc_requires_the_gnu_assembler", s_ignore, 0}, 43333965Sjdp 43477298Sobrien {"title", listing_title, 0}, /* Listing title. */ 43533965Sjdp {"ttl", listing_title, 0}, 43677298Sobrien/* type */ 43738889Sjdp {"uleb128", s_leb128, 0}, 43877298Sobrien/* use */ 43977298Sobrien/* val */ 44033965Sjdp {"xcom", s_comm, 0}, 44133965Sjdp {"xdef", s_globl, 0}, 44233965Sjdp {"xref", s_ignore, 0}, 44333965Sjdp {"xstabs", s_xstab, 's'}, 444218822Sdim {"warning", s_errwarn, 0}, 445218822Sdim {"weakref", s_weakref, 0}, 44633965Sjdp {"word", cons, 2}, 44733965Sjdp {"zero", s_space, 0}, 44877298Sobrien {NULL, NULL, 0} /* End sentinel. */ 44933965Sjdp}; 45033965Sjdp 451218822Sdimstatic offsetT 452218822Sdimget_absolute_expr (expressionS *exp) 453218822Sdim{ 454218822Sdim expression_and_evaluate (exp); 455218822Sdim if (exp->X_op != O_constant) 456218822Sdim { 457218822Sdim if (exp->X_op != O_absent) 458218822Sdim as_bad (_("bad or irreducible absolute expression")); 459218822Sdim exp->X_add_number = 0; 460218822Sdim } 461218822Sdim return exp->X_add_number; 462218822Sdim} 463218822Sdim 464218822SdimoffsetT 465218822Sdimget_absolute_expression (void) 466218822Sdim{ 467218822Sdim expressionS exp; 468218822Sdim 469218822Sdim return get_absolute_expr (&exp); 470218822Sdim} 471218822Sdim 47233965Sjdpstatic int pop_override_ok = 0; 47333965Sjdpstatic const char *pop_table_name; 47433965Sjdp 47533965Sjdpvoid 476130561Sobrienpop_insert (const pseudo_typeS *table) 47733965Sjdp{ 47833965Sjdp const char *errtxt; 47933965Sjdp const pseudo_typeS *pop; 48033965Sjdp for (pop = table; pop->poc_name; pop++) 48133965Sjdp { 48233965Sjdp errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); 48333965Sjdp if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists"))) 48460484Sobrien as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name, 48533965Sjdp errtxt); 48633965Sjdp } 48733965Sjdp} 48833965Sjdp 48933965Sjdp#ifndef md_pop_insert 49033965Sjdp#define md_pop_insert() pop_insert(md_pseudo_table) 49133965Sjdp#endif 49233965Sjdp 49333965Sjdp#ifndef obj_pop_insert 49433965Sjdp#define obj_pop_insert() pop_insert(obj_pseudo_table) 49533965Sjdp#endif 49633965Sjdp 497130561Sobrien#ifndef cfi_pop_insert 498130561Sobrien#define cfi_pop_insert() pop_insert(cfi_pseudo_table) 499130561Sobrien#endif 500130561Sobrien 50177298Sobrienstatic void 502130561Sobrienpobegin (void) 50333965Sjdp{ 50433965Sjdp po_hash = hash_new (); 50533965Sjdp 50677298Sobrien /* Do the target-specific pseudo ops. */ 50733965Sjdp pop_table_name = "md"; 50833965Sjdp md_pop_insert (); 50933965Sjdp 51077298Sobrien /* Now object specific. Skip any that were in the target table. */ 51133965Sjdp pop_table_name = "obj"; 51233965Sjdp pop_override_ok = 1; 51333965Sjdp obj_pop_insert (); 51433965Sjdp 51577298Sobrien /* Now portable ones. Skip any that we've seen already. */ 51633965Sjdp pop_table_name = "standard"; 51733965Sjdp pop_insert (potable); 518130561Sobrien 519130561Sobrien#ifdef TARGET_USE_CFIPOP 520130561Sobrien pop_table_name = "cfi"; 521130561Sobrien pop_override_ok = 1; 522130561Sobrien cfi_pop_insert (); 523130561Sobrien#endif 52433965Sjdp} 52533965Sjdp 52633965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY() \ 52733965Sjdp if (ignore_input ()) \ 52833965Sjdp { \ 529218822Sdim char *eol = find_end_of_line (input_line_pointer, flag_m68k_mri); \ 530218822Sdim input_line_pointer = (input_line_pointer <= buffer_limit \ 531218822Sdim && eol >= buffer_limit) \ 532218822Sdim ? buffer_limit \ 533218822Sdim : eol + 1; \ 53433965Sjdp continue; \ 53533965Sjdp } 53633965Sjdp 53733965Sjdp/* This function is used when scrubbing the characters between #APP 53833965Sjdp and #NO_APP. */ 53933965Sjdp 54033965Sjdpstatic char *scrub_string; 54133965Sjdpstatic char *scrub_string_end; 54233965Sjdp 54333965Sjdpstatic int 544130561Sobrienscrub_from_string (char *buf, int buflen) 54533965Sjdp{ 54660484Sobrien int copy; 54733965Sjdp 54860484Sobrien copy = scrub_string_end - scrub_string; 54960484Sobrien if (copy > buflen) 55060484Sobrien copy = buflen; 55160484Sobrien memcpy (buf, scrub_string, copy); 55260484Sobrien scrub_string += copy; 55360484Sobrien return copy; 55433965Sjdp} 55533965Sjdp 556218822Sdim/* Helper function of read_a_source_file, which tries to expand a macro. */ 557218822Sdimstatic int 558218822Sdimtry_macro (char term, const char *line) 559218822Sdim{ 560218822Sdim sb out; 561218822Sdim const char *err; 562218822Sdim macro_entry *macro; 563218822Sdim 564218822Sdim if (check_macro (line, &out, &err, ¯o)) 565218822Sdim { 566218822Sdim if (err != NULL) 567218822Sdim as_bad ("%s", err); 568218822Sdim *input_line_pointer++ = term; 569218822Sdim input_scrub_include_sb (&out, 570218822Sdim input_line_pointer, 1); 571218822Sdim sb_kill (&out); 572218822Sdim buffer_limit = 573218822Sdim input_scrub_next_buffer (&input_line_pointer); 574218822Sdim#ifdef md_macro_info 575218822Sdim md_macro_info (macro); 576218822Sdim#endif 577218822Sdim return 1; 578218822Sdim } 579218822Sdim return 0; 580218822Sdim} 581218822Sdim 58277298Sobrien/* We read the file, putting things into a web that represents what we 58377298Sobrien have been reading. */ 58477298Sobrienvoid 585130561Sobrienread_a_source_file (char *name) 58633965Sjdp{ 58733965Sjdp register char c; 58877298Sobrien register char *s; /* String of symbol, '\0' appended. */ 58933965Sjdp register int temp; 59033965Sjdp pseudo_typeS *pop; 59133965Sjdp 59277298Sobrien#ifdef WARN_COMMENTS 59377298Sobrien found_comment = 0; 59477298Sobrien#endif 59577298Sobrien 59633965Sjdp buffer = input_scrub_new_file (name); 59733965Sjdp 59833965Sjdp listing_file (name); 59938889Sjdp listing_newline (NULL); 60038889Sjdp register_dependency (name); 60133965Sjdp 60260484Sobrien /* Generate debugging information before we've read anything in to denote 60360484Sobrien this file as the "main" source file and not a subordinate one 60460484Sobrien (e.g. N_SO vs N_SOL in stabs). */ 60560484Sobrien generate_file_debug (); 60660484Sobrien 60733965Sjdp while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0) 60877298Sobrien { /* We have another line to parse. */ 609218822Sdim#ifndef NO_LISTING 610218822Sdim /* In order to avoid listing macro expansion lines with labels 611218822Sdim multiple times, keep track of which line was last issued. */ 612218822Sdim static char *last_eol; 613130561Sobrien 614218822Sdim last_eol = NULL; 615218822Sdim#endif 61633965Sjdp while (input_line_pointer < buffer_limit) 61733965Sjdp { 61877298Sobrien /* We have more of this buffer to parse. */ 61933965Sjdp 62077298Sobrien /* We now have input_line_pointer->1st char of next line. 62177298Sobrien If input_line_pointer [-1] == '\n' then we just 62277298Sobrien scanned another line: so bump line counters. */ 62333965Sjdp if (is_end_of_line[(unsigned char) input_line_pointer[-1]]) 62433965Sjdp { 62533965Sjdp#ifdef md_start_line_hook 62633965Sjdp md_start_line_hook (); 62733965Sjdp#endif 62833965Sjdp if (input_line_pointer[-1] == '\n') 62933965Sjdp bump_line_counters (); 63033965Sjdp 63133965Sjdp line_label = NULL; 63233965Sjdp 63360484Sobrien if (LABELS_WITHOUT_COLONS || flag_m68k_mri) 63433965Sjdp { 63533965Sjdp /* Text at the start of a line must be a label, we 63633965Sjdp run down and stick a colon in. */ 63733965Sjdp if (is_name_beginner (*input_line_pointer)) 63833965Sjdp { 63933965Sjdp char *line_start = input_line_pointer; 64033965Sjdp char c; 64133965Sjdp int mri_line_macro; 64233965Sjdp 64333965Sjdp LISTING_NEWLINE (); 64433965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 64533965Sjdp 64633965Sjdp c = get_symbol_end (); 64733965Sjdp 64833965Sjdp /* In MRI mode, the EQU and MACRO pseudoops must 64933965Sjdp be handled specially. */ 65033965Sjdp mri_line_macro = 0; 65133965Sjdp if (flag_m68k_mri) 65233965Sjdp { 65333965Sjdp char *rest = input_line_pointer + 1; 65433965Sjdp 65533965Sjdp if (*rest == ':') 65633965Sjdp ++rest; 65733965Sjdp if (*rest == ' ' || *rest == '\t') 65833965Sjdp ++rest; 65933965Sjdp if ((strncasecmp (rest, "EQU", 3) == 0 66033965Sjdp || strncasecmp (rest, "SET", 3) == 0) 66133965Sjdp && (rest[3] == ' ' || rest[3] == '\t')) 66233965Sjdp { 66333965Sjdp input_line_pointer = rest + 3; 66433965Sjdp equals (line_start, 66533965Sjdp strncasecmp (rest, "SET", 3) == 0); 66633965Sjdp continue; 66733965Sjdp } 66833965Sjdp if (strncasecmp (rest, "MACRO", 5) == 0 66933965Sjdp && (rest[5] == ' ' 67033965Sjdp || rest[5] == '\t' 67133965Sjdp || is_end_of_line[(unsigned char) rest[5]])) 67233965Sjdp mri_line_macro = 1; 67333965Sjdp } 67433965Sjdp 67533965Sjdp /* In MRI mode, we need to handle the MACRO 676130561Sobrien pseudo-op specially: we don't want to put the 677130561Sobrien symbol in the symbol table. */ 67877298Sobrien if (!mri_line_macro 67960484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON 68077298Sobrien && TC_START_LABEL_WITHOUT_COLON(c, 68177298Sobrien input_line_pointer) 68260484Sobrien#endif 68377298Sobrien ) 68433965Sjdp line_label = colon (line_start); 68533965Sjdp else 68633965Sjdp line_label = symbol_create (line_start, 68733965Sjdp absolute_section, 68833965Sjdp (valueT) 0, 68933965Sjdp &zero_address_frag); 69033965Sjdp 69133965Sjdp *input_line_pointer = c; 69233965Sjdp if (c == ':') 69333965Sjdp input_line_pointer++; 69433965Sjdp } 69533965Sjdp } 69633965Sjdp } 69733965Sjdp 698130561Sobrien /* We are at the beginning of a line, or similar place. 69977298Sobrien We expect a well-formed assembler statement. 70077298Sobrien A "symbol-name:" is a statement. 70177298Sobrien 70277298Sobrien Depending on what compiler is used, the order of these tests 70377298Sobrien may vary to catch most common case 1st. 704218822Sdim Each test is independent of all other tests at the (top) 705218822Sdim level. */ 706218822Sdim do 70777298Sobrien c = *input_line_pointer++; 708218822Sdim while (c == '\t' || c == ' ' || c == '\f'); 70938889Sjdp 71038889Sjdp#ifndef NO_LISTING 71138889Sjdp /* If listing is on, and we are expanding a macro, then give 71238889Sjdp the listing code the contents of the expanded line. */ 71338889Sjdp if (listing) 71438889Sjdp { 71538889Sjdp if ((listing & LISTING_MACEXP) && macro_nest > 0) 71638889Sjdp { 71738889Sjdp char *copy; 71838889Sjdp int len; 71938889Sjdp 72038889Sjdp /* Find the end of the current expanded macro line. */ 721218822Sdim s = find_end_of_line (input_line_pointer - 1, flag_m68k_mri); 72238889Sjdp 723218822Sdim if (s != last_eol) 724218822Sdim { 725218822Sdim last_eol = s; 726218822Sdim /* Copy it for safe keeping. Also give an indication of 727218822Sdim how much macro nesting is involved at this point. */ 728218822Sdim len = s - (input_line_pointer - 1); 729218822Sdim copy = (char *) xmalloc (len + macro_nest + 2); 730218822Sdim memset (copy, '>', macro_nest); 731218822Sdim copy[macro_nest] = ' '; 732218822Sdim memcpy (copy + macro_nest + 1, input_line_pointer - 1, len); 733218822Sdim copy[macro_nest + 1 + len] = '\0'; 73438889Sjdp 735218822Sdim /* Install the line with the listing facility. */ 736218822Sdim listing_newline (copy); 737218822Sdim } 73838889Sjdp } 73938889Sjdp else 74038889Sjdp listing_newline (NULL); 74138889Sjdp } 74238889Sjdp#endif 74377298Sobrien /* C is the 1st significant character. 74477298Sobrien Input_line_pointer points after that character. */ 74533965Sjdp if (is_name_beginner (c)) 74633965Sjdp { 74777298Sobrien /* Want user-defined label or pseudo/opcode. */ 74833965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 74933965Sjdp 75033965Sjdp s = --input_line_pointer; 75177298Sobrien c = get_symbol_end (); /* name's delimiter. */ 75277298Sobrien 75377298Sobrien /* C is character after symbol. 754130561Sobrien That character's place in the input line is now '\0'. 755130561Sobrien S points to the beginning of the symbol. 756130561Sobrien [In case of pseudo-op, s->'.'.] 757130561Sobrien Input_line_pointer->'\0' where c was. */ 75877298Sobrien if (TC_START_LABEL (c, input_line_pointer)) 75933965Sjdp { 76033965Sjdp if (flag_m68k_mri) 76133965Sjdp { 76233965Sjdp char *rest = input_line_pointer + 1; 76333965Sjdp 76433965Sjdp /* In MRI mode, \tsym: set 0 is permitted. */ 76533965Sjdp if (*rest == ':') 76633965Sjdp ++rest; 76777298Sobrien 76833965Sjdp if (*rest == ' ' || *rest == '\t') 76933965Sjdp ++rest; 77077298Sobrien 77133965Sjdp if ((strncasecmp (rest, "EQU", 3) == 0 77233965Sjdp || strncasecmp (rest, "SET", 3) == 0) 77333965Sjdp && (rest[3] == ' ' || rest[3] == '\t')) 77433965Sjdp { 77533965Sjdp input_line_pointer = rest + 3; 77633965Sjdp equals (s, 1); 77733965Sjdp continue; 77833965Sjdp } 77933965Sjdp } 78033965Sjdp 78177298Sobrien line_label = colon (s); /* User-defined label. */ 78277298Sobrien /* Put ':' back for error messages' sake. */ 78377298Sobrien *input_line_pointer++ = ':'; 784130561Sobrien#ifdef tc_check_label 785130561Sobrien tc_check_label (line_label); 786130561Sobrien#endif 78777298Sobrien /* Input_line_pointer->after ':'. */ 78833965Sjdp SKIP_WHITESPACE (); 78933965Sjdp } 790218822Sdim else if (input_line_pointer[1] == '=' 791218822Sdim && (c == '=' 792218822Sdim || ((c == ' ' || c == '\t') 793218822Sdim && input_line_pointer[2] == '='))) 794218822Sdim { 795218822Sdim equals (s, -1); 796218822Sdim demand_empty_rest_of_line (); 797218822Sdim } 798218822Sdim else if ((c == '=' 799218822Sdim || ((c == ' ' || c == '\t') 800218822Sdim && input_line_pointer[1] == '=')) 80133965Sjdp#ifdef TC_EQUAL_IN_INSN 802218822Sdim && !TC_EQUAL_IN_INSN (c, s) 80333965Sjdp#endif 804218822Sdim ) 80533965Sjdp { 80633965Sjdp equals (s, 1); 80733965Sjdp demand_empty_rest_of_line (); 80833965Sjdp } 80933965Sjdp else 81077298Sobrien { 81177298Sobrien /* Expect pseudo-op or machine instruction. */ 81233965Sjdp pop = NULL; 81333965Sjdp 814130561Sobrien#ifndef TC_CASE_SENSITIVE 81533965Sjdp { 81633965Sjdp char *s2 = s; 81777298Sobrien 81877298Sobrien strncpy (original_case_string, s2, sizeof (original_case_string)); 81977298Sobrien original_case_string[sizeof (original_case_string) - 1] = 0; 82077298Sobrien 82133965Sjdp while (*s2) 82233965Sjdp { 82389857Sobrien *s2 = TOLOWER (*s2); 82433965Sjdp s2++; 82533965Sjdp } 82633965Sjdp } 82733965Sjdp#endif 82860484Sobrien if (NO_PSEUDO_DOT || flag_m68k_mri) 82933965Sjdp { 830218822Sdim /* The MRI assembler uses pseudo-ops without 831218822Sdim a period. */ 83233965Sjdp pop = (pseudo_typeS *) hash_find (po_hash, s); 83333965Sjdp if (pop != NULL && pop->poc_handler == NULL) 83433965Sjdp pop = NULL; 83533965Sjdp } 83633965Sjdp 83733965Sjdp if (pop != NULL 83877298Sobrien || (!flag_m68k_mri && *s == '.')) 83933965Sjdp { 84077298Sobrien /* PSEUDO - OP. 84133965Sjdp 842130561Sobrien WARNING: c has next char, which may be end-of-line. 843130561Sobrien We lookup the pseudo-op table with s+1 because we 844130561Sobrien already know that the pseudo-op begins with a '.'. */ 84577298Sobrien 84633965Sjdp if (pop == NULL) 84733965Sjdp pop = (pseudo_typeS *) hash_find (po_hash, s + 1); 848130561Sobrien if (pop && !pop->poc_handler) 849130561Sobrien pop = NULL; 85033965Sjdp 85133965Sjdp /* In MRI mode, we may need to insert an 852130561Sobrien automatic alignment directive. What a hack 853130561Sobrien this is. */ 85433965Sjdp if (mri_pending_align 85533965Sjdp && (pop == NULL 85677298Sobrien || !((pop->poc_handler == cons 85777298Sobrien && pop->poc_val == 1) 85877298Sobrien || (pop->poc_handler == s_space 85977298Sobrien && pop->poc_val == 1) 86033965Sjdp#ifdef tc_conditional_pseudoop 86177298Sobrien || tc_conditional_pseudoop (pop) 86233965Sjdp#endif 86377298Sobrien || pop->poc_handler == s_if 86477298Sobrien || pop->poc_handler == s_ifdef 86577298Sobrien || pop->poc_handler == s_ifc 86677298Sobrien || pop->poc_handler == s_ifeqs 86777298Sobrien || pop->poc_handler == s_else 86877298Sobrien || pop->poc_handler == s_endif 86977298Sobrien || pop->poc_handler == s_globl 87077298Sobrien || pop->poc_handler == s_ignore))) 87133965Sjdp { 87233965Sjdp do_align (1, (char *) NULL, 0, 0); 87333965Sjdp mri_pending_align = 0; 87477298Sobrien 87533965Sjdp if (line_label != NULL) 87633965Sjdp { 87760484Sobrien symbol_set_frag (line_label, frag_now); 87833965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 87933965Sjdp } 88033965Sjdp } 88133965Sjdp 88277298Sobrien /* Print the error msg now, while we still can. */ 88333965Sjdp if (pop == NULL) 88433965Sjdp { 885218822Sdim char *end = input_line_pointer; 886218822Sdim 88733965Sjdp *input_line_pointer = c; 88833965Sjdp s_ignore (0); 889218822Sdim c = *--input_line_pointer; 890218822Sdim *input_line_pointer = '\0'; 891218822Sdim if (! macro_defined || ! try_macro (c, s)) 892218822Sdim { 893218822Sdim *end = '\0'; 894218822Sdim as_bad (_("unknown pseudo-op: `%s'"), s); 895218822Sdim *input_line_pointer++ = c; 896218822Sdim } 89733965Sjdp continue; 89833965Sjdp } 89933965Sjdp 90077298Sobrien /* Put it back for error messages etc. */ 90133965Sjdp *input_line_pointer = c; 90233965Sjdp /* The following skip of whitespace is compulsory. 90333965Sjdp A well shaped space is sometimes all that separates 90477298Sobrien keyword from operands. */ 90533965Sjdp if (c == ' ' || c == '\t') 90633965Sjdp input_line_pointer++; 90777298Sobrien 90877298Sobrien /* Input_line is restored. 909130561Sobrien Input_line_pointer->1st non-blank char 910130561Sobrien after pseudo-operation. */ 91133965Sjdp (*pop->poc_handler) (pop->poc_val); 91233965Sjdp 91333965Sjdp /* If that was .end, just get out now. */ 91433965Sjdp if (pop->poc_handler == s_end) 91533965Sjdp goto quit; 91633965Sjdp } 91733965Sjdp else 91833965Sjdp { 91977298Sobrien /* WARNING: c has char, which may be end-of-line. */ 92077298Sobrien /* Also: input_line_pointer->`\0` where c was. */ 92133965Sjdp *input_line_pointer = c; 922218822Sdim input_line_pointer = _find_end_of_line (input_line_pointer, flag_m68k_mri, 1); 92333965Sjdp c = *input_line_pointer; 92433965Sjdp *input_line_pointer = '\0'; 92533965Sjdp 92660484Sobrien generate_lineno_debug (); 92738889Sjdp 928218822Sdim if (macro_defined && try_macro (c, s)) 929218822Sdim continue; 93033965Sjdp 93133965Sjdp if (mri_pending_align) 93233965Sjdp { 93333965Sjdp do_align (1, (char *) NULL, 0, 0); 93433965Sjdp mri_pending_align = 0; 93533965Sjdp if (line_label != NULL) 93633965Sjdp { 93760484Sobrien symbol_set_frag (line_label, frag_now); 93833965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 93933965Sjdp } 94033965Sjdp } 94133965Sjdp 94277298Sobrien md_assemble (s); /* Assemble 1 instruction. */ 94333965Sjdp 94433965Sjdp *input_line_pointer++ = c; 94533965Sjdp 94633965Sjdp /* We resume loop AFTER the end-of-line from 94777298Sobrien this instruction. */ 94877298Sobrien } 94977298Sobrien } 95033965Sjdp continue; 95177298Sobrien } 95233965Sjdp 95333965Sjdp /* Empty statement? */ 95433965Sjdp if (is_end_of_line[(unsigned char) c]) 95533965Sjdp continue; 95633965Sjdp 95789857Sobrien if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c)) 95833965Sjdp { 95977298Sobrien /* local label ("4:") */ 96033965Sjdp char *backup = input_line_pointer; 96133965Sjdp 96233965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 96333965Sjdp 96433965Sjdp temp = c - '0'; 96533965Sjdp 96677298Sobrien /* Read the whole number. */ 96789857Sobrien while (ISDIGIT (*input_line_pointer)) 96833965Sjdp { 96933965Sjdp temp = (temp * 10) + *input_line_pointer - '0'; 97033965Sjdp ++input_line_pointer; 97177298Sobrien } 97233965Sjdp 97333965Sjdp if (LOCAL_LABELS_DOLLAR 97433965Sjdp && *input_line_pointer == '$' 97533965Sjdp && *(input_line_pointer + 1) == ':') 97633965Sjdp { 97733965Sjdp input_line_pointer += 2; 97833965Sjdp 97933965Sjdp if (dollar_label_defined (temp)) 98033965Sjdp { 98160484Sobrien as_fatal (_("label \"%d$\" redefined"), temp); 98233965Sjdp } 98333965Sjdp 98433965Sjdp define_dollar_label (temp); 98533965Sjdp colon (dollar_label_name (temp, 0)); 98633965Sjdp continue; 98733965Sjdp } 98833965Sjdp 98933965Sjdp if (LOCAL_LABELS_FB 99033965Sjdp && *input_line_pointer++ == ':') 99133965Sjdp { 99233965Sjdp fb_label_instance_inc (temp); 99333965Sjdp colon (fb_label_name (temp, 0)); 99433965Sjdp continue; 99533965Sjdp } 99633965Sjdp 99733965Sjdp input_line_pointer = backup; 99833965Sjdp } /* local label ("4:") */ 99933965Sjdp 100033965Sjdp if (c && strchr (line_comment_chars, c)) 100177298Sobrien { /* Its a comment. Better say APP or NO_APP. */ 1002130561Sobrien sb sbuf; 100333965Sjdp char *ends; 100433965Sjdp char *new_buf; 100533965Sjdp char *new_tmp; 100633965Sjdp unsigned int new_length; 100733965Sjdp char *tmp_buf = 0; 100833965Sjdp 100933965Sjdp s = input_line_pointer; 101033965Sjdp if (strncmp (s, "APP\n", 4)) 1011218822Sdim { 1012218822Sdim /* We ignore it. */ 1013218822Sdim ignore_rest_of_line (); 1014218822Sdim continue; 1015218822Sdim } 1016218822Sdim bump_line_counters (); 101733965Sjdp s += 4; 101833965Sjdp 1019130561Sobrien sb_new (&sbuf); 102033965Sjdp ends = strstr (s, "#NO_APP\n"); 102133965Sjdp 102233965Sjdp if (!ends) 102333965Sjdp { 102433965Sjdp unsigned int tmp_len; 102533965Sjdp unsigned int num; 102633965Sjdp 102733965Sjdp /* The end of the #APP wasn't in this buffer. We 102833965Sjdp keep reading in buffers until we find the #NO_APP 102933965Sjdp that goes with this #APP There is one. The specs 1030130561Sobrien guarantee it... */ 103133965Sjdp tmp_len = buffer_limit - s; 103233965Sjdp tmp_buf = xmalloc (tmp_len + 1); 103333965Sjdp memcpy (tmp_buf, s, tmp_len); 103433965Sjdp do 103533965Sjdp { 103633965Sjdp new_tmp = input_scrub_next_buffer (&buffer); 103733965Sjdp if (!new_tmp) 103833965Sjdp break; 103933965Sjdp else 104033965Sjdp buffer_limit = new_tmp; 104133965Sjdp input_line_pointer = buffer; 104233965Sjdp ends = strstr (buffer, "#NO_APP\n"); 104333965Sjdp if (ends) 104433965Sjdp num = ends - buffer; 104533965Sjdp else 104633965Sjdp num = buffer_limit - buffer; 104733965Sjdp 104833965Sjdp tmp_buf = xrealloc (tmp_buf, tmp_len + num); 104933965Sjdp memcpy (tmp_buf + tmp_len, buffer, num); 105033965Sjdp tmp_len += num; 105133965Sjdp } 105233965Sjdp while (!ends); 105333965Sjdp 105433965Sjdp input_line_pointer = ends ? ends + 8 : NULL; 105533965Sjdp 105633965Sjdp s = tmp_buf; 105733965Sjdp ends = s + tmp_len; 105833965Sjdp 105933965Sjdp } 106033965Sjdp else 106133965Sjdp { 106233965Sjdp input_line_pointer = ends + 8; 106333965Sjdp } 106433965Sjdp 106533965Sjdp scrub_string = s; 106633965Sjdp scrub_string_end = ends; 106733965Sjdp 106833965Sjdp new_length = ends - s; 106933965Sjdp new_buf = (char *) xmalloc (new_length); 107033965Sjdp new_tmp = new_buf; 107133965Sjdp for (;;) 107233965Sjdp { 107333965Sjdp int space; 107433965Sjdp int size; 107533965Sjdp 107633965Sjdp space = (new_buf + new_length) - new_tmp; 107733965Sjdp size = do_scrub_chars (scrub_from_string, new_tmp, space); 107833965Sjdp 107933965Sjdp if (size < space) 108033965Sjdp { 1081130561Sobrien new_tmp[size] = 0; 108233965Sjdp break; 108333965Sjdp } 108433965Sjdp 108533965Sjdp new_buf = xrealloc (new_buf, new_length + 100); 108633965Sjdp new_tmp = new_buf + new_length; 108733965Sjdp new_length += 100; 108833965Sjdp } 108933965Sjdp 109033965Sjdp if (tmp_buf) 109133965Sjdp free (tmp_buf); 109277298Sobrien 1093130561Sobrien /* We've "scrubbed" input to the preferred format. In the 1094130561Sobrien process we may have consumed the whole of the remaining 1095130561Sobrien file (and included files). We handle this formatted 1096130561Sobrien input similar to that of macro expansion, letting 1097130561Sobrien actual macro expansion (possibly nested) and other 1098130561Sobrien input expansion work. Beware that in messages, line 1099130561Sobrien numbers and possibly file names will be incorrect. */ 1100130561Sobrien sb_add_string (&sbuf, new_buf); 1101130561Sobrien input_scrub_include_sb (&sbuf, input_line_pointer, 0); 1102130561Sobrien sb_kill (&sbuf); 1103130561Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 1104130561Sobrien free (new_buf); 110533965Sjdp continue; 110633965Sjdp } 110733965Sjdp 110833965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 110933965Sjdp 111033965Sjdp#ifdef tc_unrecognized_line 111133965Sjdp if (tc_unrecognized_line (c)) 111233965Sjdp continue; 111333965Sjdp#endif 111489857Sobrien input_line_pointer--; 1115218822Sdim /* Report unknown char as error. */ 1116130561Sobrien demand_empty_rest_of_line (); 111777298Sobrien } 111833965Sjdp 111933965Sjdp#ifdef md_after_pass_hook 112033965Sjdp md_after_pass_hook (); 112133965Sjdp#endif 112277298Sobrien } 112333965Sjdp 112433965Sjdp quit: 112533965Sjdp 112633965Sjdp#ifdef md_cleanup 112777298Sobrien md_cleanup (); 112833965Sjdp#endif 112977298Sobrien /* Close the input file. */ 113077298Sobrien input_scrub_close (); 113177298Sobrien#ifdef WARN_COMMENTS 113277298Sobrien { 113377298Sobrien if (warn_comment && found_comment) 113477298Sobrien as_warn_where (found_comment_file, found_comment, 113577298Sobrien "first comment found here"); 113677298Sobrien } 113777298Sobrien#endif 113833965Sjdp} 113933965Sjdp 1140218822Sdim/* Convert O_constant expression EXP into the equivalent O_big representation. 1141218822Sdim Take the sign of the number from X_unsigned rather than X_add_number. */ 1142218822Sdim 1143218822Sdimstatic void 1144218822Sdimconvert_to_bignum (expressionS *exp) 1145218822Sdim{ 1146218822Sdim valueT value; 1147218822Sdim unsigned int i; 1148218822Sdim 1149218822Sdim value = exp->X_add_number; 1150218822Sdim for (i = 0; i < sizeof (exp->X_add_number) / CHARS_PER_LITTLENUM; i++) 1151218822Sdim { 1152218822Sdim generic_bignum[i] = value & LITTLENUM_MASK; 1153218822Sdim value >>= LITTLENUM_NUMBER_OF_BITS; 1154218822Sdim } 1155218822Sdim /* Add a sequence of sign bits if the top bit of X_add_number is not 1156218822Sdim the sign of the original value. */ 1157218822Sdim if ((exp->X_add_number < 0) != !exp->X_unsigned) 1158218822Sdim generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK; 1159218822Sdim exp->X_op = O_big; 1160218822Sdim exp->X_add_number = i; 1161218822Sdim} 1162218822Sdim 116333965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first 116433965Sjdp nonquoted space. This function looks for that point, stuffs a null 116533965Sjdp in, and sets *STOPCP to the character that used to be there, and 116633965Sjdp returns the location. 116733965Sjdp 116833965Sjdp Until I hear otherwise, I am going to assume that this is only true 116933965Sjdp for the m68k MRI assembler. */ 117033965Sjdp 117133965Sjdpchar * 1172130561Sobrienmri_comment_field (char *stopcp) 117333965Sjdp{ 117477298Sobrien char *s; 117533965Sjdp#ifdef TC_M68K 117633965Sjdp int inquote = 0; 117733965Sjdp 117833965Sjdp know (flag_m68k_mri); 117933965Sjdp 118033965Sjdp for (s = input_line_pointer; 118177298Sobrien ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t') 118233965Sjdp || inquote); 118333965Sjdp s++) 118433965Sjdp { 118533965Sjdp if (*s == '\'') 118677298Sobrien inquote = !inquote; 118733965Sjdp } 118833965Sjdp#else 118977298Sobrien for (s = input_line_pointer; 119077298Sobrien !is_end_of_line[(unsigned char) *s]; 119177298Sobrien s++) 119233965Sjdp ; 119377298Sobrien#endif 119433965Sjdp *stopcp = *s; 119533965Sjdp *s = '\0'; 119677298Sobrien 119733965Sjdp return s; 119833965Sjdp} 119933965Sjdp 120033965Sjdp/* Skip to the end of an MRI comment field. */ 120133965Sjdp 120233965Sjdpvoid 1203130561Sobrienmri_comment_end (char *stop, int stopc) 120433965Sjdp{ 120533965Sjdp know (flag_mri); 120633965Sjdp 120733965Sjdp input_line_pointer = stop; 120833965Sjdp *stop = stopc; 120977298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 121033965Sjdp ++input_line_pointer; 121133965Sjdp} 121233965Sjdp 121377298Sobrienvoid 1214130561Sobriens_abort (int ignore ATTRIBUTE_UNUSED) 121533965Sjdp{ 121660484Sobrien as_fatal (_(".abort detected. Abandoning ship.")); 121733965Sjdp} 121833965Sjdp 121933965Sjdp/* Guts of .align directive. N is the power of two to which to align. 122033965Sjdp FILL may be NULL, or it may point to the bytes of the fill pattern. 122133965Sjdp LEN is the length of whatever FILL points to, if anything. MAX is 122233965Sjdp the maximum number of characters to skip when doing the alignment, 122333965Sjdp or 0 if there is no maximum. */ 122433965Sjdp 122577298Sobrienstatic void 1226130561Sobriendo_align (int n, char *fill, int len, int max) 122733965Sjdp{ 122889857Sobrien if (now_seg == absolute_section) 122989857Sobrien { 123089857Sobrien if (fill != NULL) 123189857Sobrien while (len-- > 0) 123289857Sobrien if (*fill++ != '\0') 123389857Sobrien { 123489857Sobrien as_warn (_("ignoring fill value in absolute section")); 123589857Sobrien break; 123689857Sobrien } 123789857Sobrien fill = NULL; 123889857Sobrien len = 0; 123989857Sobrien } 124089857Sobrien 1241218822Sdim#ifdef md_flush_pending_output 1242218822Sdim md_flush_pending_output (); 1243218822Sdim#endif 124433965Sjdp#ifdef md_do_align 124533965Sjdp md_do_align (n, fill, len, max, just_record_alignment); 124633965Sjdp#endif 124733965Sjdp 124877298Sobrien /* Only make a frag if we HAVE to... */ 124933965Sjdp if (n != 0 && !need_pass_2) 125033965Sjdp { 125177298Sobrien if (fill == NULL) 125277298Sobrien { 125377298Sobrien if (subseg_text_p (now_seg)) 125477298Sobrien frag_align_code (n, max); 125577298Sobrien else 125677298Sobrien frag_align (n, 0, max); 125777298Sobrien } 125877298Sobrien else if (len <= 1) 125933965Sjdp frag_align (n, *fill, max); 126033965Sjdp else 126133965Sjdp frag_align_pattern (n, fill, len, max); 126233965Sjdp } 126333965Sjdp 126433965Sjdp#ifdef md_do_align 1265130561Sobrien just_record_alignment: ATTRIBUTE_UNUSED_LABEL 126633965Sjdp#endif 126733965Sjdp 126860484Sobrien record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER); 126933965Sjdp} 127033965Sjdp 127133965Sjdp/* Handle the .align pseudo-op. A positive ARG is a default alignment 127233965Sjdp (in bytes). A negative ARG is the negative of the length of the 127333965Sjdp fill pattern. BYTES_P is non-zero if the alignment value should be 127433965Sjdp interpreted as the byte boundary, rather than the power of 2. */ 127533965Sjdp 1276218822Sdim#define ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1) 1277218822Sdim 127833965Sjdpstatic void 1279130561Sobriens_align (int arg, int bytes_p) 128033965Sjdp{ 1281218822Sdim unsigned int align_limit = ALIGN_LIMIT; 1282218822Sdim unsigned int align; 128333965Sjdp char *stop = NULL; 1284218822Sdim char stopc = 0; 128533965Sjdp offsetT fill = 0; 128633965Sjdp int max; 128733965Sjdp int fill_p; 128833965Sjdp 128933965Sjdp if (flag_mri) 129033965Sjdp stop = mri_comment_field (&stopc); 129133965Sjdp 129233965Sjdp if (is_end_of_line[(unsigned char) *input_line_pointer]) 129333965Sjdp { 129433965Sjdp if (arg < 0) 129533965Sjdp align = 0; 129633965Sjdp else 129777298Sobrien align = arg; /* Default value from pseudo-op table. */ 129833965Sjdp } 129933965Sjdp else 130033965Sjdp { 130133965Sjdp align = get_absolute_expression (); 130233965Sjdp SKIP_WHITESPACE (); 130333965Sjdp } 130433965Sjdp 130533965Sjdp if (bytes_p) 130633965Sjdp { 130733965Sjdp /* Convert to a power of 2. */ 130833965Sjdp if (align != 0) 130933965Sjdp { 131033965Sjdp unsigned int i; 131133965Sjdp 131233965Sjdp for (i = 0; (align & 1) == 0; align >>= 1, ++i) 131333965Sjdp ; 131433965Sjdp if (align != 1) 131589857Sobrien as_bad (_("alignment not a power of 2")); 131677298Sobrien 131733965Sjdp align = i; 131833965Sjdp } 131933965Sjdp } 132033965Sjdp 1321218822Sdim if (align > align_limit) 132233965Sjdp { 1323218822Sdim align = align_limit; 132489857Sobrien as_warn (_("alignment too large: %u assumed"), align); 132533965Sjdp } 132633965Sjdp 132733965Sjdp if (*input_line_pointer != ',') 132833965Sjdp { 132933965Sjdp fill_p = 0; 133033965Sjdp max = 0; 133133965Sjdp } 133233965Sjdp else 133333965Sjdp { 133433965Sjdp ++input_line_pointer; 133533965Sjdp if (*input_line_pointer == ',') 133633965Sjdp fill_p = 0; 133733965Sjdp else 133833965Sjdp { 133933965Sjdp fill = get_absolute_expression (); 134033965Sjdp SKIP_WHITESPACE (); 134133965Sjdp fill_p = 1; 134233965Sjdp } 134333965Sjdp 134433965Sjdp if (*input_line_pointer != ',') 134533965Sjdp max = 0; 134633965Sjdp else 134733965Sjdp { 134833965Sjdp ++input_line_pointer; 134933965Sjdp max = get_absolute_expression (); 135033965Sjdp } 135133965Sjdp } 135233965Sjdp 135377298Sobrien if (!fill_p) 135433965Sjdp { 135533965Sjdp if (arg < 0) 135660484Sobrien as_warn (_("expected fill pattern missing")); 135733965Sjdp do_align (align, (char *) NULL, 0, max); 135833965Sjdp } 135933965Sjdp else 136033965Sjdp { 136133965Sjdp int fill_len; 136233965Sjdp 136333965Sjdp if (arg >= 0) 136433965Sjdp fill_len = 1; 136533965Sjdp else 136677298Sobrien fill_len = -arg; 136733965Sjdp if (fill_len <= 1) 136833965Sjdp { 136933965Sjdp char fill_char; 137033965Sjdp 137133965Sjdp fill_char = fill; 137233965Sjdp do_align (align, &fill_char, fill_len, max); 137333965Sjdp } 137433965Sjdp else 137533965Sjdp { 137633965Sjdp char ab[16]; 137733965Sjdp 137838889Sjdp if ((size_t) fill_len > sizeof ab) 137933965Sjdp abort (); 138033965Sjdp md_number_to_chars (ab, fill, fill_len); 138133965Sjdp do_align (align, ab, fill_len, max); 138233965Sjdp } 138333965Sjdp } 138433965Sjdp 138560484Sobrien demand_empty_rest_of_line (); 138660484Sobrien 138733965Sjdp if (flag_mri) 138833965Sjdp mri_comment_end (stop, stopc); 138933965Sjdp} 139033965Sjdp 139133965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means 139233965Sjdp align to a 4 byte boundary. */ 139333965Sjdp 139477298Sobrienvoid 1395130561Sobriens_align_bytes (int arg) 139633965Sjdp{ 139733965Sjdp s_align (arg, 1); 139833965Sjdp} 139933965Sjdp 140038889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align 140133965Sjdp to a 2**4 boundary. */ 140233965Sjdp 140377298Sobrienvoid 1404130561Sobriens_align_ptwo (int arg) 140533965Sjdp{ 140633965Sjdp s_align (arg, 0); 140733965Sjdp} 140833965Sjdp 1409218822Sdim/* Switch in and out of alternate macro mode. */ 1410218822Sdim 1411218822Sdimvoid 1412218822Sdims_altmacro (int on) 1413218822Sdim{ 1414218822Sdim demand_empty_rest_of_line (); 1415218822Sdim macro_set_alternate (on); 1416218822Sdim} 1417218822Sdim 1418130561SobriensymbolS * 1419130561Sobriens_comm_internal (int param, 1420130561Sobrien symbolS *(*comm_parse_extra) (int, symbolS *, addressT)) 142133965Sjdp{ 1422130561Sobrien char *name; 1423130561Sobrien char c; 1424130561Sobrien char *p; 1425130561Sobrien offsetT temp, size; 1426130561Sobrien symbolS *symbolP = NULL; 142733965Sjdp char *stop = NULL; 1428218822Sdim char stopc = 0; 1429130561Sobrien expressionS exp; 143033965Sjdp 143133965Sjdp if (flag_mri) 143233965Sjdp stop = mri_comment_field (&stopc); 143333965Sjdp 143433965Sjdp name = input_line_pointer; 143533965Sjdp c = get_symbol_end (); 143677298Sobrien /* Just after name is now '\0'. */ 143733965Sjdp p = input_line_pointer; 143833965Sjdp *p = c; 143989857Sobrien 144089857Sobrien if (name == p) 144189857Sobrien { 144289857Sobrien as_bad (_("expected symbol name")); 1443218822Sdim ignore_rest_of_line (); 1444130561Sobrien goto out; 144589857Sobrien } 144689857Sobrien 144733965Sjdp SKIP_WHITESPACE (); 144877298Sobrien 1449130561Sobrien /* Accept an optional comma after the name. The comma used to be 1450130561Sobrien required, but Irix 5 cc does not generate it for .lcomm. */ 1451130561Sobrien if (*input_line_pointer == ',') 1452130561Sobrien input_line_pointer++; 1453130561Sobrien 1454130561Sobrien temp = get_absolute_expr (&exp); 1455130561Sobrien size = temp; 1456130561Sobrien size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1; 1457130561Sobrien if (exp.X_op == O_absent) 145833965Sjdp { 1459130561Sobrien as_bad (_("missing size expression")); 146060484Sobrien ignore_rest_of_line (); 1461130561Sobrien goto out; 146233965Sjdp } 1463130561Sobrien else if (temp != size || !exp.X_unsigned) 146433965Sjdp { 1465130561Sobrien as_warn (_("size (%ld) out of range, ignored"), (long) temp); 146660484Sobrien ignore_rest_of_line (); 1467130561Sobrien goto out; 146833965Sjdp } 146977298Sobrien 1470218822Sdim *p = 0; 147133965Sjdp symbolP = symbol_find_or_make (name); 1472218822Sdim if ((S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) 1473218822Sdim && !S_IS_COMMON (symbolP)) 147433965Sjdp { 1475218822Sdim if (!S_IS_VOLATILE (symbolP)) 1476218822Sdim { 1477218822Sdim symbolP = NULL; 1478218822Sdim as_bad (_("symbol `%s' is already defined"), name); 1479218822Sdim *p = c; 1480218822Sdim ignore_rest_of_line (); 1481218822Sdim goto out; 1482218822Sdim } 1483218822Sdim symbolP = symbol_clone (symbolP, 1); 1484218822Sdim S_SET_SEGMENT (symbolP, undefined_section); 1485218822Sdim S_SET_VALUE (symbolP, 0); 1486218822Sdim symbol_set_frag (symbolP, &zero_address_frag); 1487218822Sdim S_CLEAR_VOLATILE (symbolP); 148833965Sjdp } 148977298Sobrien 1490130561Sobrien size = S_GET_VALUE (symbolP); 1491130561Sobrien if (size == 0) 1492130561Sobrien size = temp; 1493130561Sobrien else if (size != temp) 1494130561Sobrien as_warn (_("size of \"%s\" is already %ld; not changing to %ld"), 1495130561Sobrien name, (long) size, (long) temp); 1496130561Sobrien 1497130561Sobrien *p = c; 1498130561Sobrien if (comm_parse_extra != NULL) 1499130561Sobrien symbolP = (*comm_parse_extra) (param, symbolP, size); 150033965Sjdp else 150133965Sjdp { 1502130561Sobrien S_SET_VALUE (symbolP, (valueT) size); 150333965Sjdp S_SET_EXTERNAL (symbolP); 1504218822Sdim S_SET_SEGMENT (symbolP, bfd_com_section_ptr); 1505130561Sobrien#ifdef OBJ_VMS 1506130561Sobrien { 1507130561Sobrien extern int flag_one; 1508130561Sobrien if (size == 0 || !flag_one) 1509130561Sobrien S_GET_OTHER (symbolP) = const_flag; 1510130561Sobrien } 1511130561Sobrien#endif 151233965Sjdp } 151333965Sjdp 151460484Sobrien demand_empty_rest_of_line (); 1515130561Sobrien out: 151633965Sjdp if (flag_mri) 151733965Sjdp mri_comment_end (stop, stopc); 1518130561Sobrien return symbolP; 1519130561Sobrien} 152033965Sjdp 1521130561Sobrienvoid 1522130561Sobriens_comm (int ignore) 1523130561Sobrien{ 1524130561Sobrien s_comm_internal (ignore, NULL); 1525130561Sobrien} 1526130561Sobrien 152733965Sjdp/* The MRI COMMON pseudo-op. We handle this by creating a common 152833965Sjdp symbol with the appropriate name. We make s_space do the right 152933965Sjdp thing by increasing the size. */ 153033965Sjdp 153133965Sjdpvoid 1532130561Sobriens_mri_common (int small ATTRIBUTE_UNUSED) 153333965Sjdp{ 153433965Sjdp char *name; 153533965Sjdp char c; 153633965Sjdp char *alc = NULL; 153733965Sjdp symbolS *sym; 153833965Sjdp offsetT align; 153933965Sjdp char *stop = NULL; 1540218822Sdim char stopc = 0; 154133965Sjdp 154277298Sobrien if (!flag_mri) 154333965Sjdp { 154433965Sjdp s_comm (0); 154533965Sjdp return; 154633965Sjdp } 154733965Sjdp 154833965Sjdp stop = mri_comment_field (&stopc); 154933965Sjdp 155033965Sjdp SKIP_WHITESPACE (); 155133965Sjdp 155233965Sjdp name = input_line_pointer; 155389857Sobrien if (!ISDIGIT (*name)) 155433965Sjdp c = get_symbol_end (); 155533965Sjdp else 155633965Sjdp { 155733965Sjdp do 155833965Sjdp { 155933965Sjdp ++input_line_pointer; 156033965Sjdp } 156189857Sobrien while (ISDIGIT (*input_line_pointer)); 156277298Sobrien 156333965Sjdp c = *input_line_pointer; 156433965Sjdp *input_line_pointer = '\0'; 156533965Sjdp 156633965Sjdp if (line_label != NULL) 156733965Sjdp { 156833965Sjdp alc = (char *) xmalloc (strlen (S_GET_NAME (line_label)) 156933965Sjdp + (input_line_pointer - name) 157033965Sjdp + 1); 157133965Sjdp sprintf (alc, "%s%s", name, S_GET_NAME (line_label)); 157233965Sjdp name = alc; 157333965Sjdp } 157433965Sjdp } 157533965Sjdp 157633965Sjdp sym = symbol_find_or_make (name); 157733965Sjdp *input_line_pointer = c; 157833965Sjdp if (alc != NULL) 157933965Sjdp free (alc); 158033965Sjdp 158133965Sjdp if (*input_line_pointer != ',') 158233965Sjdp align = 0; 158333965Sjdp else 158433965Sjdp { 158533965Sjdp ++input_line_pointer; 158633965Sjdp align = get_absolute_expression (); 158733965Sjdp } 158833965Sjdp 158977298Sobrien if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym)) 159033965Sjdp { 159189857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym)); 159260484Sobrien ignore_rest_of_line (); 159333965Sjdp mri_comment_end (stop, stopc); 159433965Sjdp return; 159533965Sjdp } 159633965Sjdp 159733965Sjdp S_SET_EXTERNAL (sym); 1598218822Sdim S_SET_SEGMENT (sym, bfd_com_section_ptr); 159933965Sjdp mri_common_symbol = sym; 160033965Sjdp 160133965Sjdp#ifdef S_SET_ALIGN 160233965Sjdp if (align != 0) 160333965Sjdp S_SET_ALIGN (sym, align); 160433965Sjdp#endif 160533965Sjdp 160633965Sjdp if (line_label != NULL) 160733965Sjdp { 160860484Sobrien expressionS exp; 160960484Sobrien exp.X_op = O_symbol; 161060484Sobrien exp.X_add_symbol = sym; 161160484Sobrien exp.X_add_number = 0; 161260484Sobrien symbol_set_value_expression (line_label, &exp); 161360484Sobrien symbol_set_frag (line_label, &zero_address_frag); 161433965Sjdp S_SET_SEGMENT (line_label, expr_section); 161533965Sjdp } 161633965Sjdp 161733965Sjdp /* FIXME: We just ignore the small argument, which distinguishes 161833965Sjdp COMMON and COMMON.S. I don't know what we can do about it. */ 161933965Sjdp 162033965Sjdp /* Ignore the type and hptype. */ 162133965Sjdp if (*input_line_pointer == ',') 162233965Sjdp input_line_pointer += 2; 162333965Sjdp if (*input_line_pointer == ',') 162433965Sjdp input_line_pointer += 2; 162533965Sjdp 162660484Sobrien demand_empty_rest_of_line (); 162760484Sobrien 162833965Sjdp mri_comment_end (stop, stopc); 162933965Sjdp} 163033965Sjdp 163133965Sjdpvoid 1632130561Sobriens_data (int ignore ATTRIBUTE_UNUSED) 163333965Sjdp{ 163433965Sjdp segT section; 163533965Sjdp register int temp; 163633965Sjdp 163733965Sjdp temp = get_absolute_expression (); 163833965Sjdp if (flag_readonly_data_in_text) 163933965Sjdp { 164033965Sjdp section = text_section; 164133965Sjdp temp += 1000; 164233965Sjdp } 164333965Sjdp else 164433965Sjdp section = data_section; 164533965Sjdp 164633965Sjdp subseg_set (section, (subsegT) temp); 164733965Sjdp 164833965Sjdp#ifdef OBJ_VMS 164933965Sjdp const_flag = 0; 165033965Sjdp#endif 165133965Sjdp demand_empty_rest_of_line (); 165233965Sjdp} 165333965Sjdp 165433965Sjdp/* Handle the .appfile pseudo-op. This is automatically generated by 165533965Sjdp do_scrub_chars when a preprocessor # line comment is seen with a 165633965Sjdp file name. This default definition may be overridden by the object 165733965Sjdp or CPU specific pseudo-ops. This function is also the default 165833965Sjdp definition for .file; the APPFILE argument is 1 for .appfile, 0 for 165933965Sjdp .file. */ 166033965Sjdp 166177298Sobrienvoid 1662218822Sdims_app_file_string (char *file, int appfile ATTRIBUTE_UNUSED) 1663104834Sobrien{ 1664104834Sobrien#ifdef LISTING 1665104834Sobrien if (listing) 1666104834Sobrien listing_source_file (file); 1667104834Sobrien#endif 1668104834Sobrien register_dependency (file); 1669104834Sobrien#ifdef obj_app_file 1670218822Sdim obj_app_file (file, appfile); 1671104834Sobrien#endif 1672104834Sobrien} 1673104834Sobrien 1674104834Sobrienvoid 1675130561Sobriens_app_file (int appfile) 167633965Sjdp{ 167733965Sjdp register char *s; 167833965Sjdp int length; 167933965Sjdp 168077298Sobrien /* Some assemblers tolerate immediately following '"'. */ 168133965Sjdp if ((s = demand_copy_string (&length)) != 0) 168233965Sjdp { 168338889Sjdp int may_omit 1684218822Sdim = (!new_logical_line_flags (s, -1, 1) && appfile); 168533965Sjdp 168633965Sjdp /* In MRI mode, the preprocessor may have inserted an extraneous 1687130561Sobrien backquote. */ 168833965Sjdp if (flag_m68k_mri 168933965Sjdp && *input_line_pointer == '\'' 169033965Sjdp && is_end_of_line[(unsigned char) input_line_pointer[1]]) 169133965Sjdp ++input_line_pointer; 169233965Sjdp 169333965Sjdp demand_empty_rest_of_line (); 169477298Sobrien if (!may_omit) 1695218822Sdim s_app_file_string (s, appfile); 169638889Sjdp } 169733965Sjdp} 169833965Sjdp 1699218822Sdimstatic int 1700218822Sdimget_linefile_number (int *flag) 1701218822Sdim{ 1702218822Sdim SKIP_WHITESPACE (); 1703218822Sdim 1704218822Sdim if (*input_line_pointer < '0' || *input_line_pointer > '9') 1705218822Sdim return 0; 1706218822Sdim 1707218822Sdim *flag = get_absolute_expression (); 1708218822Sdim 1709218822Sdim return 1; 1710218822Sdim} 1711218822Sdim 171233965Sjdp/* Handle the .appline pseudo-op. This is automatically generated by 171333965Sjdp do_scrub_chars when a preprocessor # line comment is seen. This 171433965Sjdp default definition may be overridden by the object or CPU specific 171533965Sjdp pseudo-ops. */ 171633965Sjdp 171733965Sjdpvoid 1718218822Sdims_app_line (int appline) 171933965Sjdp{ 1720218822Sdim char *file = NULL; 172133965Sjdp int l; 172233965Sjdp 172333965Sjdp /* The given number is that of the next line. */ 1724218822Sdim if (appline) 1725218822Sdim l = get_absolute_expression (); 1726218822Sdim else if (!get_linefile_number (&l)) 1727218822Sdim { 1728218822Sdim ignore_rest_of_line (); 1729218822Sdim return; 1730218822Sdim } 1731218822Sdim 1732218822Sdim l--; 1733218822Sdim 1734218822Sdim if (l < -1) 173533965Sjdp /* Some of the back ends can't deal with non-positive line numbers. 1736218822Sdim Besides, it's silly. GCC however will generate a line number of 1737218822Sdim zero when it is pre-processing builtins for assembler-with-cpp files: 1738218822Sdim 1739218822Sdim # 0 "<built-in>" 1740218822Sdim 1741218822Sdim We do not want to barf on this, especially since such files are used 1742218822Sdim in the GCC and GDB testsuites. So we check for negative line numbers 1743218822Sdim rather than non-positive line numbers. */ 174489857Sobrien as_warn (_("line numbers must be positive; line number %d rejected"), 174577298Sobrien l + 1); 174633965Sjdp else 174733965Sjdp { 1748218822Sdim int flags = 0; 1749218822Sdim int length = 0; 1750218822Sdim 1751218822Sdim if (!appline) 1752218822Sdim { 1753218822Sdim SKIP_WHITESPACE (); 1754218822Sdim 1755218822Sdim if (*input_line_pointer == '"') 1756218822Sdim file = demand_copy_string (&length); 1757218822Sdim 1758218822Sdim if (file) 1759218822Sdim { 1760218822Sdim int this_flag; 1761218822Sdim 1762218822Sdim while (get_linefile_number (&this_flag)) 1763218822Sdim switch (this_flag) 1764218822Sdim { 1765218822Sdim /* From GCC's cpp documentation: 1766218822Sdim 1: start of a new file. 1767218822Sdim 2: returning to a file after having included 1768218822Sdim another file. 1769218822Sdim 3: following text comes from a system header file. 1770218822Sdim 4: following text should be treated as extern "C". 1771218822Sdim 1772218822Sdim 4 is nonsensical for the assembler; 3, we don't 1773218822Sdim care about, so we ignore it just in case a 1774218822Sdim system header file is included while 1775218822Sdim preprocessing assembly. So 1 and 2 are all we 1776218822Sdim care about, and they are mutually incompatible. 1777218822Sdim new_logical_line_flags() demands this. */ 1778218822Sdim case 1: 1779218822Sdim case 2: 1780218822Sdim if (flags && flags != (1 << this_flag)) 1781218822Sdim as_warn (_("incompatible flag %i in line directive"), 1782218822Sdim this_flag); 1783218822Sdim else 1784218822Sdim flags |= 1 << this_flag; 1785218822Sdim break; 1786218822Sdim 1787218822Sdim case 3: 1788218822Sdim case 4: 1789218822Sdim /* We ignore these. */ 1790218822Sdim break; 1791218822Sdim 1792218822Sdim default: 1793218822Sdim as_warn (_("unsupported flag %i in line directive"), 1794218822Sdim this_flag); 1795218822Sdim break; 1796218822Sdim } 1797218822Sdim 1798218822Sdim if (!is_end_of_line[(unsigned char)*input_line_pointer]) 1799218822Sdim file = 0; 1800218822Sdim } 1801218822Sdim } 1802218822Sdim 1803218822Sdim if (appline || file) 1804218822Sdim { 1805218822Sdim new_logical_line_flags (file, l, flags); 180633965Sjdp#ifdef LISTING 1807218822Sdim if (listing) 1808218822Sdim listing_source_line (l); 180933965Sjdp#endif 1810218822Sdim } 181133965Sjdp } 1812218822Sdim if (appline || file) 1813218822Sdim demand_empty_rest_of_line (); 1814218822Sdim else 1815218822Sdim ignore_rest_of_line (); 181633965Sjdp} 181733965Sjdp 181833965Sjdp/* Handle the .end pseudo-op. Actually, the real work is done in 181933965Sjdp read_a_source_file. */ 182033965Sjdp 182133965Sjdpvoid 1822130561Sobriens_end (int ignore ATTRIBUTE_UNUSED) 182333965Sjdp{ 182433965Sjdp if (flag_mri) 182533965Sjdp { 182633965Sjdp /* The MRI assembler permits the start symbol to follow .end, 1827130561Sobrien but we don't support that. */ 182833965Sjdp SKIP_WHITESPACE (); 182977298Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer] 183033965Sjdp && *input_line_pointer != '*' 183133965Sjdp && *input_line_pointer != '!') 183260484Sobrien as_warn (_("start address not supported")); 183333965Sjdp } 183433965Sjdp} 183533965Sjdp 183633965Sjdp/* Handle the .err pseudo-op. */ 183733965Sjdp 183833965Sjdpvoid 1839130561Sobriens_err (int ignore ATTRIBUTE_UNUSED) 184033965Sjdp{ 184160484Sobrien as_bad (_(".err encountered")); 184233965Sjdp demand_empty_rest_of_line (); 184333965Sjdp} 184433965Sjdp 1845218822Sdim/* Handle the .error and .warning pseudo-ops. */ 1846218822Sdim 1847218822Sdimvoid 1848218822Sdims_errwarn (int err) 1849218822Sdim{ 1850218822Sdim int len; 1851218822Sdim /* The purpose for the conditional assignment is not to 1852218822Sdim internationalize the directive itself, but that we need a 1853218822Sdim self-contained message, one that can be passed like the 1854218822Sdim demand_copy_C_string return value, and with no assumption on the 1855218822Sdim location of the name of the directive within the message. */ 1856218822Sdim char *msg 1857218822Sdim = (err ? _(".error directive invoked in source file") 1858218822Sdim : _(".warning directive invoked in source file")); 1859218822Sdim 1860218822Sdim if (!is_it_end_of_statement ()) 1861218822Sdim { 1862218822Sdim if (*input_line_pointer != '\"') 1863218822Sdim { 1864218822Sdim as_bad (_("%s argument must be a string"), 1865218822Sdim err ? ".error" : ".warning"); 1866218822Sdim ignore_rest_of_line (); 1867218822Sdim return; 1868218822Sdim } 1869218822Sdim 1870218822Sdim msg = demand_copy_C_string (&len); 1871218822Sdim if (msg == NULL) 1872218822Sdim return; 1873218822Sdim } 1874218822Sdim 1875218822Sdim if (err) 1876218822Sdim as_bad ("%s", msg); 1877218822Sdim else 1878218822Sdim as_warn ("%s", msg); 1879218822Sdim demand_empty_rest_of_line (); 1880218822Sdim} 1881218822Sdim 188233965Sjdp/* Handle the MRI fail pseudo-op. */ 188333965Sjdp 188433965Sjdpvoid 1885130561Sobriens_fail (int ignore ATTRIBUTE_UNUSED) 188633965Sjdp{ 188733965Sjdp offsetT temp; 188833965Sjdp char *stop = NULL; 1889218822Sdim char stopc = 0; 189033965Sjdp 189133965Sjdp if (flag_mri) 189233965Sjdp stop = mri_comment_field (&stopc); 189333965Sjdp 189433965Sjdp temp = get_absolute_expression (); 189533965Sjdp if (temp >= 500) 189660484Sobrien as_warn (_(".fail %ld encountered"), (long) temp); 189733965Sjdp else 189860484Sobrien as_bad (_(".fail %ld encountered"), (long) temp); 189933965Sjdp 190060484Sobrien demand_empty_rest_of_line (); 190160484Sobrien 190233965Sjdp if (flag_mri) 190333965Sjdp mri_comment_end (stop, stopc); 190433965Sjdp} 190533965Sjdp 190677298Sobrienvoid 1907130561Sobriens_fill (int ignore ATTRIBUTE_UNUSED) 190833965Sjdp{ 190938889Sjdp expressionS rep_exp; 191038889Sjdp long size = 1; 191138889Sjdp register long fill = 0; 191233965Sjdp char *p; 191333965Sjdp 191433965Sjdp#ifdef md_flush_pending_output 191533965Sjdp md_flush_pending_output (); 191633965Sjdp#endif 191733965Sjdp 191838889Sjdp get_known_segmented_expression (&rep_exp); 191933965Sjdp if (*input_line_pointer == ',') 192033965Sjdp { 192133965Sjdp input_line_pointer++; 192238889Sjdp size = get_absolute_expression (); 192333965Sjdp if (*input_line_pointer == ',') 192433965Sjdp { 192533965Sjdp input_line_pointer++; 192638889Sjdp fill = get_absolute_expression (); 192733965Sjdp } 192833965Sjdp } 192938889Sjdp 193033965Sjdp /* This is to be compatible with BSD 4.2 AS, not for any rational reason. */ 193133965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8) 193238889Sjdp if (size > BSD_FILL_SIZE_CROCK_8) 193333965Sjdp { 193489857Sobrien as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8); 193538889Sjdp size = BSD_FILL_SIZE_CROCK_8; 193633965Sjdp } 193738889Sjdp if (size < 0) 193833965Sjdp { 193989857Sobrien as_warn (_("size negative; .fill ignored")); 194038889Sjdp size = 0; 194133965Sjdp } 194238889Sjdp else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0) 194333965Sjdp { 194438889Sjdp if (rep_exp.X_add_number < 0) 194589857Sobrien as_warn (_("repeat < 0; .fill ignored")); 194638889Sjdp size = 0; 194733965Sjdp } 194833965Sjdp 194938889Sjdp if (size && !need_pass_2) 195033965Sjdp { 195138889Sjdp if (rep_exp.X_op == O_constant) 195238889Sjdp { 195338889Sjdp p = frag_var (rs_fill, (int) size, (int) size, 195438889Sjdp (relax_substateT) 0, (symbolS *) 0, 195538889Sjdp (offsetT) rep_exp.X_add_number, 195638889Sjdp (char *) 0); 195738889Sjdp } 195838889Sjdp else 195938889Sjdp { 196038889Sjdp /* We don't have a constant repeat count, so we can't use 196138889Sjdp rs_fill. We can get the same results out of rs_space, 196238889Sjdp but its argument is in bytes, so we must multiply the 196338889Sjdp repeat count by size. */ 196438889Sjdp 196538889Sjdp symbolS *rep_sym; 196638889Sjdp rep_sym = make_expr_symbol (&rep_exp); 196738889Sjdp if (size != 1) 196838889Sjdp { 196938889Sjdp expressionS size_exp; 197038889Sjdp size_exp.X_op = O_constant; 197138889Sjdp size_exp.X_add_number = size; 197238889Sjdp 197338889Sjdp rep_exp.X_op = O_multiply; 197438889Sjdp rep_exp.X_add_symbol = rep_sym; 197538889Sjdp rep_exp.X_op_symbol = make_expr_symbol (&size_exp); 197638889Sjdp rep_exp.X_add_number = 0; 197738889Sjdp rep_sym = make_expr_symbol (&rep_exp); 197838889Sjdp } 197938889Sjdp 198038889Sjdp p = frag_var (rs_space, (int) size, (int) size, 198138889Sjdp (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0); 198238889Sjdp } 198377298Sobrien 198438889Sjdp memset (p, 0, (unsigned int) size); 198577298Sobrien 198633965Sjdp /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX 1987130561Sobrien flavoured AS. The following bizarre behaviour is to be 1988130561Sobrien compatible with above. I guess they tried to take up to 8 1989130561Sobrien bytes from a 4-byte expression and they forgot to sign 1990130561Sobrien extend. */ 199133965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4) 199238889Sjdp md_number_to_chars (p, (valueT) fill, 199338889Sjdp (size > BSD_FILL_SIZE_CROCK_4 199433965Sjdp ? BSD_FILL_SIZE_CROCK_4 199538889Sjdp : (int) size)); 199633965Sjdp /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) 1997130561Sobrien but emits no error message because it seems a legal thing to do. 1998130561Sobrien It is a degenerate case of .fill but could be emitted by a 199977298Sobrien compiler. */ 200033965Sjdp } 200133965Sjdp demand_empty_rest_of_line (); 200233965Sjdp} 200333965Sjdp 200477298Sobrienvoid 2005130561Sobriens_globl (int ignore ATTRIBUTE_UNUSED) 200633965Sjdp{ 200733965Sjdp char *name; 200833965Sjdp int c; 200933965Sjdp symbolS *symbolP; 201033965Sjdp char *stop = NULL; 2011218822Sdim char stopc = 0; 201233965Sjdp 201333965Sjdp if (flag_mri) 201433965Sjdp stop = mri_comment_field (&stopc); 201533965Sjdp 201633965Sjdp do 201733965Sjdp { 201833965Sjdp name = input_line_pointer; 201933965Sjdp c = get_symbol_end (); 202033965Sjdp symbolP = symbol_find_or_make (name); 202160484Sobrien S_SET_EXTERNAL (symbolP); 202260484Sobrien 202333965Sjdp *input_line_pointer = c; 202433965Sjdp SKIP_WHITESPACE (); 202560484Sobrien c = *input_line_pointer; 202633965Sjdp if (c == ',') 202733965Sjdp { 202833965Sjdp input_line_pointer++; 202933965Sjdp SKIP_WHITESPACE (); 203089857Sobrien if (is_end_of_line[(unsigned char) *input_line_pointer]) 203133965Sjdp c = '\n'; 203233965Sjdp } 203333965Sjdp } 203433965Sjdp while (c == ','); 203533965Sjdp 203660484Sobrien demand_empty_rest_of_line (); 203760484Sobrien 203833965Sjdp if (flag_mri) 203933965Sjdp mri_comment_end (stop, stopc); 204033965Sjdp} 204133965Sjdp 2042218822Sdim#ifdef OBJ_ELF 2043218822Sdim#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0) 2044218822Sdim 2045218822Sdimstatic inline int 2046218822Sdimskip_past_char (char ** str, char c) 2047218822Sdim{ 2048218822Sdim if (**str == c) 2049218822Sdim { 2050218822Sdim (*str)++; 2051218822Sdim return 0; 2052218822Sdim } 2053218822Sdim else 2054218822Sdim return -1; 2055218822Sdim} 2056218822Sdim#define skip_past_comma(str) skip_past_char (str, ',') 2057218822Sdim 2058218822Sdim/* Parse an attribute directive for VENDOR. */ 2059218822Sdimvoid 2060218822Sdims_vendor_attribute (int vendor) 2061218822Sdim{ 2062218822Sdim expressionS exp; 2063218822Sdim int type; 2064218822Sdim int tag; 2065218822Sdim unsigned int i = 0; 2066218822Sdim char *s = NULL; 2067218822Sdim char saved_char; 2068218822Sdim 2069218822Sdim expression (& exp); 2070218822Sdim if (exp.X_op != O_constant) 2071218822Sdim goto bad; 2072218822Sdim 2073218822Sdim tag = exp.X_add_number; 2074218822Sdim type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag); 2075218822Sdim 2076218822Sdim if (skip_past_comma (&input_line_pointer) == -1) 2077218822Sdim goto bad; 2078218822Sdim if (type & 1) 2079218822Sdim { 2080218822Sdim expression (& exp); 2081218822Sdim if (exp.X_op != O_constant) 2082218822Sdim { 2083218822Sdim as_bad (_("expected numeric constant")); 2084218822Sdim ignore_rest_of_line (); 2085218822Sdim return; 2086218822Sdim } 2087218822Sdim i = exp.X_add_number; 2088218822Sdim } 2089218822Sdim if (type == 3 2090218822Sdim && skip_past_comma (&input_line_pointer) == -1) 2091218822Sdim { 2092218822Sdim as_bad (_("expected comma")); 2093218822Sdim ignore_rest_of_line (); 2094218822Sdim return; 2095218822Sdim } 2096218822Sdim if (type & 2) 2097218822Sdim { 2098218822Sdim skip_whitespace(input_line_pointer); 2099218822Sdim if (*input_line_pointer != '"') 2100218822Sdim goto bad_string; 2101218822Sdim input_line_pointer++; 2102218822Sdim s = input_line_pointer; 2103218822Sdim while (*input_line_pointer && *input_line_pointer != '"') 2104218822Sdim input_line_pointer++; 2105218822Sdim if (*input_line_pointer != '"') 2106218822Sdim goto bad_string; 2107218822Sdim saved_char = *input_line_pointer; 2108218822Sdim *input_line_pointer = 0; 2109218822Sdim } 2110218822Sdim else 2111218822Sdim { 2112218822Sdim s = NULL; 2113218822Sdim saved_char = 0; 2114218822Sdim } 2115218822Sdim 2116218822Sdim switch (type) 2117218822Sdim { 2118218822Sdim case 3: 2119218822Sdim bfd_elf_add_obj_attr_compat (stdoutput, vendor, i, s); 2120218822Sdim break; 2121218822Sdim case 2: 2122218822Sdim bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s); 2123218822Sdim break; 2124218822Sdim case 1: 2125218822Sdim bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i); 2126218822Sdim break; 2127218822Sdim default: 2128218822Sdim abort (); 2129218822Sdim } 2130218822Sdim 2131218822Sdim if (s) 2132218822Sdim { 2133218822Sdim *input_line_pointer = saved_char; 2134218822Sdim input_line_pointer++; 2135218822Sdim } 2136218822Sdim demand_empty_rest_of_line (); 2137218822Sdim return; 2138218822Sdimbad_string: 2139218822Sdim as_bad (_("bad string constant")); 2140218822Sdim ignore_rest_of_line (); 2141218822Sdim return; 2142218822Sdimbad: 2143218822Sdim as_bad (_("expected <tag> , <value>")); 2144218822Sdim ignore_rest_of_line (); 2145218822Sdim} 2146218822Sdim 2147218822Sdim/* Parse a .gnu_attribute directive. */ 2148218822Sdim 2149218822Sdimstatic void 2150218822Sdims_gnu_attribute (int ignored ATTRIBUTE_UNUSED) 2151218822Sdim{ 2152218822Sdim s_vendor_attribute (OBJ_ATTR_GNU); 2153218822Sdim} 2154218822Sdim#endif /* OBJ_ELF */ 2155218822Sdim 215633965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops. */ 215733965Sjdp 215833965Sjdpvoid 2159130561Sobriens_irp (int irpc) 216033965Sjdp{ 2161218822Sdim char *file, *eol; 216233965Sjdp unsigned int line; 216333965Sjdp sb s; 216433965Sjdp const char *err; 216533965Sjdp sb out; 216633965Sjdp 216733965Sjdp as_where (&file, &line); 216833965Sjdp 216933965Sjdp sb_new (&s); 2170218822Sdim eol = find_end_of_line (input_line_pointer, 0); 2171218822Sdim sb_add_buffer (&s, input_line_pointer, eol - input_line_pointer); 2172218822Sdim input_line_pointer = eol; 217333965Sjdp 217433965Sjdp sb_new (&out); 217533965Sjdp 2176130561Sobrien err = expand_irp (irpc, 0, &s, &out, get_line_sb); 217733965Sjdp if (err != NULL) 217833965Sjdp as_bad_where (file, line, "%s", err); 217933965Sjdp 218033965Sjdp sb_kill (&s); 218133965Sjdp 218260484Sobrien input_scrub_include_sb (&out, input_line_pointer, 1); 218333965Sjdp sb_kill (&out); 218433965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 218533965Sjdp} 218633965Sjdp 218733965Sjdp/* Handle the .linkonce pseudo-op. This tells the assembler to mark 218833965Sjdp the section to only be linked once. However, this is not supported 218933965Sjdp by most object file formats. This takes an optional argument, 219033965Sjdp which is what to do about duplicates. */ 219133965Sjdp 219233965Sjdpvoid 2193130561Sobriens_linkonce (int ignore ATTRIBUTE_UNUSED) 219433965Sjdp{ 219533965Sjdp enum linkonce_type type; 219633965Sjdp 219733965Sjdp SKIP_WHITESPACE (); 219833965Sjdp 219933965Sjdp type = LINKONCE_DISCARD; 220033965Sjdp 220177298Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer]) 220233965Sjdp { 220333965Sjdp char *s; 220433965Sjdp char c; 220533965Sjdp 220633965Sjdp s = input_line_pointer; 220733965Sjdp c = get_symbol_end (); 220833965Sjdp if (strcasecmp (s, "discard") == 0) 220933965Sjdp type = LINKONCE_DISCARD; 221033965Sjdp else if (strcasecmp (s, "one_only") == 0) 221133965Sjdp type = LINKONCE_ONE_ONLY; 221233965Sjdp else if (strcasecmp (s, "same_size") == 0) 221333965Sjdp type = LINKONCE_SAME_SIZE; 221433965Sjdp else if (strcasecmp (s, "same_contents") == 0) 221533965Sjdp type = LINKONCE_SAME_CONTENTS; 221633965Sjdp else 221760484Sobrien as_warn (_("unrecognized .linkonce type `%s'"), s); 221833965Sjdp 221933965Sjdp *input_line_pointer = c; 222033965Sjdp } 222133965Sjdp 222233965Sjdp#ifdef obj_handle_link_once 222333965Sjdp obj_handle_link_once (type); 222433965Sjdp#else /* ! defined (obj_handle_link_once) */ 222533965Sjdp { 222633965Sjdp flagword flags; 222733965Sjdp 222833965Sjdp if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0) 222960484Sobrien as_warn (_(".linkonce is not supported for this object file format")); 223033965Sjdp 223133965Sjdp flags = bfd_get_section_flags (stdoutput, now_seg); 223233965Sjdp flags |= SEC_LINK_ONCE; 223333965Sjdp switch (type) 223433965Sjdp { 223533965Sjdp default: 223633965Sjdp abort (); 223733965Sjdp case LINKONCE_DISCARD: 223833965Sjdp flags |= SEC_LINK_DUPLICATES_DISCARD; 223933965Sjdp break; 224033965Sjdp case LINKONCE_ONE_ONLY: 224133965Sjdp flags |= SEC_LINK_DUPLICATES_ONE_ONLY; 224233965Sjdp break; 224333965Sjdp case LINKONCE_SAME_SIZE: 224433965Sjdp flags |= SEC_LINK_DUPLICATES_SAME_SIZE; 224533965Sjdp break; 224633965Sjdp case LINKONCE_SAME_CONTENTS: 224733965Sjdp flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS; 224833965Sjdp break; 224933965Sjdp } 225077298Sobrien if (!bfd_set_section_flags (stdoutput, now_seg, flags)) 225160484Sobrien as_bad (_("bfd_set_section_flags: %s"), 225233965Sjdp bfd_errmsg (bfd_get_error ())); 225333965Sjdp } 225433965Sjdp#endif /* ! defined (obj_handle_link_once) */ 225533965Sjdp 225633965Sjdp demand_empty_rest_of_line (); 225733965Sjdp} 225833965Sjdp 2259130561Sobrienvoid 2260130561Sobrienbss_alloc (symbolS *symbolP, addressT size, int align) 226133965Sjdp{ 2262130561Sobrien char *pfrag; 226333965Sjdp segT current_seg = now_seg; 226433965Sjdp subsegT current_subseg = now_subseg; 226533965Sjdp segT bss_seg = bss_section; 226633965Sjdp 226733965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA) 226833965Sjdp if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour 226933965Sjdp || OUTPUT_FLAVOR == bfd_target_elf_flavour) 227033965Sjdp { 227133965Sjdp /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */ 2272130561Sobrien if (size <= bfd_get_gp_size (stdoutput)) 227333965Sjdp { 227433965Sjdp bss_seg = subseg_new (".sbss", 1); 227533965Sjdp seg_info (bss_seg)->bss = 1; 227677298Sobrien if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) 227760484Sobrien as_warn (_("error setting flags for \".sbss\": %s"), 227833965Sjdp bfd_errmsg (bfd_get_error ())); 227933965Sjdp } 228033965Sjdp } 228133965Sjdp#endif 2282130561Sobrien subseg_set (bss_seg, 1); 228360484Sobrien 2284130561Sobrien if (align) 228577298Sobrien { 2286130561Sobrien record_alignment (bss_seg, align); 2287130561Sobrien frag_align (align, 0, 0); 228877298Sobrien } 228933965Sjdp 2290130561Sobrien /* Detach from old frag. */ 2291130561Sobrien if (S_GET_SEGMENT (symbolP) == bss_seg) 2292130561Sobrien symbol_get_frag (symbolP)->fr_symbol = NULL; 229377298Sobrien 2294130561Sobrien symbol_set_frag (symbolP, frag_now); 2295130561Sobrien pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL); 2296130561Sobrien *pfrag = 0; 229777298Sobrien 2298130561Sobrien#ifdef S_SET_SIZE 2299130561Sobrien S_SET_SIZE (symbolP, size); 2300130561Sobrien#endif 2301130561Sobrien S_SET_SEGMENT (symbolP, bss_seg); 230277298Sobrien 2303130561Sobrien#ifdef OBJ_COFF 2304130561Sobrien /* The symbol may already have been created with a preceding 2305130561Sobrien ".globl" directive -- be careful not to step on storage class 2306130561Sobrien in that case. Otherwise, set it to static. */ 2307130561Sobrien if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 2308130561Sobrien S_SET_STORAGE_CLASS (symbolP, C_STAT); 2309130561Sobrien#endif /* OBJ_COFF */ 231077298Sobrien 2311130561Sobrien subseg_set (current_seg, current_subseg); 2312130561Sobrien} 231377298Sobrien 2314130561SobrienoffsetT 2315130561Sobrienparse_align (int align_bytes) 2316130561Sobrien{ 2317130561Sobrien expressionS exp; 2318130561Sobrien addressT align; 231938889Sjdp 2320130561Sobrien SKIP_WHITESPACE (); 2321130561Sobrien if (*input_line_pointer != ',') 2322130561Sobrien { 2323130561Sobrien no_align: 2324130561Sobrien as_bad (_("expected alignment after size")); 2325130561Sobrien ignore_rest_of_line (); 2326130561Sobrien return -1; 2327130561Sobrien } 232877298Sobrien 2329130561Sobrien input_line_pointer++; 2330130561Sobrien SKIP_WHITESPACE (); 233177298Sobrien 2332130561Sobrien align = get_absolute_expr (&exp); 2333130561Sobrien if (exp.X_op == O_absent) 2334130561Sobrien goto no_align; 2335130561Sobrien 2336130561Sobrien if (!exp.X_unsigned) 2337130561Sobrien { 2338130561Sobrien as_warn (_("alignment negative; 0 assumed")); 2339130561Sobrien align = 0; 234077298Sobrien } 2341130561Sobrien 2342130561Sobrien if (align_bytes && align != 0) 234333965Sjdp { 2344130561Sobrien /* convert to a power of 2 alignment */ 2345130561Sobrien unsigned int alignp2 = 0; 2346130561Sobrien while ((align & 1) == 0) 2347130561Sobrien align >>= 1, ++alignp2; 2348130561Sobrien if (align != 1) 234933965Sjdp { 2350130561Sobrien as_bad (_("alignment not a power of 2")); 2351130561Sobrien ignore_rest_of_line (); 2352130561Sobrien return -1; 235333965Sjdp } 2354130561Sobrien align = alignp2; 235533965Sjdp } 2356130561Sobrien return align; 2357130561Sobrien} 235833965Sjdp 2359130561Sobrien/* Called from s_comm_internal after symbol name and size have been 2360130561Sobrien parsed. NEEDS_ALIGN is 0 if it was an ".lcomm" (2 args only), 2361130561Sobrien 1 if this was a ".bss" directive which has a 3rd argument 2362130561Sobrien (alignment as a power of 2), or 2 if this was a ".bss" directive 2363130561Sobrien with alignment in bytes. */ 236433965Sjdp 2365130561SobriensymbolS * 2366130561Sobriens_lcomm_internal (int needs_align, symbolS *symbolP, addressT size) 2367130561Sobrien{ 2368130561Sobrien addressT align = 0; 2369130561Sobrien 2370130561Sobrien if (needs_align) 237133965Sjdp { 2372130561Sobrien align = parse_align (needs_align - 1); 2373130561Sobrien if (align == (addressT) -1) 2374130561Sobrien return NULL; 237533965Sjdp } 237633965Sjdp else 2377130561Sobrien /* Assume some objects may require alignment on some systems. */ 2378130561Sobrien TC_IMPLICIT_LCOMM_ALIGNMENT (size, align); 237933965Sjdp 2380130561Sobrien bss_alloc (symbolP, size, align); 2381130561Sobrien return symbolP; 238277298Sobrien} 238333965Sjdp 238438889Sjdpvoid 2385130561Sobriens_lcomm (int needs_align) 238638889Sjdp{ 2387130561Sobrien s_comm_internal (needs_align, s_lcomm_internal); 238838889Sjdp} 238938889Sjdp 239077298Sobrienvoid 2391130561Sobriens_lcomm_bytes (int needs_align) 239238889Sjdp{ 2393130561Sobrien s_comm_internal (needs_align * 2, s_lcomm_internal); 239438889Sjdp} 239538889Sjdp 239677298Sobrienvoid 2397130561Sobriens_lsym (int ignore ATTRIBUTE_UNUSED) 239833965Sjdp{ 239933965Sjdp register char *name; 240033965Sjdp register char c; 240133965Sjdp register char *p; 240233965Sjdp expressionS exp; 240333965Sjdp register symbolS *symbolP; 240433965Sjdp 240577298Sobrien /* We permit ANY defined expression: BSD4.2 demands constants. */ 240633965Sjdp name = input_line_pointer; 240733965Sjdp c = get_symbol_end (); 240833965Sjdp p = input_line_pointer; 240933965Sjdp *p = c; 241089857Sobrien 241189857Sobrien if (name == p) 241289857Sobrien { 241389857Sobrien as_bad (_("expected symbol name")); 2414218822Sdim ignore_rest_of_line (); 241589857Sobrien return; 241689857Sobrien } 241789857Sobrien 241833965Sjdp SKIP_WHITESPACE (); 241977298Sobrien 242033965Sjdp if (*input_line_pointer != ',') 242133965Sjdp { 242233965Sjdp *p = 0; 242389857Sobrien as_bad (_("expected comma after \"%s\""), name); 242433965Sjdp *p = c; 242533965Sjdp ignore_rest_of_line (); 242633965Sjdp return; 242733965Sjdp } 242877298Sobrien 242933965Sjdp input_line_pointer++; 2430218822Sdim expression_and_evaluate (&exp); 243177298Sobrien 243233965Sjdp if (exp.X_op != O_constant 243333965Sjdp && exp.X_op != O_register) 243433965Sjdp { 243560484Sobrien as_bad (_("bad expression")); 243633965Sjdp ignore_rest_of_line (); 243733965Sjdp return; 243833965Sjdp } 243977298Sobrien 244033965Sjdp *p = 0; 244133965Sjdp symbolP = symbol_find_or_make (name); 244233965Sjdp 2443218822Sdim if (S_GET_SEGMENT (symbolP) == undefined_section) 244433965Sjdp { 244533965Sjdp /* The name might be an undefined .global symbol; be sure to 244677298Sobrien keep the "external" bit. */ 244733965Sjdp S_SET_SEGMENT (symbolP, 244833965Sjdp (exp.X_op == O_constant 244933965Sjdp ? absolute_section 245033965Sjdp : reg_section)); 245133965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 245233965Sjdp } 245333965Sjdp else 245433965Sjdp { 245589857Sobrien as_bad (_("symbol `%s' is already defined"), name); 245633965Sjdp } 245777298Sobrien 245833965Sjdp *p = c; 245933965Sjdp demand_empty_rest_of_line (); 246077298Sobrien} 246133965Sjdp 2462130561Sobrien/* Read a line into an sb. Returns the character that ended the line 2463130561Sobrien or zero if there are no more lines. */ 246433965Sjdp 246533965Sjdpstatic int 2466130561Sobrienget_line_sb (sb *line) 246733965Sjdp{ 2468218822Sdim char *eol; 246933965Sjdp 247033965Sjdp if (input_line_pointer[-1] == '\n') 247133965Sjdp bump_line_counters (); 247233965Sjdp 247333965Sjdp if (input_line_pointer >= buffer_limit) 247433965Sjdp { 247533965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 247633965Sjdp if (buffer_limit == 0) 247733965Sjdp return 0; 247833965Sjdp } 247933965Sjdp 2480218822Sdim eol = find_end_of_line (input_line_pointer, flag_m68k_mri); 2481218822Sdim sb_add_buffer (line, input_line_pointer, eol - input_line_pointer); 2482218822Sdim input_line_pointer = eol; 248333965Sjdp 2484130561Sobrien /* Don't skip multiple end-of-line characters, because that breaks support 2485130561Sobrien for the IA-64 stop bit (;;) which looks like two consecutive end-of-line 2486130561Sobrien characters but isn't. Instead just skip one end of line character and 2487130561Sobrien return the character skipped so that the caller can re-insert it if 2488130561Sobrien necessary. */ 2489218822Sdim return *input_line_pointer++; 249033965Sjdp} 249133965Sjdp 2492130561Sobrien/* Define a macro. This is an interface to macro.c. */ 249333965Sjdp 249433965Sjdpvoid 2495130561Sobriens_macro (int ignore ATTRIBUTE_UNUSED) 249633965Sjdp{ 2497218822Sdim char *file, *eol; 249833965Sjdp unsigned int line; 249933965Sjdp sb s; 250033965Sjdp const char *err; 250133965Sjdp const char *name; 250233965Sjdp 250333965Sjdp as_where (&file, &line); 250433965Sjdp 250533965Sjdp sb_new (&s); 2506218822Sdim eol = find_end_of_line (input_line_pointer, 0); 2507218822Sdim sb_add_buffer (&s, input_line_pointer, eol - input_line_pointer); 2508218822Sdim input_line_pointer = eol; 250933965Sjdp 251033965Sjdp if (line_label != NULL) 2511218822Sdim { 2512218822Sdim sb label; 251333965Sjdp 2514218822Sdim sb_new (&label); 2515218822Sdim sb_add_string (&label, S_GET_NAME (line_label)); 2516218822Sdim err = define_macro (0, &s, &label, get_line_sb, file, line, &name); 2517218822Sdim sb_kill (&label); 2518218822Sdim } 2519218822Sdim else 2520218822Sdim err = define_macro (0, &s, NULL, get_line_sb, file, line, &name); 252133965Sjdp if (err != NULL) 2522218822Sdim as_bad_where (file, line, err, name); 252333965Sjdp else 252433965Sjdp { 252533965Sjdp if (line_label != NULL) 252633965Sjdp { 2527218822Sdim S_SET_SEGMENT (line_label, absolute_section); 252833965Sjdp S_SET_VALUE (line_label, 0); 252960484Sobrien symbol_set_frag (line_label, &zero_address_frag); 253033965Sjdp } 253133965Sjdp 253260484Sobrien if (((NO_PSEUDO_DOT || flag_m68k_mri) 253333965Sjdp && hash_find (po_hash, name) != NULL) 253477298Sobrien || (!flag_m68k_mri 253533965Sjdp && *name == '.' 253633965Sjdp && hash_find (po_hash, name + 1) != NULL)) 2537218822Sdim as_warn_where (file, 2538218822Sdim line, 2539218822Sdim _("attempt to redefine pseudo-op `%s' ignored"), 254033965Sjdp name); 254133965Sjdp } 254233965Sjdp 254333965Sjdp sb_kill (&s); 254433965Sjdp} 254533965Sjdp 254633965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro 254733965Sjdp expansion. */ 254833965Sjdp 254933965Sjdpvoid 2550130561Sobriens_mexit (int ignore ATTRIBUTE_UNUSED) 255133965Sjdp{ 255233965Sjdp cond_exit_macro (macro_nest); 255333965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 255433965Sjdp} 255533965Sjdp 255633965Sjdp/* Switch in and out of MRI mode. */ 255733965Sjdp 255833965Sjdpvoid 2559130561Sobriens_mri (int ignore ATTRIBUTE_UNUSED) 256033965Sjdp{ 256133965Sjdp int on, old_flag; 256233965Sjdp 256333965Sjdp on = get_absolute_expression (); 256433965Sjdp old_flag = flag_mri; 256533965Sjdp if (on != 0) 256633965Sjdp { 256733965Sjdp flag_mri = 1; 256833965Sjdp#ifdef TC_M68K 256933965Sjdp flag_m68k_mri = 1; 257033965Sjdp#endif 257160484Sobrien macro_mri_mode (1); 257233965Sjdp } 257333965Sjdp else 257433965Sjdp { 257533965Sjdp flag_mri = 0; 257660484Sobrien#ifdef TC_M68K 257733965Sjdp flag_m68k_mri = 0; 257860484Sobrien#endif 257960484Sobrien macro_mri_mode (0); 258033965Sjdp } 258133965Sjdp 258260484Sobrien /* Operator precedence changes in m68k MRI mode, so we need to 258360484Sobrien update the operator rankings. */ 258460484Sobrien expr_set_precedence (); 258560484Sobrien 258633965Sjdp#ifdef MRI_MODE_CHANGE 258733965Sjdp if (on != old_flag) 258833965Sjdp MRI_MODE_CHANGE (on); 258933965Sjdp#endif 259033965Sjdp 259133965Sjdp demand_empty_rest_of_line (); 259233965Sjdp} 259333965Sjdp 259433965Sjdp/* Handle changing the location counter. */ 259533965Sjdp 259633965Sjdpstatic void 2597130561Sobriendo_org (segT segment, expressionS *exp, int fill) 259833965Sjdp{ 259933965Sjdp if (segment != now_seg && segment != absolute_section) 260089857Sobrien as_bad (_("invalid segment \"%s\""), segment_name (segment)); 260133965Sjdp 260233965Sjdp if (now_seg == absolute_section) 260333965Sjdp { 260433965Sjdp if (fill != 0) 260560484Sobrien as_warn (_("ignoring fill value in absolute section")); 260633965Sjdp if (exp->X_op != O_constant) 260733965Sjdp { 260860484Sobrien as_bad (_("only constant offsets supported in absolute section")); 260933965Sjdp exp->X_add_number = 0; 261033965Sjdp } 261133965Sjdp abs_section_offset = exp->X_add_number; 261233965Sjdp } 261333965Sjdp else 261433965Sjdp { 261533965Sjdp char *p; 261678828Sobrien symbolS *sym = exp->X_add_symbol; 261778828Sobrien offsetT off = exp->X_add_number * OCTETS_PER_BYTE; 261833965Sjdp 261978828Sobrien if (exp->X_op != O_constant && exp->X_op != O_symbol) 262078828Sobrien { 262178828Sobrien /* Handle complex expressions. */ 262278828Sobrien sym = make_expr_symbol (exp); 262378828Sobrien off = 0; 262478828Sobrien } 262578828Sobrien 262678828Sobrien p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0); 262733965Sjdp *p = fill; 262833965Sjdp } 262933965Sjdp} 263033965Sjdp 263177298Sobrienvoid 2632130561Sobriens_org (int ignore ATTRIBUTE_UNUSED) 263333965Sjdp{ 263433965Sjdp register segT segment; 263533965Sjdp expressionS exp; 263633965Sjdp register long temp_fill; 263733965Sjdp 263860484Sobrien#ifdef md_flush_pending_output 263960484Sobrien md_flush_pending_output (); 264060484Sobrien#endif 264160484Sobrien 264233965Sjdp /* The m68k MRI assembler has a different meaning for .org. It 264333965Sjdp means to create an absolute section at a given address. We can't 264433965Sjdp support that--use a linker script instead. */ 264533965Sjdp if (flag_m68k_mri) 264633965Sjdp { 264760484Sobrien as_bad (_("MRI style ORG pseudo-op not supported")); 264833965Sjdp ignore_rest_of_line (); 264933965Sjdp return; 265033965Sjdp } 265133965Sjdp 265233965Sjdp /* Don't believe the documentation of BSD 4.2 AS. There is no such 265333965Sjdp thing as a sub-segment-relative origin. Any absolute origin is 265433965Sjdp given a warning, then assumed to be segment-relative. Any 265533965Sjdp segmented origin expression ("foo+42") had better be in the right 265633965Sjdp segment or the .org is ignored. 265733965Sjdp 265833965Sjdp BSD 4.2 AS warns if you try to .org backwards. We cannot because 265933965Sjdp we never know sub-segment sizes when we are reading code. BSD 266033965Sjdp will crash trying to emit negative numbers of filler bytes in 266133965Sjdp certain .orgs. We don't crash, but see as-write for that code. 266233965Sjdp 266333965Sjdp Don't make frag if need_pass_2==1. */ 266433965Sjdp segment = get_known_segmented_expression (&exp); 266533965Sjdp if (*input_line_pointer == ',') 266633965Sjdp { 266733965Sjdp input_line_pointer++; 266833965Sjdp temp_fill = get_absolute_expression (); 266933965Sjdp } 267033965Sjdp else 267133965Sjdp temp_fill = 0; 267233965Sjdp 267333965Sjdp if (!need_pass_2) 267433965Sjdp do_org (segment, &exp, temp_fill); 267533965Sjdp 267633965Sjdp demand_empty_rest_of_line (); 267777298Sobrien} 267833965Sjdp 267933965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op. This should be 268033965Sjdp called by the obj-format routine which handles section changing 268133965Sjdp when in MRI mode. It will create a new section, and return it. It 268233965Sjdp will set *TYPE to the section type: one of 'C' (code), 'D' (data), 2683218822Sdim 'M' (mixed), or 'R' (romable). The flags will be set in the section. */ 268433965Sjdp 268533965Sjdpvoid 2686130561Sobriens_mri_sect (char *type ATTRIBUTE_UNUSED) 268733965Sjdp{ 268833965Sjdp#ifdef TC_M68K 268933965Sjdp 269033965Sjdp char *name; 269133965Sjdp char c; 269233965Sjdp segT seg; 269333965Sjdp 269433965Sjdp SKIP_WHITESPACE (); 269577298Sobrien 269633965Sjdp name = input_line_pointer; 269789857Sobrien if (!ISDIGIT (*name)) 269833965Sjdp c = get_symbol_end (); 269933965Sjdp else 270033965Sjdp { 270133965Sjdp do 270233965Sjdp { 270333965Sjdp ++input_line_pointer; 270433965Sjdp } 270589857Sobrien while (ISDIGIT (*input_line_pointer)); 270677298Sobrien 270733965Sjdp c = *input_line_pointer; 270833965Sjdp *input_line_pointer = '\0'; 270933965Sjdp } 271033965Sjdp 271133965Sjdp name = xstrdup (name); 271233965Sjdp 271333965Sjdp *input_line_pointer = c; 271433965Sjdp 271533965Sjdp seg = subseg_new (name, 0); 271633965Sjdp 271733965Sjdp if (*input_line_pointer == ',') 271833965Sjdp { 271933965Sjdp int align; 272033965Sjdp 272133965Sjdp ++input_line_pointer; 272233965Sjdp align = get_absolute_expression (); 272333965Sjdp record_alignment (seg, align); 272433965Sjdp } 272533965Sjdp 272633965Sjdp *type = 'C'; 272733965Sjdp if (*input_line_pointer == ',') 272833965Sjdp { 272933965Sjdp c = *++input_line_pointer; 273089857Sobrien c = TOUPPER (c); 273133965Sjdp if (c == 'C' || c == 'D' || c == 'M' || c == 'R') 273233965Sjdp *type = c; 273333965Sjdp else 273460484Sobrien as_bad (_("unrecognized section type")); 273533965Sjdp ++input_line_pointer; 273633965Sjdp 273733965Sjdp { 273833965Sjdp flagword flags; 273933965Sjdp 274033965Sjdp flags = SEC_NO_FLAGS; 274133965Sjdp if (*type == 'C') 274233965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE; 274333965Sjdp else if (*type == 'D' || *type == 'M') 274433965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_DATA; 274533965Sjdp else if (*type == 'R') 274633965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM; 274733965Sjdp if (flags != SEC_NO_FLAGS) 274833965Sjdp { 274977298Sobrien if (!bfd_set_section_flags (stdoutput, seg, flags)) 275060484Sobrien as_warn (_("error setting flags for \"%s\": %s"), 275133965Sjdp bfd_section_name (stdoutput, seg), 275233965Sjdp bfd_errmsg (bfd_get_error ())); 275333965Sjdp } 275433965Sjdp } 275533965Sjdp } 275633965Sjdp 275733965Sjdp /* Ignore the HP type. */ 275833965Sjdp if (*input_line_pointer == ',') 275933965Sjdp input_line_pointer += 2; 276033965Sjdp 276133965Sjdp demand_empty_rest_of_line (); 276233965Sjdp 276333965Sjdp#else /* ! TC_M68K */ 276433965Sjdp#ifdef TC_I960 276533965Sjdp 276633965Sjdp char *name; 276733965Sjdp char c; 276833965Sjdp segT seg; 276933965Sjdp 277033965Sjdp SKIP_WHITESPACE (); 277133965Sjdp 277233965Sjdp name = input_line_pointer; 277333965Sjdp c = get_symbol_end (); 277433965Sjdp 277533965Sjdp name = xstrdup (name); 277633965Sjdp 277733965Sjdp *input_line_pointer = c; 277833965Sjdp 277933965Sjdp seg = subseg_new (name, 0); 278033965Sjdp 278133965Sjdp if (*input_line_pointer != ',') 278233965Sjdp *type = 'C'; 278333965Sjdp else 278433965Sjdp { 278533965Sjdp char *sectype; 278633965Sjdp 278733965Sjdp ++input_line_pointer; 278833965Sjdp SKIP_WHITESPACE (); 278933965Sjdp sectype = input_line_pointer; 279033965Sjdp c = get_symbol_end (); 279133965Sjdp if (*sectype == '\0') 279233965Sjdp *type = 'C'; 279333965Sjdp else if (strcasecmp (sectype, "text") == 0) 279433965Sjdp *type = 'C'; 279533965Sjdp else if (strcasecmp (sectype, "data") == 0) 279633965Sjdp *type = 'D'; 279733965Sjdp else if (strcasecmp (sectype, "romdata") == 0) 279833965Sjdp *type = 'R'; 279933965Sjdp else 280060484Sobrien as_warn (_("unrecognized section type `%s'"), sectype); 280133965Sjdp *input_line_pointer = c; 280233965Sjdp } 280333965Sjdp 280433965Sjdp if (*input_line_pointer == ',') 280533965Sjdp { 280633965Sjdp char *seccmd; 280733965Sjdp 280833965Sjdp ++input_line_pointer; 280933965Sjdp SKIP_WHITESPACE (); 281033965Sjdp seccmd = input_line_pointer; 281133965Sjdp c = get_symbol_end (); 281233965Sjdp if (strcasecmp (seccmd, "absolute") == 0) 281333965Sjdp { 281460484Sobrien as_bad (_("absolute sections are not supported")); 281533965Sjdp *input_line_pointer = c; 281633965Sjdp ignore_rest_of_line (); 281733965Sjdp return; 281833965Sjdp } 281933965Sjdp else if (strcasecmp (seccmd, "align") == 0) 282033965Sjdp { 282133965Sjdp int align; 282233965Sjdp 282333965Sjdp *input_line_pointer = c; 282433965Sjdp align = get_absolute_expression (); 282533965Sjdp record_alignment (seg, align); 282633965Sjdp } 282733965Sjdp else 282833965Sjdp { 282960484Sobrien as_warn (_("unrecognized section command `%s'"), seccmd); 283033965Sjdp *input_line_pointer = c; 283133965Sjdp } 283233965Sjdp } 283333965Sjdp 283477298Sobrien demand_empty_rest_of_line (); 283533965Sjdp 283633965Sjdp#else /* ! TC_I960 */ 283733965Sjdp /* The MRI assembler seems to use different forms of .sect for 283833965Sjdp different targets. */ 283960484Sobrien as_bad ("MRI mode not supported for this target"); 284060484Sobrien ignore_rest_of_line (); 284133965Sjdp#endif /* ! TC_I960 */ 284233965Sjdp#endif /* ! TC_M68K */ 284333965Sjdp} 284433965Sjdp 284533965Sjdp/* Handle the .print pseudo-op. */ 284633965Sjdp 284733965Sjdpvoid 2848130561Sobriens_print (int ignore ATTRIBUTE_UNUSED) 284933965Sjdp{ 285033965Sjdp char *s; 285133965Sjdp int len; 285233965Sjdp 285333965Sjdp s = demand_copy_C_string (&len); 2854130561Sobrien if (s != NULL) 2855130561Sobrien printf ("%s\n", s); 285633965Sjdp demand_empty_rest_of_line (); 285733965Sjdp} 285833965Sjdp 285933965Sjdp/* Handle the .purgem pseudo-op. */ 286033965Sjdp 286133965Sjdpvoid 2862130561Sobriens_purgem (int ignore ATTRIBUTE_UNUSED) 286333965Sjdp{ 286433965Sjdp if (is_it_end_of_statement ()) 286533965Sjdp { 286633965Sjdp demand_empty_rest_of_line (); 286733965Sjdp return; 286833965Sjdp } 286933965Sjdp 287033965Sjdp do 287133965Sjdp { 287233965Sjdp char *name; 287333965Sjdp char c; 287433965Sjdp 287533965Sjdp SKIP_WHITESPACE (); 287633965Sjdp name = input_line_pointer; 287733965Sjdp c = get_symbol_end (); 287833965Sjdp delete_macro (name); 287933965Sjdp *input_line_pointer = c; 288033965Sjdp SKIP_WHITESPACE (); 288133965Sjdp } 288233965Sjdp while (*input_line_pointer++ == ','); 288333965Sjdp 288433965Sjdp --input_line_pointer; 288533965Sjdp demand_empty_rest_of_line (); 288633965Sjdp} 288733965Sjdp 2888218822Sdim/* Handle the .endm/.endr pseudo-ops. */ 288933965Sjdp 2890218822Sdimstatic void 2891218822Sdims_bad_end (int endr) 289289857Sobrien{ 2893218822Sdim as_warn (_(".end%c encountered without preceeding %s"), 2894218822Sdim endr ? 'r' : 'm', 2895218822Sdim endr ? ".rept, .irp, or .irpc" : ".macro"); 289689857Sobrien demand_empty_rest_of_line (); 289789857Sobrien} 289889857Sobrien 289989857Sobrien/* Handle the .rept pseudo-op. */ 290089857Sobrien 290189857Sobrienvoid 2902130561Sobriens_rept (int ignore ATTRIBUTE_UNUSED) 290333965Sjdp{ 290433965Sjdp int count; 290560484Sobrien 290660484Sobrien count = get_absolute_expression (); 290760484Sobrien 290877298Sobrien do_repeat (count, "REPT", "ENDR"); 290960484Sobrien} 291060484Sobrien 291160484Sobrien/* This function provides a generic repeat block implementation. It allows 291277298Sobrien different directives to be used as the start/end keys. */ 291360484Sobrien 291460484Sobrienvoid 2915130561Sobriendo_repeat (int count, const char *start, const char *end) 291660484Sobrien{ 291733965Sjdp sb one; 291833965Sjdp sb many; 291933965Sjdp 292033965Sjdp sb_new (&one); 292177298Sobrien if (!buffer_and_nest (start, end, &one, get_line_sb)) 292233965Sjdp { 292360484Sobrien as_bad (_("%s without %s"), start, end); 292433965Sjdp return; 292533965Sjdp } 292633965Sjdp 292733965Sjdp sb_new (&many); 292833965Sjdp while (count-- > 0) 292933965Sjdp sb_add_sb (&many, &one); 293033965Sjdp 293133965Sjdp sb_kill (&one); 293233965Sjdp 293360484Sobrien input_scrub_include_sb (&many, input_line_pointer, 1); 293433965Sjdp sb_kill (&many); 293533965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 293633965Sjdp} 293733965Sjdp 293860484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional 293960484Sobrien input buffers to skip. Assumes that conditionals preceding the loop end 294077298Sobrien are properly nested. 294160484Sobrien 294260484Sobrien This function makes it easier to implement a premature "break" out of the 294360484Sobrien loop. The EXTRA arg accounts for other buffers we might have inserted, 294477298Sobrien such as line substitutions. */ 294560484Sobrien 294660484Sobrienvoid 2947130561Sobrienend_repeat (int extra) 294860484Sobrien{ 294960484Sobrien cond_exit_macro (macro_nest); 295060484Sobrien while (extra-- >= 0) 295160484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 295260484Sobrien} 295360484Sobrien 2954218822Sdimstatic void 2955218822Sdimassign_symbol (char *name, int mode) 295633965Sjdp{ 2957218822Sdim symbolS *symbolP; 295833965Sjdp 295933965Sjdp if (name[0] == '.' && name[1] == '\0') 296033965Sjdp { 296177298Sobrien /* Turn '. = mumble' into a .org mumble. */ 2962218822Sdim segT segment; 296333965Sjdp expressionS exp; 296433965Sjdp 296533965Sjdp segment = get_known_segmented_expression (&exp); 296633965Sjdp 296733965Sjdp if (!need_pass_2) 296833965Sjdp do_org (segment, &exp, 0); 296933965Sjdp 297033965Sjdp return; 297133965Sjdp } 297233965Sjdp 297333965Sjdp if ((symbolP = symbol_find (name)) == NULL 297433965Sjdp && (symbolP = md_undefined_symbol (name)) == NULL) 297533965Sjdp { 2976218822Sdim symbolP = symbol_find_or_make (name); 297738889Sjdp#ifndef NO_LISTING 297838889Sjdp /* When doing symbol listings, play games with dummy fragments living 297938889Sjdp outside the normal fragment chain to record the file and line info 2980130561Sobrien for this symbol. */ 298138889Sjdp if (listing & LISTING_SYMBOLS) 298238889Sjdp { 298338889Sjdp extern struct list_info_struct *listing_tail; 2984218822Sdim fragS *dummy_frag = (fragS *) xcalloc (1, sizeof (fragS)); 298538889Sjdp dummy_frag->line = listing_tail; 298638889Sjdp dummy_frag->fr_symbol = symbolP; 2987218822Sdim symbol_set_frag (symbolP, dummy_frag); 298838889Sjdp } 298938889Sjdp#endif 299033965Sjdp#ifdef OBJ_COFF 299177298Sobrien /* "set" symbols are local unless otherwise specified. */ 299233965Sjdp SF_SET_LOCAL (symbolP); 2993218822Sdim#endif 299477298Sobrien } 299533965Sjdp 2996218822Sdim if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) 2997218822Sdim { 2998218822Sdim /* Permit register names to be redefined. */ 2999218822Sdim if ((mode != 0 || !S_IS_VOLATILE (symbolP)) 3000218822Sdim && S_GET_SEGMENT (symbolP) != reg_section) 3001218822Sdim { 3002218822Sdim as_bad (_("symbol `%s' is already defined"), name); 3003218822Sdim symbolP = symbol_clone (symbolP, 0); 3004218822Sdim } 3005218822Sdim /* If the symbol is volatile, copy the symbol and replace the 3006218822Sdim original with the copy, so that previous uses of the symbol will 3007218822Sdim retain the value of the symbol at the point of use. */ 3008218822Sdim else if (S_IS_VOLATILE (symbolP)) 3009218822Sdim symbolP = symbol_clone (symbolP, 1); 3010218822Sdim } 301133965Sjdp 3012218822Sdim if (mode == 0) 3013218822Sdim S_SET_VOLATILE (symbolP); 3014218822Sdim else if (mode < 0) 3015218822Sdim S_SET_FORWARD_REF (symbolP); 3016218822Sdim 3017218822Sdim pseudo_set (symbolP); 3018218822Sdim} 3019218822Sdim 3020218822Sdim/* Handle the .equ, .equiv, .eqv, and .set directives. If EQUIV is 1, 3021218822Sdim then this is .equiv, and it is an error if the symbol is already 3022218822Sdim defined. If EQUIV is -1, the symbol additionally is a forward 3023218822Sdim reference. */ 3024218822Sdim 3025218822Sdimvoid 3026218822Sdims_set (int equiv) 3027218822Sdim{ 3028218822Sdim char *name; 3029218822Sdim char delim; 3030218822Sdim char *end_name; 3031218822Sdim 3032218822Sdim /* Especial apologies for the random logic: 3033218822Sdim this just grew, and could be parsed much more simply! 3034218822Sdim Dean in haste. */ 3035218822Sdim name = input_line_pointer; 3036218822Sdim delim = get_symbol_end (); 3037218822Sdim end_name = input_line_pointer; 303833965Sjdp *end_name = delim; 303933965Sjdp 3040218822Sdim if (name == end_name) 3041218822Sdim { 3042218822Sdim as_bad (_("expected symbol name")); 3043218822Sdim ignore_rest_of_line (); 3044218822Sdim return; 3045218822Sdim } 304633965Sjdp 3047218822Sdim SKIP_WHITESPACE (); 3048218822Sdim 3049218822Sdim if (*input_line_pointer != ',') 3050218822Sdim { 3051218822Sdim *end_name = 0; 3052218822Sdim as_bad (_("expected comma after \"%s\""), name); 3053218822Sdim *end_name = delim; 3054218822Sdim ignore_rest_of_line (); 3055218822Sdim return; 3056218822Sdim } 3057218822Sdim 3058218822Sdim input_line_pointer++; 3059218822Sdim *end_name = 0; 3060218822Sdim 3061218822Sdim assign_symbol (name, equiv); 3062218822Sdim *end_name = delim; 3063218822Sdim 306433965Sjdp demand_empty_rest_of_line (); 306577298Sobrien} 306633965Sjdp 306777298Sobrienvoid 3068130561Sobriens_space (int mult) 306933965Sjdp{ 307033965Sjdp expressionS exp; 307133965Sjdp expressionS val; 307233965Sjdp char *p = 0; 307333965Sjdp char *stop = NULL; 3074218822Sdim char stopc = 0; 307533965Sjdp int bytes; 307633965Sjdp 307733965Sjdp#ifdef md_flush_pending_output 307833965Sjdp md_flush_pending_output (); 307933965Sjdp#endif 308033965Sjdp 308133965Sjdp if (flag_mri) 308233965Sjdp stop = mri_comment_field (&stopc); 308333965Sjdp 308433965Sjdp /* In m68k MRI mode, we need to align to a word boundary, unless 308533965Sjdp this is ds.b. */ 308633965Sjdp if (flag_m68k_mri && mult > 1) 308733965Sjdp { 308833965Sjdp if (now_seg == absolute_section) 308933965Sjdp { 309033965Sjdp abs_section_offset += abs_section_offset & 1; 309133965Sjdp if (line_label != NULL) 309233965Sjdp S_SET_VALUE (line_label, abs_section_offset); 309333965Sjdp } 309433965Sjdp else if (mri_common_symbol != NULL) 309533965Sjdp { 309633965Sjdp valueT val; 309733965Sjdp 309833965Sjdp val = S_GET_VALUE (mri_common_symbol); 309933965Sjdp if ((val & 1) != 0) 310033965Sjdp { 310133965Sjdp S_SET_VALUE (mri_common_symbol, val + 1); 310233965Sjdp if (line_label != NULL) 310333965Sjdp { 310460484Sobrien expressionS *symexp; 310560484Sobrien 310660484Sobrien symexp = symbol_get_value_expression (line_label); 310760484Sobrien know (symexp->X_op == O_symbol); 310860484Sobrien know (symexp->X_add_symbol == mri_common_symbol); 310960484Sobrien symexp->X_add_number += 1; 311033965Sjdp } 311133965Sjdp } 311233965Sjdp } 311333965Sjdp else 311433965Sjdp { 311533965Sjdp do_align (1, (char *) NULL, 0, 0); 311633965Sjdp if (line_label != NULL) 311733965Sjdp { 311860484Sobrien symbol_set_frag (line_label, frag_now); 311933965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 312033965Sjdp } 312133965Sjdp } 312233965Sjdp } 312333965Sjdp 312433965Sjdp bytes = mult; 312533965Sjdp 312633965Sjdp expression (&exp); 312733965Sjdp 312833965Sjdp SKIP_WHITESPACE (); 312933965Sjdp if (*input_line_pointer == ',') 313033965Sjdp { 313133965Sjdp ++input_line_pointer; 313233965Sjdp expression (&val); 313333965Sjdp } 313433965Sjdp else 313533965Sjdp { 313633965Sjdp val.X_op = O_constant; 313733965Sjdp val.X_add_number = 0; 313833965Sjdp } 313933965Sjdp 314033965Sjdp if (val.X_op != O_constant 314133965Sjdp || val.X_add_number < - 0x80 314233965Sjdp || val.X_add_number > 0xff 314333965Sjdp || (mult != 0 && mult != 1 && val.X_add_number != 0)) 314433965Sjdp { 3145218822Sdim resolve_expression (&exp); 314633965Sjdp if (exp.X_op != O_constant) 314789857Sobrien as_bad (_("unsupported variable size or fill value")); 314833965Sjdp else 314933965Sjdp { 315033965Sjdp offsetT i; 315133965Sjdp 315233965Sjdp if (mult == 0) 315333965Sjdp mult = 1; 315433965Sjdp bytes = mult * exp.X_add_number; 315533965Sjdp for (i = 0; i < exp.X_add_number; i++) 315633965Sjdp emit_expr (&val, mult); 315733965Sjdp } 315833965Sjdp } 315933965Sjdp else 316033965Sjdp { 3161218822Sdim if (now_seg == absolute_section || mri_common_symbol != NULL) 3162218822Sdim resolve_expression (&exp); 3163218822Sdim 316433965Sjdp if (exp.X_op == O_constant) 316533965Sjdp { 316633965Sjdp long repeat; 316733965Sjdp 316833965Sjdp repeat = exp.X_add_number; 316933965Sjdp if (mult) 317033965Sjdp repeat *= mult; 317133965Sjdp bytes = repeat; 317233965Sjdp if (repeat <= 0) 317333965Sjdp { 317477298Sobrien if (!flag_mri) 317560484Sobrien as_warn (_(".space repeat count is zero, ignored")); 317660484Sobrien else if (repeat < 0) 317760484Sobrien as_warn (_(".space repeat count is negative, ignored")); 317833965Sjdp goto getout; 317933965Sjdp } 318033965Sjdp 318133965Sjdp /* If we are in the absolute section, just bump the offset. */ 318233965Sjdp if (now_seg == absolute_section) 318333965Sjdp { 318433965Sjdp abs_section_offset += repeat; 318533965Sjdp goto getout; 318633965Sjdp } 318733965Sjdp 318833965Sjdp /* If we are secretly in an MRI common section, then 318933965Sjdp creating space just increases the size of the common 319033965Sjdp symbol. */ 319133965Sjdp if (mri_common_symbol != NULL) 319233965Sjdp { 319333965Sjdp S_SET_VALUE (mri_common_symbol, 319433965Sjdp S_GET_VALUE (mri_common_symbol) + repeat); 319533965Sjdp goto getout; 319633965Sjdp } 319733965Sjdp 319833965Sjdp if (!need_pass_2) 319933965Sjdp p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, 320033965Sjdp (offsetT) repeat, (char *) 0); 320133965Sjdp } 320233965Sjdp else 320333965Sjdp { 320433965Sjdp if (now_seg == absolute_section) 320533965Sjdp { 320660484Sobrien as_bad (_("space allocation too complex in absolute section")); 320733965Sjdp subseg_set (text_section, 0); 320833965Sjdp } 320977298Sobrien 321033965Sjdp if (mri_common_symbol != NULL) 321133965Sjdp { 321260484Sobrien as_bad (_("space allocation too complex in common section")); 321333965Sjdp mri_common_symbol = NULL; 321433965Sjdp } 321577298Sobrien 321633965Sjdp if (!need_pass_2) 321733965Sjdp p = frag_var (rs_space, 1, 1, (relax_substateT) 0, 321833965Sjdp make_expr_symbol (&exp), (offsetT) 0, (char *) 0); 321933965Sjdp } 322033965Sjdp 322133965Sjdp if (p) 322233965Sjdp *p = val.X_add_number; 322333965Sjdp } 322433965Sjdp 322533965Sjdp getout: 322633965Sjdp 322733965Sjdp /* In MRI mode, after an odd number of bytes, we must align to an 322833965Sjdp even word boundary, unless the next instruction is a dc.b, ds.b 322933965Sjdp or dcb.b. */ 323033965Sjdp if (flag_mri && (bytes & 1) != 0) 323133965Sjdp mri_pending_align = 1; 323233965Sjdp 323360484Sobrien demand_empty_rest_of_line (); 323460484Sobrien 323533965Sjdp if (flag_mri) 323633965Sjdp mri_comment_end (stop, stopc); 323733965Sjdp} 323833965Sjdp 323933965Sjdp/* This is like s_space, but the value is a floating point number with 324033965Sjdp the given precision. This is for the MRI dcb.s pseudo-op and 324133965Sjdp friends. */ 324233965Sjdp 324333965Sjdpvoid 3244130561Sobriens_float_space (int float_type) 324533965Sjdp{ 324633965Sjdp offsetT count; 324733965Sjdp int flen; 324833965Sjdp char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 324933965Sjdp char *stop = NULL; 3250218822Sdim char stopc = 0; 325133965Sjdp 325233965Sjdp if (flag_mri) 325333965Sjdp stop = mri_comment_field (&stopc); 325433965Sjdp 325533965Sjdp count = get_absolute_expression (); 325633965Sjdp 325733965Sjdp SKIP_WHITESPACE (); 325833965Sjdp if (*input_line_pointer != ',') 325933965Sjdp { 326060484Sobrien as_bad (_("missing value")); 326160484Sobrien ignore_rest_of_line (); 326233965Sjdp if (flag_mri) 326333965Sjdp mri_comment_end (stop, stopc); 326433965Sjdp return; 326533965Sjdp } 326633965Sjdp 326733965Sjdp ++input_line_pointer; 326833965Sjdp 326933965Sjdp SKIP_WHITESPACE (); 327033965Sjdp 327133965Sjdp /* Skip any 0{letter} that may be present. Don't even check if the 327233965Sjdp * letter is legal. */ 327338889Sjdp if (input_line_pointer[0] == '0' 327489857Sobrien && ISALPHA (input_line_pointer[1])) 327533965Sjdp input_line_pointer += 2; 327633965Sjdp 327733965Sjdp /* Accept :xxxx, where the x's are hex digits, for a floating point 327833965Sjdp with the exact digits specified. */ 327933965Sjdp if (input_line_pointer[0] == ':') 328033965Sjdp { 328133965Sjdp flen = hex_float (float_type, temp); 328233965Sjdp if (flen < 0) 328333965Sjdp { 328460484Sobrien ignore_rest_of_line (); 328533965Sjdp if (flag_mri) 328633965Sjdp mri_comment_end (stop, stopc); 328733965Sjdp return; 328833965Sjdp } 328933965Sjdp } 329033965Sjdp else 329133965Sjdp { 329233965Sjdp char *err; 329333965Sjdp 329433965Sjdp err = md_atof (float_type, temp, &flen); 329533965Sjdp know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 329633965Sjdp know (flen > 0); 329733965Sjdp if (err) 329833965Sjdp { 329989857Sobrien as_bad (_("bad floating literal: %s"), err); 330060484Sobrien ignore_rest_of_line (); 330133965Sjdp if (flag_mri) 330233965Sjdp mri_comment_end (stop, stopc); 330333965Sjdp return; 330433965Sjdp } 330533965Sjdp } 330633965Sjdp 330733965Sjdp while (--count >= 0) 330833965Sjdp { 330933965Sjdp char *p; 331033965Sjdp 331133965Sjdp p = frag_more (flen); 331233965Sjdp memcpy (p, temp, (unsigned int) flen); 331333965Sjdp } 331433965Sjdp 331560484Sobrien demand_empty_rest_of_line (); 331660484Sobrien 331733965Sjdp if (flag_mri) 331833965Sjdp mri_comment_end (stop, stopc); 331933965Sjdp} 332033965Sjdp 332133965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers. */ 332233965Sjdp 332333965Sjdpvoid 3324130561Sobriens_struct (int ignore ATTRIBUTE_UNUSED) 332533965Sjdp{ 332633965Sjdp char *stop = NULL; 3327218822Sdim char stopc = 0; 332833965Sjdp 332933965Sjdp if (flag_mri) 333033965Sjdp stop = mri_comment_field (&stopc); 333133965Sjdp abs_section_offset = get_absolute_expression (); 3332218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 3333218822Sdim /* The ELF backend needs to know that we are changing sections, so 3334218822Sdim that .previous works correctly. */ 3335218822Sdim if (IS_ELF) 3336218822Sdim obj_elf_section_change_hook (); 3337218822Sdim#endif 333833965Sjdp subseg_set (absolute_section, 0); 333960484Sobrien demand_empty_rest_of_line (); 334033965Sjdp if (flag_mri) 334133965Sjdp mri_comment_end (stop, stopc); 334233965Sjdp} 334333965Sjdp 334433965Sjdpvoid 3345130561Sobriens_text (int ignore ATTRIBUTE_UNUSED) 334633965Sjdp{ 334733965Sjdp register int temp; 334833965Sjdp 334933965Sjdp temp = get_absolute_expression (); 335033965Sjdp subseg_set (text_section, (subsegT) temp); 335133965Sjdp demand_empty_rest_of_line (); 335233965Sjdp#ifdef OBJ_VMS 335333965Sjdp const_flag &= ~IN_DEFAULT_SECTION; 335433965Sjdp#endif 335577298Sobrien} 3356218822Sdim 3357218822Sdim/* .weakref x, y sets x as an alias to y that, as long as y is not 3358218822Sdim referenced directly, will cause y to become a weak symbol. */ 3359218822Sdimvoid 3360218822Sdims_weakref (int ignore ATTRIBUTE_UNUSED) 3361218822Sdim{ 3362218822Sdim char *name; 3363218822Sdim char delim; 3364218822Sdim char *end_name; 3365218822Sdim symbolS *symbolP; 3366218822Sdim symbolS *symbolP2; 3367218822Sdim expressionS exp; 3368218822Sdim 3369218822Sdim name = input_line_pointer; 3370218822Sdim delim = get_symbol_end (); 3371218822Sdim end_name = input_line_pointer; 3372218822Sdim 3373218822Sdim if (name == end_name) 3374218822Sdim { 3375218822Sdim as_bad (_("expected symbol name")); 3376218822Sdim *end_name = delim; 3377218822Sdim ignore_rest_of_line (); 3378218822Sdim return; 3379218822Sdim } 3380218822Sdim 3381218822Sdim symbolP = symbol_find_or_make (name); 3382218822Sdim 3383218822Sdim if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) 3384218822Sdim { 3385218822Sdim if (!S_IS_VOLATILE (symbolP)) 3386218822Sdim { 3387218822Sdim as_bad (_("symbol `%s' is already defined"), name); 3388218822Sdim *end_name = delim; 3389218822Sdim ignore_rest_of_line (); 3390218822Sdim return; 3391218822Sdim } 3392218822Sdim symbolP = symbol_clone (symbolP, 1); 3393218822Sdim S_CLEAR_VOLATILE (symbolP); 3394218822Sdim } 3395218822Sdim 3396218822Sdim *end_name = delim; 3397218822Sdim 3398218822Sdim SKIP_WHITESPACE (); 3399218822Sdim 3400218822Sdim if (*input_line_pointer != ',') 3401218822Sdim { 3402218822Sdim *end_name = 0; 3403218822Sdim as_bad (_("expected comma after \"%s\""), name); 3404218822Sdim *end_name = delim; 3405218822Sdim ignore_rest_of_line (); 3406218822Sdim return; 3407218822Sdim } 3408218822Sdim 3409218822Sdim input_line_pointer++; 3410218822Sdim 3411218822Sdim SKIP_WHITESPACE (); 3412218822Sdim 3413218822Sdim name = input_line_pointer; 3414218822Sdim delim = get_symbol_end (); 3415218822Sdim end_name = input_line_pointer; 3416218822Sdim 3417218822Sdim if (name == end_name) 3418218822Sdim { 3419218822Sdim as_bad (_("expected symbol name")); 3420218822Sdim ignore_rest_of_line (); 3421218822Sdim return; 3422218822Sdim } 3423218822Sdim 3424218822Sdim if ((symbolP2 = symbol_find_noref (name, 1)) == NULL 3425218822Sdim && (symbolP2 = md_undefined_symbol (name)) == NULL) 3426218822Sdim { 3427218822Sdim symbolP2 = symbol_find_or_make (name); 3428218822Sdim S_SET_WEAKREFD (symbolP2); 3429218822Sdim } 3430218822Sdim else 3431218822Sdim { 3432218822Sdim symbolS *symp = symbolP2; 3433218822Sdim 3434218822Sdim while (S_IS_WEAKREFR (symp) && symp != symbolP) 3435218822Sdim { 3436218822Sdim expressionS *expP = symbol_get_value_expression (symp); 3437218822Sdim 3438218822Sdim assert (expP->X_op == O_symbol 3439218822Sdim && expP->X_add_number == 0); 3440218822Sdim symp = expP->X_add_symbol; 3441218822Sdim } 3442218822Sdim if (symp == symbolP) 3443218822Sdim { 3444218822Sdim char *loop; 3445218822Sdim 3446218822Sdim loop = concat (S_GET_NAME (symbolP), 3447218822Sdim " => ", S_GET_NAME (symbolP2), NULL); 3448218822Sdim 3449218822Sdim symp = symbolP2; 3450218822Sdim while (symp != symbolP) 3451218822Sdim { 3452218822Sdim char *old_loop = loop; 3453218822Sdim symp = symbol_get_value_expression (symp)->X_add_symbol; 3454218822Sdim loop = concat (loop, " => ", S_GET_NAME (symp), NULL); 3455218822Sdim free (old_loop); 3456218822Sdim } 3457218822Sdim 3458218822Sdim as_bad (_("%s: would close weakref loop: %s"), 3459218822Sdim S_GET_NAME (symbolP), loop); 3460218822Sdim 3461218822Sdim free (loop); 3462218822Sdim 3463218822Sdim *end_name = delim; 3464218822Sdim ignore_rest_of_line (); 3465218822Sdim return; 3466218822Sdim } 3467218822Sdim 3468218822Sdim /* Short-circuiting instead of just checking here might speed 3469218822Sdim things up a tiny little bit, but loop error messages would 3470218822Sdim miss intermediate links. */ 3471218822Sdim /* symbolP2 = symp; */ 3472218822Sdim } 3473218822Sdim 3474218822Sdim *end_name = delim; 3475218822Sdim 3476218822Sdim memset (&exp, 0, sizeof (exp)); 3477218822Sdim exp.X_op = O_symbol; 3478218822Sdim exp.X_add_symbol = symbolP2; 3479218822Sdim 3480218822Sdim S_SET_SEGMENT (symbolP, undefined_section); 3481218822Sdim symbol_set_value_expression (symbolP, &exp); 3482218822Sdim symbol_set_frag (symbolP, &zero_address_frag); 3483218822Sdim S_SET_WEAKREFR (symbolP); 3484218822Sdim 3485218822Sdim demand_empty_rest_of_line (); 3486218822Sdim} 348733965Sjdp 3488130561Sobrien 3489130561Sobrien/* Verify that we are at the end of a line. If not, issue an error and 3490130561Sobrien skip to EOL. */ 3491130561Sobrien 349277298Sobrienvoid 3493130561Sobriendemand_empty_rest_of_line (void) 349433965Sjdp{ 349533965Sjdp SKIP_WHITESPACE (); 349633965Sjdp if (is_end_of_line[(unsigned char) *input_line_pointer]) 349777298Sobrien input_line_pointer++; 349833965Sjdp else 349933965Sjdp { 350089857Sobrien if (ISPRINT (*input_line_pointer)) 3501130561Sobrien as_bad (_("junk at end of line, first unrecognized character is `%c'"), 350289857Sobrien *input_line_pointer); 350333965Sjdp else 3504130561Sobrien as_bad (_("junk at end of line, first unrecognized character valued 0x%x"), 350589857Sobrien *input_line_pointer); 3506130561Sobrien ignore_rest_of_line (); 350733965Sjdp } 3508130561Sobrien 3509130561Sobrien /* Return pointing just after end-of-line. */ 3510130561Sobrien know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 3511130561Sobrien} 351277298Sobrien 3513130561Sobrien/* Silently advance to the end of line. Use this after already having 3514130561Sobrien issued an error about something bad. */ 3515130561Sobrien 3516130561Sobrienvoid 3517130561Sobrienignore_rest_of_line (void) 3518130561Sobrien{ 3519130561Sobrien while (input_line_pointer < buffer_limit 3520130561Sobrien && !is_end_of_line[(unsigned char) *input_line_pointer]) 3521130561Sobrien input_line_pointer++; 3522130561Sobrien 352377298Sobrien input_line_pointer++; 352477298Sobrien 352577298Sobrien /* Return pointing just after end-of-line. */ 352633965Sjdp know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 352733965Sjdp} 352833965Sjdp 3529218822Sdim/* Sets frag for given symbol to zero_address_frag, except when the 3530218822Sdim symbol frag is already set to a dummy listing frag. */ 3531218822Sdim 3532218822Sdimstatic void 3533218822Sdimset_zero_frag (symbolS *symbolP) 353460484Sobrien{ 3535218822Sdim if (symbol_get_frag (symbolP)->fr_type != rs_dummy) 3536218822Sdim symbol_set_frag (symbolP, &zero_address_frag); 353760484Sobrien} 353860484Sobrien 353977298Sobrien/* In: Pointer to a symbol. 3540130561Sobrien Input_line_pointer->expression. 354177298Sobrien 354277298Sobrien Out: Input_line_pointer->just after any whitespace after expression. 3543130561Sobrien Tried to set symbol to value of expression. 3544130561Sobrien Will change symbols type, value, and frag; */ 354577298Sobrien 354633965Sjdpvoid 3547130561Sobrienpseudo_set (symbolS *symbolP) 354833965Sjdp{ 354933965Sjdp expressionS exp; 3550218822Sdim segT seg; 355133965Sjdp 355277298Sobrien know (symbolP); /* NULL pointer is logic error. */ 355333965Sjdp 3554218822Sdim if (!S_IS_FORWARD_REF (symbolP)) 3555218822Sdim (void) expression (&exp); 3556218822Sdim else 3557218822Sdim (void) deferred_expression (&exp); 355833965Sjdp 355933965Sjdp if (exp.X_op == O_illegal) 356089857Sobrien as_bad (_("illegal expression")); 356133965Sjdp else if (exp.X_op == O_absent) 356289857Sobrien as_bad (_("missing expression")); 356333965Sjdp else if (exp.X_op == O_big) 356460484Sobrien { 356560484Sobrien if (exp.X_add_number > 0) 356689857Sobrien as_bad (_("bignum invalid")); 356760484Sobrien else 356889857Sobrien as_bad (_("floating point number invalid")); 356960484Sobrien } 357033965Sjdp else if (exp.X_op == O_subtract 3571218822Sdim && !S_IS_FORWARD_REF (symbolP) 357233965Sjdp && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol)) 357360484Sobrien && (symbol_get_frag (exp.X_add_symbol) 357460484Sobrien == symbol_get_frag (exp.X_op_symbol))) 357533965Sjdp { 357633965Sjdp exp.X_op = O_constant; 357733965Sjdp exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol) 357833965Sjdp - S_GET_VALUE (exp.X_op_symbol)); 357933965Sjdp } 358033965Sjdp 3581218822Sdim if (symbol_section_p (symbolP)) 3582218822Sdim { 3583218822Sdim as_bad ("attempt to set value of section symbol"); 3584218822Sdim return; 3585218822Sdim } 3586218822Sdim 358733965Sjdp switch (exp.X_op) 358833965Sjdp { 358933965Sjdp case O_illegal: 359033965Sjdp case O_absent: 359133965Sjdp case O_big: 359233965Sjdp exp.X_add_number = 0; 359333965Sjdp /* Fall through. */ 359433965Sjdp case O_constant: 359533965Sjdp S_SET_SEGMENT (symbolP, absolute_section); 359633965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 3597218822Sdim set_zero_frag (symbolP); 359833965Sjdp break; 359933965Sjdp 360033965Sjdp case O_register: 360133965Sjdp S_SET_SEGMENT (symbolP, reg_section); 360233965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 3603218822Sdim set_zero_frag (symbolP); 3604218822Sdim symbol_get_value_expression (symbolP)->X_op = O_register; 360533965Sjdp break; 360633965Sjdp 360733965Sjdp case O_symbol: 3608218822Sdim seg = S_GET_SEGMENT (exp.X_add_symbol); 3609218822Sdim /* For x=undef+const, create an expression symbol. 3610218822Sdim For x=x+const, just update x except when x is an undefined symbol 3611218822Sdim For x=defined+const, evaluate x. */ 3612218822Sdim if (symbolP == exp.X_add_symbol 3613218822Sdim && (seg != undefined_section 3614218822Sdim || !symbol_constant_p (symbolP))) 361533965Sjdp { 3616218822Sdim *symbol_X_add_number (symbolP) += exp.X_add_number; 3617218822Sdim break; 3618218822Sdim } 3619218822Sdim else if (!S_IS_FORWARD_REF (symbolP) && seg != undefined_section) 3620218822Sdim { 362133965Sjdp symbolS *s = exp.X_add_symbol; 362233965Sjdp 3623218822Sdim if (S_IS_COMMON (s)) 3624218822Sdim as_bad (_("`%s' can't be equated to common symbol '%s'"), 3625218822Sdim S_GET_NAME (symbolP), S_GET_NAME (s)); 3626218822Sdim 3627218822Sdim S_SET_SEGMENT (symbolP, seg); 3628218822Sdim S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (s)); 362960484Sobrien symbol_set_frag (symbolP, symbol_get_frag (s)); 363033965Sjdp copy_symbol_attributes (symbolP, s); 3631218822Sdim break; 363233965Sjdp } 3633218822Sdim S_SET_SEGMENT (symbolP, undefined_section); 3634218822Sdim symbol_set_value_expression (symbolP, &exp); 3635218822Sdim set_zero_frag (symbolP); 363633965Sjdp break; 363733965Sjdp 363833965Sjdp default: 3639218822Sdim /* The value is some complex expression. */ 3640218822Sdim S_SET_SEGMENT (symbolP, expr_section); 364160484Sobrien symbol_set_value_expression (symbolP, &exp); 3642218822Sdim set_zero_frag (symbolP); 364333965Sjdp break; 364433965Sjdp } 364533965Sjdp} 364633965Sjdp 3647130561Sobrien/* cons() 364833965Sjdp 364977298Sobrien CONStruct more frag of .bytes, or .words etc. 365077298Sobrien Should need_pass_2 be 1 then emit no frag(s). 365177298Sobrien This understands EXPRESSIONS. 365277298Sobrien 365377298Sobrien Bug (?) 365477298Sobrien 365577298Sobrien This has a split personality. We use expression() to read the 365677298Sobrien value. We can detect if the value won't fit in a byte or word. 365777298Sobrien But we can't detect if expression() discarded significant digits 365877298Sobrien in the case of a long. Not worth the crocks required to fix it. */ 365977298Sobrien 366033965Sjdp/* Select a parser for cons expressions. */ 366133965Sjdp 366233965Sjdp/* Some targets need to parse the expression in various fancy ways. 366333965Sjdp You can define TC_PARSE_CONS_EXPRESSION to do whatever you like 366433965Sjdp (for example, the HPPA does this). Otherwise, you can define 366533965Sjdp BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or 366633965Sjdp REPEAT_CONS_EXPRESSIONS to permit repeat counts. If none of these 366733965Sjdp are defined, which is the normal case, then only simple expressions 366833965Sjdp are permitted. */ 366933965Sjdp 367060484Sobrien#ifdef TC_M68K 367133965Sjdpstatic void 3672130561Sobrienparse_mri_cons (expressionS *exp, unsigned int nbytes); 367360484Sobrien#endif 367433965Sjdp 367533965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION 367633965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS 367733965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES) 367877298Sobrienstatic void 3679130561Sobrienparse_bitfield_cons (expressionS *exp, unsigned int nbytes); 368033965Sjdp#endif 368133965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 368233965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES) 368333965Sjdpstatic void 3684130561Sobrienparse_repeat_cons (expressionS *exp, unsigned int nbytes); 368533965Sjdp#endif 368633965Sjdp 368733965Sjdp/* If we haven't gotten one yet, just call expression. */ 368833965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION 368933965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP) 369033965Sjdp#endif 369133965Sjdp#endif 369233965Sjdp 3693130561Sobrienvoid 3694130561Sobriendo_parse_cons_expression (expressionS *exp, 3695130561Sobrien int nbytes ATTRIBUTE_UNUSED) 3696130561Sobrien{ 3697130561Sobrien TC_PARSE_CONS_EXPRESSION (exp, nbytes); 3698130561Sobrien} 3699130561Sobrien 3700130561Sobrien 370177298Sobrien/* Worker to do .byte etc statements. 370277298Sobrien Clobbers input_line_pointer and checks end-of-line. */ 370377298Sobrien 370477298Sobrienstatic void 3705130561Sobriencons_worker (register int nbytes, /* 1=.byte, 2=.word, 4=.long. */ 3706130561Sobrien int rva) 370733965Sjdp{ 370833965Sjdp int c; 370933965Sjdp expressionS exp; 371033965Sjdp char *stop = NULL; 3711218822Sdim char stopc = 0; 371233965Sjdp 371333965Sjdp#ifdef md_flush_pending_output 371433965Sjdp md_flush_pending_output (); 371533965Sjdp#endif 371633965Sjdp 371733965Sjdp if (flag_mri) 371833965Sjdp stop = mri_comment_field (&stopc); 371933965Sjdp 372033965Sjdp if (is_it_end_of_statement ()) 372133965Sjdp { 372260484Sobrien demand_empty_rest_of_line (); 372333965Sjdp if (flag_mri) 372433965Sjdp mri_comment_end (stop, stopc); 372533965Sjdp return; 372633965Sjdp } 372733965Sjdp 3728218822Sdim#ifdef TC_ADDRESS_BYTES 3729218822Sdim if (nbytes == 0) 3730218822Sdim nbytes = TC_ADDRESS_BYTES (); 3731218822Sdim#endif 3732218822Sdim 373333965Sjdp#ifdef md_cons_align 373433965Sjdp md_cons_align (nbytes); 373533965Sjdp#endif 373633965Sjdp 373733965Sjdp c = 0; 373833965Sjdp do 373933965Sjdp { 374060484Sobrien#ifdef TC_M68K 374133965Sjdp if (flag_m68k_mri) 374233965Sjdp parse_mri_cons (&exp, (unsigned int) nbytes); 374333965Sjdp else 374460484Sobrien#endif 374533965Sjdp TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); 374633965Sjdp 374733965Sjdp if (rva) 374833965Sjdp { 374933965Sjdp if (exp.X_op == O_symbol) 375033965Sjdp exp.X_op = O_symbol_rva; 375133965Sjdp else 375260484Sobrien as_fatal (_("rva without symbol")); 375333965Sjdp } 375433965Sjdp emit_expr (&exp, (unsigned int) nbytes); 375533965Sjdp ++c; 375633965Sjdp } 375733965Sjdp while (*input_line_pointer++ == ','); 375833965Sjdp 375933965Sjdp /* In MRI mode, after an odd number of bytes, we must align to an 376033965Sjdp even word boundary, unless the next instruction is a dc.b, ds.b 376133965Sjdp or dcb.b. */ 376233965Sjdp if (flag_mri && nbytes == 1 && (c & 1) != 0) 376333965Sjdp mri_pending_align = 1; 376433965Sjdp 376577298Sobrien input_line_pointer--; /* Put terminator back into stream. */ 376633965Sjdp 376760484Sobrien demand_empty_rest_of_line (); 376860484Sobrien 376933965Sjdp if (flag_mri) 377033965Sjdp mri_comment_end (stop, stopc); 377133965Sjdp} 377233965Sjdp 377333965Sjdpvoid 3774130561Sobriencons (int size) 377533965Sjdp{ 377633965Sjdp cons_worker (size, 0); 377733965Sjdp} 377833965Sjdp 377977298Sobrienvoid 3780130561Sobriens_rva (int size) 378133965Sjdp{ 378233965Sjdp cons_worker (size, 1); 378333965Sjdp} 378433965Sjdp 3785218822Sdim/* .reloc offset, reloc_name, symbol+addend. */ 3786218822Sdim 3787218822Sdimvoid 3788218822Sdims_reloc (int ignore ATTRIBUTE_UNUSED) 3789218822Sdim{ 3790218822Sdim char *stop = NULL; 3791218822Sdim char stopc = 0; 3792218822Sdim expressionS exp; 3793218822Sdim char *r_name; 3794218822Sdim int c; 3795218822Sdim struct reloc_list *reloc; 3796218822Sdim 3797218822Sdim reloc = xmalloc (sizeof (*reloc)); 3798218822Sdim 3799218822Sdim if (flag_mri) 3800218822Sdim stop = mri_comment_field (&stopc); 3801218822Sdim 3802218822Sdim expression (&exp); 3803218822Sdim switch (exp.X_op) 3804218822Sdim { 3805218822Sdim case O_illegal: 3806218822Sdim case O_absent: 3807218822Sdim case O_big: 3808218822Sdim case O_register: 3809218822Sdim as_bad (_("missing or bad offset expression")); 3810218822Sdim goto err_out; 3811218822Sdim case O_constant: 3812218822Sdim exp.X_add_symbol = section_symbol (now_seg); 3813218822Sdim exp.X_op = O_symbol; 3814218822Sdim /* Fall thru */ 3815218822Sdim case O_symbol: 3816218822Sdim if (exp.X_add_number == 0) 3817218822Sdim { 3818218822Sdim reloc->u.a.offset_sym = exp.X_add_symbol; 3819218822Sdim break; 3820218822Sdim } 3821218822Sdim /* Fall thru */ 3822218822Sdim default: 3823218822Sdim reloc->u.a.offset_sym = make_expr_symbol (&exp); 3824218822Sdim break; 3825218822Sdim } 3826218822Sdim 3827218822Sdim SKIP_WHITESPACE (); 3828218822Sdim if (*input_line_pointer != ',') 3829218822Sdim { 3830218822Sdim as_bad (_("missing reloc type")); 3831218822Sdim goto err_out; 3832218822Sdim } 3833218822Sdim 3834218822Sdim ++input_line_pointer; 3835218822Sdim SKIP_WHITESPACE (); 3836218822Sdim r_name = input_line_pointer; 3837218822Sdim c = get_symbol_end (); 3838218822Sdim reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name); 3839218822Sdim *input_line_pointer = c; 3840218822Sdim if (reloc->u.a.howto == NULL) 3841218822Sdim { 3842218822Sdim as_bad (_("unrecognized reloc type")); 3843218822Sdim goto err_out; 3844218822Sdim } 3845218822Sdim 3846218822Sdim exp.X_op = O_absent; 3847218822Sdim SKIP_WHITESPACE (); 3848218822Sdim if (*input_line_pointer == ',') 3849218822Sdim { 3850218822Sdim ++input_line_pointer; 3851218822Sdim expression_and_evaluate (&exp); 3852218822Sdim } 3853218822Sdim switch (exp.X_op) 3854218822Sdim { 3855218822Sdim case O_illegal: 3856218822Sdim case O_big: 3857218822Sdim case O_register: 3858218822Sdim as_bad (_("bad reloc expression")); 3859218822Sdim err_out: 3860218822Sdim ignore_rest_of_line (); 3861218822Sdim free (reloc); 3862218822Sdim if (flag_mri) 3863218822Sdim mri_comment_end (stop, stopc); 3864218822Sdim return; 3865218822Sdim case O_absent: 3866218822Sdim reloc->u.a.sym = NULL; 3867218822Sdim reloc->u.a.addend = 0; 3868218822Sdim break; 3869218822Sdim case O_constant: 3870218822Sdim reloc->u.a.sym = NULL; 3871218822Sdim reloc->u.a.addend = exp.X_add_number; 3872218822Sdim break; 3873218822Sdim case O_symbol: 3874218822Sdim reloc->u.a.sym = exp.X_add_symbol; 3875218822Sdim reloc->u.a.addend = exp.X_add_number; 3876218822Sdim break; 3877218822Sdim default: 3878218822Sdim reloc->u.a.sym = make_expr_symbol (&exp); 3879218822Sdim reloc->u.a.addend = 0; 3880218822Sdim break; 3881218822Sdim } 3882218822Sdim 3883218822Sdim as_where (&reloc->file, &reloc->line); 3884218822Sdim reloc->next = reloc_list; 3885218822Sdim reloc_list = reloc; 3886218822Sdim 3887218822Sdim demand_empty_rest_of_line (); 3888218822Sdim if (flag_mri) 3889218822Sdim mri_comment_end (stop, stopc); 3890218822Sdim} 3891218822Sdim 389233965Sjdp/* Put the contents of expression EXP into the object file using 389333965Sjdp NBYTES bytes. If need_pass_2 is 1, this does nothing. */ 389433965Sjdp 389533965Sjdpvoid 3896130561Sobrienemit_expr (expressionS *exp, unsigned int nbytes) 389733965Sjdp{ 389833965Sjdp operatorT op; 389933965Sjdp register char *p; 390033965Sjdp valueT extra_digit = 0; 390133965Sjdp 390233965Sjdp /* Don't do anything if we are going to make another pass. */ 390333965Sjdp if (need_pass_2) 390433965Sjdp return; 390533965Sjdp 3906130561Sobrien dot_value = frag_now_fix (); 3907130561Sobrien 390838889Sjdp#ifndef NO_LISTING 390938889Sjdp#ifdef OBJ_ELF 391038889Sjdp /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will 391138889Sjdp appear as a four byte positive constant in the .line section, 391238889Sjdp followed by a 2 byte 0xffff. Look for that case here. */ 391338889Sjdp { 391438889Sjdp static int dwarf_line = -1; 391538889Sjdp 391638889Sjdp if (strcmp (segment_name (now_seg), ".line") != 0) 391738889Sjdp dwarf_line = -1; 391838889Sjdp else if (dwarf_line >= 0 391938889Sjdp && nbytes == 2 392038889Sjdp && exp->X_op == O_constant 392138889Sjdp && (exp->X_add_number == -1 || exp->X_add_number == 0xffff)) 392238889Sjdp listing_source_line ((unsigned int) dwarf_line); 392338889Sjdp else if (nbytes == 4 392438889Sjdp && exp->X_op == O_constant 392538889Sjdp && exp->X_add_number >= 0) 392638889Sjdp dwarf_line = exp->X_add_number; 392738889Sjdp else 392838889Sjdp dwarf_line = -1; 392938889Sjdp } 393038889Sjdp 393138889Sjdp /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will 393238889Sjdp appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte 393338889Sjdp AT_sibling (0x12) followed by a four byte address of the sibling 393438889Sjdp followed by a 2 byte AT_name (0x38) followed by the name of the 393538889Sjdp file. We look for that case here. */ 393638889Sjdp { 393738889Sjdp static int dwarf_file = 0; 393838889Sjdp 393938889Sjdp if (strcmp (segment_name (now_seg), ".debug") != 0) 394038889Sjdp dwarf_file = 0; 394138889Sjdp else if (dwarf_file == 0 394238889Sjdp && nbytes == 2 394338889Sjdp && exp->X_op == O_constant 394438889Sjdp && exp->X_add_number == 0x11) 394538889Sjdp dwarf_file = 1; 394638889Sjdp else if (dwarf_file == 1 394738889Sjdp && nbytes == 2 394838889Sjdp && exp->X_op == O_constant 394938889Sjdp && exp->X_add_number == 0x12) 395038889Sjdp dwarf_file = 2; 395138889Sjdp else if (dwarf_file == 2 395238889Sjdp && nbytes == 4) 395338889Sjdp dwarf_file = 3; 395438889Sjdp else if (dwarf_file == 3 395538889Sjdp && nbytes == 2 395638889Sjdp && exp->X_op == O_constant 395738889Sjdp && exp->X_add_number == 0x38) 395838889Sjdp dwarf_file = 4; 395938889Sjdp else 396038889Sjdp dwarf_file = 0; 396138889Sjdp 396238889Sjdp /* The variable dwarf_file_string tells stringer that the string 396338889Sjdp may be the name of the source file. */ 396438889Sjdp if (dwarf_file == 4) 396538889Sjdp dwarf_file_string = 1; 396638889Sjdp else 396738889Sjdp dwarf_file_string = 0; 396838889Sjdp } 396938889Sjdp#endif 397038889Sjdp#endif 397138889Sjdp 397238889Sjdp if (check_eh_frame (exp, &nbytes)) 397338889Sjdp return; 397438889Sjdp 397533965Sjdp op = exp->X_op; 397633965Sjdp 397733965Sjdp /* Allow `.word 0' in the absolute section. */ 397833965Sjdp if (now_seg == absolute_section) 397933965Sjdp { 398033965Sjdp if (op != O_constant || exp->X_add_number != 0) 398160484Sobrien as_bad (_("attempt to store value in absolute section")); 398233965Sjdp abs_section_offset += nbytes; 398333965Sjdp return; 398433965Sjdp } 398533965Sjdp 398633965Sjdp /* Handle a negative bignum. */ 398733965Sjdp if (op == O_uminus 398833965Sjdp && exp->X_add_number == 0 398960484Sobrien && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big 399060484Sobrien && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0) 399133965Sjdp { 399233965Sjdp int i; 399333965Sjdp unsigned long carry; 399433965Sjdp 399560484Sobrien exp = symbol_get_value_expression (exp->X_add_symbol); 399633965Sjdp 399733965Sjdp /* Negate the bignum: one's complement each digit and add 1. */ 399833965Sjdp carry = 1; 399933965Sjdp for (i = 0; i < exp->X_add_number; i++) 400033965Sjdp { 400133965Sjdp unsigned long next; 400233965Sjdp 400377298Sobrien next = (((~(generic_bignum[i] & LITTLENUM_MASK)) 400433965Sjdp & LITTLENUM_MASK) 400533965Sjdp + carry); 400633965Sjdp generic_bignum[i] = next & LITTLENUM_MASK; 400733965Sjdp carry = next >> LITTLENUM_NUMBER_OF_BITS; 400833965Sjdp } 400933965Sjdp 401033965Sjdp /* We can ignore any carry out, because it will be handled by 401133965Sjdp extra_digit if it is needed. */ 401233965Sjdp 401333965Sjdp extra_digit = (valueT) -1; 401433965Sjdp op = O_big; 401533965Sjdp } 401633965Sjdp 401733965Sjdp if (op == O_absent || op == O_illegal) 401833965Sjdp { 401960484Sobrien as_warn (_("zero assumed for missing expression")); 402033965Sjdp exp->X_add_number = 0; 402133965Sjdp op = O_constant; 402233965Sjdp } 402333965Sjdp else if (op == O_big && exp->X_add_number <= 0) 402433965Sjdp { 402589857Sobrien as_bad (_("floating point number invalid")); 402633965Sjdp exp->X_add_number = 0; 402733965Sjdp op = O_constant; 402833965Sjdp } 402933965Sjdp else if (op == O_register) 403033965Sjdp { 403160484Sobrien as_warn (_("register value used as expression")); 403233965Sjdp op = O_constant; 403333965Sjdp } 403433965Sjdp 403533965Sjdp p = frag_more ((int) nbytes); 403633965Sjdp 403733965Sjdp#ifndef WORKING_DOT_WORD 403833965Sjdp /* If we have the difference of two symbols in a word, save it on 403933965Sjdp the broken_words list. See the code in write.c. */ 404033965Sjdp if (op == O_subtract && nbytes == 2) 404133965Sjdp { 404233965Sjdp struct broken_word *x; 404333965Sjdp 404433965Sjdp x = (struct broken_word *) xmalloc (sizeof (struct broken_word)); 404533965Sjdp x->next_broken_word = broken_words; 404633965Sjdp broken_words = x; 404760484Sobrien x->seg = now_seg; 404860484Sobrien x->subseg = now_subseg; 404933965Sjdp x->frag = frag_now; 405033965Sjdp x->word_goes_here = p; 405133965Sjdp x->dispfrag = 0; 405233965Sjdp x->add = exp->X_add_symbol; 405333965Sjdp x->sub = exp->X_op_symbol; 405433965Sjdp x->addnum = exp->X_add_number; 405533965Sjdp x->added = 0; 4056130561Sobrien x->use_jump = 0; 405733965Sjdp new_broken_words++; 405833965Sjdp return; 405933965Sjdp } 406033965Sjdp#endif 406133965Sjdp 406233965Sjdp /* If we have an integer, but the number of bytes is too large to 406333965Sjdp pass to md_number_to_chars, handle it as a bignum. */ 406433965Sjdp if (op == O_constant && nbytes > sizeof (valueT)) 406533965Sjdp { 4066218822Sdim extra_digit = exp->X_unsigned ? 0 : -1; 4067218822Sdim convert_to_bignum (exp); 4068218822Sdim op = O_big; 406933965Sjdp } 407033965Sjdp 407133965Sjdp if (op == O_constant) 407233965Sjdp { 407333965Sjdp register valueT get; 407433965Sjdp register valueT use; 407533965Sjdp register valueT mask; 407633965Sjdp valueT hibit; 407733965Sjdp register valueT unmask; 407833965Sjdp 407933965Sjdp /* JF << of >= number of bits in the object is undefined. In 408077298Sobrien particular SPARC (Sun 4) has problems. */ 408133965Sjdp if (nbytes >= sizeof (valueT)) 408233965Sjdp { 408333965Sjdp mask = 0; 408433965Sjdp if (nbytes > sizeof (valueT)) 408533965Sjdp hibit = 0; 408633965Sjdp else 408733965Sjdp hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); 408833965Sjdp } 408933965Sjdp else 409033965Sjdp { 409177298Sobrien /* Don't store these bits. */ 409233965Sjdp mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); 409333965Sjdp hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); 409433965Sjdp } 409533965Sjdp 409677298Sobrien unmask = ~mask; /* Do store these bits. */ 409733965Sjdp 409833965Sjdp#ifdef NEVER 409933965Sjdp "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; 410077298Sobrien mask = ~(unmask >> 1); /* Includes sign bit now. */ 410133965Sjdp#endif 410233965Sjdp 410333965Sjdp get = exp->X_add_number; 410433965Sjdp use = get & unmask; 410533965Sjdp if ((get & mask) != 0 410633965Sjdp && ((get & mask) != mask 410733965Sjdp || (get & hibit) == 0)) 410877298Sobrien { /* Leading bits contain both 0s & 1s. */ 410989857Sobrien as_warn (_("value 0x%lx truncated to 0x%lx"), 411033965Sjdp (unsigned long) get, (unsigned long) use); 411133965Sjdp } 411277298Sobrien /* Put bytes in right order. */ 411333965Sjdp md_number_to_chars (p, use, (int) nbytes); 411433965Sjdp } 411533965Sjdp else if (op == O_big) 411633965Sjdp { 411738889Sjdp unsigned int size; 411833965Sjdp LITTLENUM_TYPE *nums; 411933965Sjdp 412033965Sjdp know (nbytes % CHARS_PER_LITTLENUM == 0); 412133965Sjdp 412233965Sjdp size = exp->X_add_number * CHARS_PER_LITTLENUM; 412333965Sjdp if (nbytes < size) 412433965Sjdp { 412589857Sobrien as_warn (_("bignum truncated to %d bytes"), nbytes); 412633965Sjdp size = nbytes; 412733965Sjdp } 412833965Sjdp 412933965Sjdp if (target_big_endian) 413033965Sjdp { 413133965Sjdp while (nbytes > size) 413233965Sjdp { 413333965Sjdp md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); 413433965Sjdp nbytes -= CHARS_PER_LITTLENUM; 413533965Sjdp p += CHARS_PER_LITTLENUM; 413633965Sjdp } 413733965Sjdp 413833965Sjdp nums = generic_bignum + size / CHARS_PER_LITTLENUM; 413989857Sobrien while (size >= CHARS_PER_LITTLENUM) 414033965Sjdp { 414133965Sjdp --nums; 414233965Sjdp md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); 414333965Sjdp size -= CHARS_PER_LITTLENUM; 414433965Sjdp p += CHARS_PER_LITTLENUM; 414533965Sjdp } 414633965Sjdp } 414733965Sjdp else 414833965Sjdp { 414933965Sjdp nums = generic_bignum; 415089857Sobrien while (size >= CHARS_PER_LITTLENUM) 415133965Sjdp { 415233965Sjdp md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); 415333965Sjdp ++nums; 415433965Sjdp size -= CHARS_PER_LITTLENUM; 415533965Sjdp p += CHARS_PER_LITTLENUM; 415633965Sjdp nbytes -= CHARS_PER_LITTLENUM; 415733965Sjdp } 415833965Sjdp 415989857Sobrien while (nbytes >= CHARS_PER_LITTLENUM) 416033965Sjdp { 416133965Sjdp md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); 416233965Sjdp nbytes -= CHARS_PER_LITTLENUM; 416333965Sjdp p += CHARS_PER_LITTLENUM; 416433965Sjdp } 416533965Sjdp } 416633965Sjdp } 416733965Sjdp else 416833965Sjdp { 416933965Sjdp memset (p, 0, nbytes); 417033965Sjdp 4171218822Sdim /* Now we need to generate a fixS to record the symbol value. */ 417233965Sjdp 417333965Sjdp#ifdef TC_CONS_FIX_NEW 417433965Sjdp TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp); 417533965Sjdp#else 417633965Sjdp { 417733965Sjdp bfd_reloc_code_real_type r; 417833965Sjdp 417933965Sjdp switch (nbytes) 418033965Sjdp { 418133965Sjdp case 1: 418233965Sjdp r = BFD_RELOC_8; 418333965Sjdp break; 418433965Sjdp case 2: 418533965Sjdp r = BFD_RELOC_16; 418633965Sjdp break; 418733965Sjdp case 4: 418833965Sjdp r = BFD_RELOC_32; 418933965Sjdp break; 419033965Sjdp case 8: 419133965Sjdp r = BFD_RELOC_64; 419233965Sjdp break; 419333965Sjdp default: 419460484Sobrien as_bad (_("unsupported BFD relocation size %u"), nbytes); 419533965Sjdp r = BFD_RELOC_32; 419633965Sjdp break; 419733965Sjdp } 419833965Sjdp fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 419933965Sjdp 0, r); 420033965Sjdp } 420133965Sjdp#endif 420233965Sjdp } 420333965Sjdp} 420433965Sjdp 420533965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS 420633965Sjdp 420733965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as 420833965Sjdp w:x,y:z, where w and y are bitwidths and x and y are values. They 420933965Sjdp then pack them all together. We do a little better in that we allow 421033965Sjdp them in words, longs, etc. and we'll pack them in target byte order 421133965Sjdp for you. 421233965Sjdp 4213130561Sobrien The rules are: pack least significant bit first, if a field doesn't 421433965Sjdp entirely fit, put it in the next unit. Overflowing the bitfield is 421533965Sjdp explicitly *not* even a warning. The bitwidth should be considered 421633965Sjdp a "mask". 421733965Sjdp 421833965Sjdp To use this function the tc-XXX.h file should define 421933965Sjdp BITFIELD_CONS_EXPRESSIONS. */ 422033965Sjdp 422177298Sobrienstatic void 422233965Sjdpparse_bitfield_cons (exp, nbytes) 422333965Sjdp expressionS *exp; 422433965Sjdp unsigned int nbytes; 422533965Sjdp{ 422633965Sjdp unsigned int bits_available = BITS_PER_CHAR * nbytes; 422733965Sjdp char *hold = input_line_pointer; 422833965Sjdp 422933965Sjdp (void) expression (exp); 423033965Sjdp 423133965Sjdp if (*input_line_pointer == ':') 423277298Sobrien { 423377298Sobrien /* Bitfields. */ 423433965Sjdp long value = 0; 423533965Sjdp 423633965Sjdp for (;;) 423733965Sjdp { 423833965Sjdp unsigned long width; 423933965Sjdp 424033965Sjdp if (*input_line_pointer != ':') 424133965Sjdp { 424233965Sjdp input_line_pointer = hold; 424333965Sjdp break; 424477298Sobrien } /* Next piece is not a bitfield. */ 424533965Sjdp 424633965Sjdp /* In the general case, we can't allow 424733965Sjdp full expressions with symbol 424833965Sjdp differences and such. The relocation 424933965Sjdp entries for symbols not defined in this 425033965Sjdp assembly would require arbitrary field 425133965Sjdp widths, positions, and masks which most 425233965Sjdp of our current object formats don't 425333965Sjdp support. 425433965Sjdp 425533965Sjdp In the specific case where a symbol 425633965Sjdp *is* defined in this assembly, we 425733965Sjdp *could* build fixups and track it, but 425833965Sjdp this could lead to confusion for the 425933965Sjdp backends. I'm lazy. I'll take any 426033965Sjdp SEG_ABSOLUTE. I think that means that 426133965Sjdp you can use a previous .set or 426277298Sobrien .equ type symbol. xoxorich. */ 426333965Sjdp 426433965Sjdp if (exp->X_op == O_absent) 426533965Sjdp { 426660484Sobrien as_warn (_("using a bit field width of zero")); 426733965Sjdp exp->X_add_number = 0; 426833965Sjdp exp->X_op = O_constant; 426977298Sobrien } /* Implied zero width bitfield. */ 427033965Sjdp 427133965Sjdp if (exp->X_op != O_constant) 427233965Sjdp { 427333965Sjdp *input_line_pointer = '\0'; 427460484Sobrien as_bad (_("field width \"%s\" too complex for a bitfield"), hold); 427533965Sjdp *input_line_pointer = ':'; 427633965Sjdp demand_empty_rest_of_line (); 427733965Sjdp return; 427877298Sobrien } /* Too complex. */ 427933965Sjdp 428033965Sjdp if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes)) 428133965Sjdp { 428260484Sobrien as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), 428333965Sjdp width, nbytes, (BITS_PER_CHAR * nbytes)); 428433965Sjdp width = BITS_PER_CHAR * nbytes; 428577298Sobrien } /* Too big. */ 428633965Sjdp 428733965Sjdp if (width > bits_available) 428833965Sjdp { 428933965Sjdp /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */ 429033965Sjdp input_line_pointer = hold; 429133965Sjdp exp->X_add_number = value; 429233965Sjdp break; 429377298Sobrien } /* Won't fit. */ 429433965Sjdp 429577298Sobrien /* Skip ':'. */ 429677298Sobrien hold = ++input_line_pointer; 429733965Sjdp 429833965Sjdp (void) expression (exp); 429933965Sjdp if (exp->X_op != O_constant) 430033965Sjdp { 430133965Sjdp char cache = *input_line_pointer; 430233965Sjdp 430333965Sjdp *input_line_pointer = '\0'; 430460484Sobrien as_bad (_("field value \"%s\" too complex for a bitfield"), hold); 430533965Sjdp *input_line_pointer = cache; 430633965Sjdp demand_empty_rest_of_line (); 430733965Sjdp return; 430877298Sobrien } /* Too complex. */ 430933965Sjdp 431033965Sjdp value |= ((~(-1 << width) & exp->X_add_number) 431133965Sjdp << ((BITS_PER_CHAR * nbytes) - bits_available)); 431233965Sjdp 431333965Sjdp if ((bits_available -= width) == 0 431433965Sjdp || is_it_end_of_statement () 431533965Sjdp || *input_line_pointer != ',') 431633965Sjdp { 431733965Sjdp break; 431877298Sobrien } /* All the bitfields we're gonna get. */ 431933965Sjdp 432033965Sjdp hold = ++input_line_pointer; 432133965Sjdp (void) expression (exp); 432277298Sobrien } 432333965Sjdp 432433965Sjdp exp->X_add_number = value; 432533965Sjdp exp->X_op = O_constant; 432633965Sjdp exp->X_unsigned = 1; 432777298Sobrien } 432877298Sobrien} 432933965Sjdp 433033965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */ 433133965Sjdp 433233965Sjdp/* Handle an MRI style string expression. */ 433333965Sjdp 433460484Sobrien#ifdef TC_M68K 433533965Sjdpstatic void 433633965Sjdpparse_mri_cons (exp, nbytes) 433733965Sjdp expressionS *exp; 433833965Sjdp unsigned int nbytes; 433933965Sjdp{ 434033965Sjdp if (*input_line_pointer != '\'' 434133965Sjdp && (input_line_pointer[1] != '\'' 434233965Sjdp || (*input_line_pointer != 'A' 434333965Sjdp && *input_line_pointer != 'E'))) 434433965Sjdp TC_PARSE_CONS_EXPRESSION (exp, nbytes); 434533965Sjdp else 434633965Sjdp { 434738889Sjdp unsigned int scan; 434833965Sjdp unsigned int result = 0; 434933965Sjdp 435033965Sjdp /* An MRI style string. Cut into as many bytes as will fit into 435133965Sjdp a nbyte chunk, left justify if necessary, and separate with 435233965Sjdp commas so we can try again later. */ 435333965Sjdp if (*input_line_pointer == 'A') 435433965Sjdp ++input_line_pointer; 435533965Sjdp else if (*input_line_pointer == 'E') 435633965Sjdp { 435760484Sobrien as_bad (_("EBCDIC constants are not supported")); 435833965Sjdp ++input_line_pointer; 435933965Sjdp } 436033965Sjdp 436133965Sjdp input_line_pointer++; 436233965Sjdp for (scan = 0; scan < nbytes; scan++) 436333965Sjdp { 436433965Sjdp if (*input_line_pointer == '\'') 436533965Sjdp { 436633965Sjdp if (input_line_pointer[1] == '\'') 436733965Sjdp { 436833965Sjdp input_line_pointer++; 436933965Sjdp } 437033965Sjdp else 437133965Sjdp break; 437233965Sjdp } 437333965Sjdp result = (result << 8) | (*input_line_pointer++); 437433965Sjdp } 437533965Sjdp 437677298Sobrien /* Left justify. */ 437733965Sjdp while (scan < nbytes) 437833965Sjdp { 437933965Sjdp result <<= 8; 438033965Sjdp scan++; 438133965Sjdp } 438277298Sobrien 438377298Sobrien /* Create correct expression. */ 438433965Sjdp exp->X_op = O_constant; 438533965Sjdp exp->X_add_number = result; 438677298Sobrien 438777298Sobrien /* Fake it so that we can read the next char too. */ 438833965Sjdp if (input_line_pointer[0] != '\'' || 438933965Sjdp (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\'')) 439033965Sjdp { 439133965Sjdp input_line_pointer -= 2; 439233965Sjdp input_line_pointer[0] = ','; 439333965Sjdp input_line_pointer[1] = '\''; 439433965Sjdp } 439533965Sjdp else 439633965Sjdp input_line_pointer++; 439733965Sjdp } 439833965Sjdp} 439960484Sobrien#endif /* TC_M68K */ 440033965Sjdp 440133965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 440233965Sjdp 440333965Sjdp/* Parse a repeat expression for cons. This is used by the MIPS 440433965Sjdp assembler. The format is NUMBER:COUNT; NUMBER appears in the 440533965Sjdp object file COUNT times. 440633965Sjdp 440733965Sjdp To use this for a target, define REPEAT_CONS_EXPRESSIONS. */ 440833965Sjdp 440933965Sjdpstatic void 441033965Sjdpparse_repeat_cons (exp, nbytes) 441133965Sjdp expressionS *exp; 441233965Sjdp unsigned int nbytes; 441333965Sjdp{ 441433965Sjdp expressionS count; 441533965Sjdp register int i; 441633965Sjdp 441733965Sjdp expression (exp); 441833965Sjdp 441933965Sjdp if (*input_line_pointer != ':') 442033965Sjdp { 442133965Sjdp /* No repeat count. */ 442233965Sjdp return; 442333965Sjdp } 442433965Sjdp 442533965Sjdp ++input_line_pointer; 442633965Sjdp expression (&count); 442733965Sjdp if (count.X_op != O_constant 442833965Sjdp || count.X_add_number <= 0) 442933965Sjdp { 443089857Sobrien as_warn (_("unresolvable or nonpositive repeat count; using 1")); 443133965Sjdp return; 443233965Sjdp } 443333965Sjdp 443433965Sjdp /* The cons function is going to output this expression once. So we 443533965Sjdp output it count - 1 times. */ 443633965Sjdp for (i = count.X_add_number - 1; i > 0; i--) 443733965Sjdp emit_expr (exp, nbytes); 443833965Sjdp} 443933965Sjdp 444033965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */ 444133965Sjdp 444233965Sjdp/* Parse a floating point number represented as a hex constant. This 444333965Sjdp permits users to specify the exact bits they want in the floating 444433965Sjdp point number. */ 444533965Sjdp 444633965Sjdpstatic int 4447130561Sobrienhex_float (int float_type, char *bytes) 444833965Sjdp{ 444933965Sjdp int length; 445033965Sjdp int i; 445133965Sjdp 445233965Sjdp switch (float_type) 445333965Sjdp { 445433965Sjdp case 'f': 445533965Sjdp case 'F': 445633965Sjdp case 's': 445733965Sjdp case 'S': 445833965Sjdp length = 4; 445933965Sjdp break; 446033965Sjdp 446133965Sjdp case 'd': 446233965Sjdp case 'D': 446333965Sjdp case 'r': 446433965Sjdp case 'R': 446533965Sjdp length = 8; 446633965Sjdp break; 446733965Sjdp 446833965Sjdp case 'x': 446933965Sjdp case 'X': 447033965Sjdp length = 12; 447133965Sjdp break; 447233965Sjdp 447333965Sjdp case 'p': 447433965Sjdp case 'P': 447533965Sjdp length = 12; 447633965Sjdp break; 447733965Sjdp 447833965Sjdp default: 447989857Sobrien as_bad (_("unknown floating type type '%c'"), float_type); 448033965Sjdp return -1; 448133965Sjdp } 448233965Sjdp 448333965Sjdp /* It would be nice if we could go through expression to parse the 448433965Sjdp hex constant, but if we get a bignum it's a pain to sort it into 448533965Sjdp the buffer correctly. */ 448633965Sjdp i = 0; 448733965Sjdp while (hex_p (*input_line_pointer) || *input_line_pointer == '_') 448833965Sjdp { 448933965Sjdp int d; 449033965Sjdp 449133965Sjdp /* The MRI assembler accepts arbitrary underscores strewn about 449277298Sobrien through the hex constant, so we ignore them as well. */ 449333965Sjdp if (*input_line_pointer == '_') 449433965Sjdp { 449533965Sjdp ++input_line_pointer; 449633965Sjdp continue; 449733965Sjdp } 449833965Sjdp 449933965Sjdp if (i >= length) 450033965Sjdp { 450189857Sobrien as_warn (_("floating point constant too large")); 450233965Sjdp return -1; 450333965Sjdp } 450433965Sjdp d = hex_value (*input_line_pointer) << 4; 450533965Sjdp ++input_line_pointer; 450633965Sjdp while (*input_line_pointer == '_') 450733965Sjdp ++input_line_pointer; 450833965Sjdp if (hex_p (*input_line_pointer)) 450933965Sjdp { 451033965Sjdp d += hex_value (*input_line_pointer); 451133965Sjdp ++input_line_pointer; 451233965Sjdp } 451333965Sjdp if (target_big_endian) 451433965Sjdp bytes[i] = d; 451533965Sjdp else 451633965Sjdp bytes[length - i - 1] = d; 451733965Sjdp ++i; 451833965Sjdp } 451933965Sjdp 452033965Sjdp if (i < length) 452133965Sjdp { 452233965Sjdp if (target_big_endian) 452333965Sjdp memset (bytes + i, 0, length - i); 452433965Sjdp else 452533965Sjdp memset (bytes, 0, length - i); 452633965Sjdp } 452733965Sjdp 452833965Sjdp return length; 452933965Sjdp} 453033965Sjdp 4531130561Sobrien/* float_cons() 453233965Sjdp 453377298Sobrien CONStruct some more frag chars of .floats .ffloats etc. 453477298Sobrien Makes 0 or more new frags. 453577298Sobrien If need_pass_2 == 1, no frags are emitted. 453677298Sobrien This understands only floating literals, not expressions. Sorry. 453777298Sobrien 453877298Sobrien A floating constant is defined by atof_generic(), except it is preceded 453977298Sobrien by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its 454077298Sobrien reading, I decided to be incompatible. This always tries to give you 454177298Sobrien rounded bits to the precision of the pseudo-op. Former AS did premature 4542130561Sobrien truncation, restored noisy bits instead of trailing 0s AND gave you 454377298Sobrien a choice of 2 flavours of noise according to which of 2 floating-point 454477298Sobrien scanners you directed AS to use. 454577298Sobrien 454677298Sobrien In: input_line_pointer->whitespace before, or '0' of flonum. */ 454777298Sobrien 454833965Sjdpvoid 4549130561Sobrienfloat_cons (/* Clobbers input_line-pointer, checks end-of-line. */ 4550130561Sobrien register int float_type /* 'f':.ffloat ... 'F':.float ... */) 455133965Sjdp{ 455233965Sjdp register char *p; 455377298Sobrien int length; /* Number of chars in an object. */ 455477298Sobrien register char *err; /* Error from scanning floating literal. */ 455533965Sjdp char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 455633965Sjdp 455733965Sjdp if (is_it_end_of_statement ()) 455833965Sjdp { 455933965Sjdp demand_empty_rest_of_line (); 456033965Sjdp return; 456133965Sjdp } 456233965Sjdp 456333965Sjdp#ifdef md_flush_pending_output 456433965Sjdp md_flush_pending_output (); 456533965Sjdp#endif 456633965Sjdp 456733965Sjdp do 456833965Sjdp { 456977298Sobrien /* input_line_pointer->1st char of a flonum (we hope!). */ 457033965Sjdp SKIP_WHITESPACE (); 457133965Sjdp 457233965Sjdp /* Skip any 0{letter} that may be present. Don't even check if the 4573130561Sobrien letter is legal. Someone may invent a "z" format and this routine 4574130561Sobrien has no use for such information. Lusers beware: you get 4575130561Sobrien diagnostics if your input is ill-conditioned. */ 457638889Sjdp if (input_line_pointer[0] == '0' 457789857Sobrien && ISALPHA (input_line_pointer[1])) 457833965Sjdp input_line_pointer += 2; 457933965Sjdp 458033965Sjdp /* Accept :xxxx, where the x's are hex digits, for a floating 4581130561Sobrien point with the exact digits specified. */ 458233965Sjdp if (input_line_pointer[0] == ':') 458333965Sjdp { 458433965Sjdp ++input_line_pointer; 458533965Sjdp length = hex_float (float_type, temp); 458633965Sjdp if (length < 0) 458733965Sjdp { 458833965Sjdp ignore_rest_of_line (); 458933965Sjdp return; 459033965Sjdp } 459133965Sjdp } 459233965Sjdp else 459333965Sjdp { 459433965Sjdp err = md_atof (float_type, temp, &length); 459533965Sjdp know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 459633965Sjdp know (length > 0); 459733965Sjdp if (err) 459833965Sjdp { 459989857Sobrien as_bad (_("bad floating literal: %s"), err); 460033965Sjdp ignore_rest_of_line (); 460133965Sjdp return; 460233965Sjdp } 460333965Sjdp } 460433965Sjdp 460533965Sjdp if (!need_pass_2) 460633965Sjdp { 460733965Sjdp int count; 460833965Sjdp 460933965Sjdp count = 1; 461033965Sjdp 461133965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 461233965Sjdp if (*input_line_pointer == ':') 461333965Sjdp { 461433965Sjdp expressionS count_exp; 461533965Sjdp 461633965Sjdp ++input_line_pointer; 461733965Sjdp expression (&count_exp); 461877298Sobrien 461933965Sjdp if (count_exp.X_op != O_constant 462033965Sjdp || count_exp.X_add_number <= 0) 462177298Sobrien as_warn (_("unresolvable or nonpositive repeat count; using 1")); 462233965Sjdp else 462333965Sjdp count = count_exp.X_add_number; 462433965Sjdp } 462533965Sjdp#endif 462633965Sjdp 462733965Sjdp while (--count >= 0) 462833965Sjdp { 462933965Sjdp p = frag_more (length); 463033965Sjdp memcpy (p, temp, (unsigned int) length); 463133965Sjdp } 463233965Sjdp } 463333965Sjdp SKIP_WHITESPACE (); 463433965Sjdp } 463533965Sjdp while (*input_line_pointer++ == ','); 463633965Sjdp 463777298Sobrien /* Put terminator back into stream. */ 463877298Sobrien --input_line_pointer; 463933965Sjdp demand_empty_rest_of_line (); 464077298Sobrien} 464133965Sjdp 464277298Sobrien/* Return the size of a LEB128 value. */ 464338889Sjdp 464438889Sjdpstatic inline int 4645130561Sobriensizeof_sleb128 (offsetT value) 464638889Sjdp{ 464738889Sjdp register int size = 0; 464838889Sjdp register unsigned byte; 464938889Sjdp 465038889Sjdp do 465138889Sjdp { 465238889Sjdp byte = (value & 0x7f); 465338889Sjdp /* Sadly, we cannot rely on typical arithmetic right shift behaviour. 465438889Sjdp Fortunately, we can structure things so that the extra work reduces 465538889Sjdp to a noop on systems that do things "properly". */ 465638889Sjdp value = (value >> 7) | ~(-(offsetT)1 >> 7); 465738889Sjdp size += 1; 465838889Sjdp } 465938889Sjdp while (!(((value == 0) && ((byte & 0x40) == 0)) 466038889Sjdp || ((value == -1) && ((byte & 0x40) != 0)))); 466138889Sjdp 466238889Sjdp return size; 466338889Sjdp} 466438889Sjdp 466538889Sjdpstatic inline int 4666130561Sobriensizeof_uleb128 (valueT value) 466738889Sjdp{ 466838889Sjdp register int size = 0; 466938889Sjdp register unsigned byte; 467038889Sjdp 467138889Sjdp do 467238889Sjdp { 467338889Sjdp byte = (value & 0x7f); 467438889Sjdp value >>= 7; 467538889Sjdp size += 1; 467638889Sjdp } 467738889Sjdp while (value != 0); 467838889Sjdp 467938889Sjdp return size; 468038889Sjdp} 468138889Sjdp 468260484Sobrienint 4683130561Sobriensizeof_leb128 (valueT value, int sign) 468438889Sjdp{ 468538889Sjdp if (sign) 468638889Sjdp return sizeof_sleb128 ((offsetT) value); 468738889Sjdp else 468838889Sjdp return sizeof_uleb128 (value); 468938889Sjdp} 469038889Sjdp 469138889Sjdp/* Output a LEB128 value. */ 469238889Sjdp 469338889Sjdpstatic inline int 4694130561Sobrienoutput_sleb128 (char *p, offsetT value) 469538889Sjdp{ 469638889Sjdp register char *orig = p; 469738889Sjdp register int more; 469838889Sjdp 469938889Sjdp do 470038889Sjdp { 470138889Sjdp unsigned byte = (value & 0x7f); 470238889Sjdp 470338889Sjdp /* Sadly, we cannot rely on typical arithmetic right shift behaviour. 470438889Sjdp Fortunately, we can structure things so that the extra work reduces 470538889Sjdp to a noop on systems that do things "properly". */ 470638889Sjdp value = (value >> 7) | ~(-(offsetT)1 >> 7); 470738889Sjdp 470838889Sjdp more = !((((value == 0) && ((byte & 0x40) == 0)) 470938889Sjdp || ((value == -1) && ((byte & 0x40) != 0)))); 471038889Sjdp if (more) 471138889Sjdp byte |= 0x80; 471238889Sjdp 471338889Sjdp *p++ = byte; 471438889Sjdp } 471538889Sjdp while (more); 471638889Sjdp 471738889Sjdp return p - orig; 471838889Sjdp} 471938889Sjdp 472038889Sjdpstatic inline int 4721130561Sobrienoutput_uleb128 (char *p, valueT value) 472238889Sjdp{ 472338889Sjdp char *orig = p; 472438889Sjdp 472538889Sjdp do 472638889Sjdp { 472738889Sjdp unsigned byte = (value & 0x7f); 472838889Sjdp value >>= 7; 472938889Sjdp if (value != 0) 473038889Sjdp /* More bytes to follow. */ 473138889Sjdp byte |= 0x80; 473238889Sjdp 473338889Sjdp *p++ = byte; 473438889Sjdp } 473538889Sjdp while (value != 0); 473638889Sjdp 473738889Sjdp return p - orig; 473838889Sjdp} 473938889Sjdp 474060484Sobrienint 4741130561Sobrienoutput_leb128 (char *p, valueT value, int sign) 474238889Sjdp{ 474338889Sjdp if (sign) 474438889Sjdp return output_sleb128 (p, (offsetT) value); 474538889Sjdp else 474638889Sjdp return output_uleb128 (p, value); 474738889Sjdp} 474838889Sjdp 474938889Sjdp/* Do the same for bignums. We combine sizeof with output here in that 475038889Sjdp we don't output for NULL values of P. It isn't really as critical as 475138889Sjdp for "normal" values that this be streamlined. */ 475238889Sjdp 475360484Sobrienstatic inline int 4754130561Sobrienoutput_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size) 475538889Sjdp{ 475638889Sjdp char *orig = p; 475738889Sjdp valueT val = 0; 475838889Sjdp int loaded = 0; 475938889Sjdp unsigned byte; 476038889Sjdp 476138889Sjdp /* Strip leading sign extensions off the bignum. */ 4762218822Sdim while (size > 1 4763218822Sdim && bignum[size - 1] == LITTLENUM_MASK 4764218822Sdim && bignum[size - 2] > LITTLENUM_MASK / 2) 476538889Sjdp size--; 476638889Sjdp 476738889Sjdp do 476838889Sjdp { 4769218822Sdim /* OR in the next part of the littlenum. */ 4770218822Sdim val |= (*bignum << loaded); 4771218822Sdim loaded += LITTLENUM_NUMBER_OF_BITS; 4772218822Sdim size--; 4773218822Sdim bignum++; 477438889Sjdp 4775218822Sdim /* Add bytes until there are less than 7 bits left in VAL 4776218822Sdim or until every non-sign bit has been written. */ 4777218822Sdim do 477838889Sjdp { 4779218822Sdim byte = val & 0x7f; 4780218822Sdim loaded -= 7; 4781218822Sdim val >>= 7; 4782218822Sdim if (size > 0 4783218822Sdim || val != ((byte & 0x40) == 0 ? 0 : ((valueT) 1 << loaded) - 1)) 478438889Sjdp byte |= 0x80; 4785218822Sdim 4786218822Sdim if (orig) 4787218822Sdim *p = byte; 4788218822Sdim p++; 478938889Sjdp } 4790218822Sdim while ((byte & 0x80) != 0 && loaded >= 7); 4791218822Sdim } 4792218822Sdim while (size > 0); 479338889Sjdp 4794218822Sdim /* Mop up any left-over bits (of which there will be less than 7). */ 4795218822Sdim if ((byte & 0x80) != 0) 4796218822Sdim { 4797218822Sdim /* Sign-extend VAL. */ 4798218822Sdim if (val & (1 << (loaded - 1))) 4799218822Sdim val |= ~0 << loaded; 480038889Sjdp if (orig) 4801218822Sdim *p = val & 0x7f; 480238889Sjdp p++; 480338889Sjdp } 480438889Sjdp 480538889Sjdp return p - orig; 480638889Sjdp} 480738889Sjdp 480860484Sobrienstatic inline int 4809130561Sobrienoutput_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size) 481038889Sjdp{ 481138889Sjdp char *orig = p; 481238889Sjdp valueT val = 0; 481338889Sjdp int loaded = 0; 481438889Sjdp unsigned byte; 481538889Sjdp 481638889Sjdp /* Strip leading zeros off the bignum. */ 481738889Sjdp /* XXX: Is this needed? */ 481877298Sobrien while (size > 0 && bignum[size - 1] == 0) 481938889Sjdp size--; 482038889Sjdp 482138889Sjdp do 482238889Sjdp { 482338889Sjdp if (loaded < 7 && size > 0) 482438889Sjdp { 482538889Sjdp val |= (*bignum << loaded); 482638889Sjdp loaded += 8 * CHARS_PER_LITTLENUM; 482738889Sjdp size--; 482838889Sjdp bignum++; 482938889Sjdp } 483038889Sjdp 483138889Sjdp byte = val & 0x7f; 483238889Sjdp loaded -= 7; 483338889Sjdp val >>= 7; 483438889Sjdp 483538889Sjdp if (size > 0 || val) 483638889Sjdp byte |= 0x80; 483738889Sjdp 483838889Sjdp if (orig) 483938889Sjdp *p = byte; 484038889Sjdp p++; 484138889Sjdp } 484238889Sjdp while (byte & 0x80); 484338889Sjdp 484438889Sjdp return p - orig; 484538889Sjdp} 484638889Sjdp 484760484Sobrienstatic int 4848130561Sobrienoutput_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign) 484938889Sjdp{ 485038889Sjdp if (sign) 485138889Sjdp return output_big_sleb128 (p, bignum, size); 485238889Sjdp else 485338889Sjdp return output_big_uleb128 (p, bignum, size); 485438889Sjdp} 485538889Sjdp 485638889Sjdp/* Generate the appropriate fragments for a given expression to emit a 485738889Sjdp leb128 value. */ 485838889Sjdp 4859218822Sdimstatic void 4860130561Sobrienemit_leb128_expr (expressionS *exp, int sign) 486138889Sjdp{ 486238889Sjdp operatorT op = exp->X_op; 4863218822Sdim unsigned int nbytes; 486438889Sjdp 486538889Sjdp if (op == O_absent || op == O_illegal) 486638889Sjdp { 486760484Sobrien as_warn (_("zero assumed for missing expression")); 486838889Sjdp exp->X_add_number = 0; 486938889Sjdp op = O_constant; 487038889Sjdp } 487138889Sjdp else if (op == O_big && exp->X_add_number <= 0) 487238889Sjdp { 487389857Sobrien as_bad (_("floating point number invalid")); 487438889Sjdp exp->X_add_number = 0; 487538889Sjdp op = O_constant; 487638889Sjdp } 487738889Sjdp else if (op == O_register) 487838889Sjdp { 487960484Sobrien as_warn (_("register value used as expression")); 488038889Sjdp op = O_constant; 488138889Sjdp } 4882218822Sdim else if (op == O_constant 4883218822Sdim && sign 4884218822Sdim && (exp->X_add_number < 0) != !exp->X_unsigned) 4885218822Sdim { 4886218822Sdim /* We're outputting a signed leb128 and the sign of X_add_number 4887218822Sdim doesn't reflect the sign of the original value. Convert EXP 4888218822Sdim to a correctly-extended bignum instead. */ 4889218822Sdim convert_to_bignum (exp); 4890218822Sdim op = O_big; 4891218822Sdim } 489238889Sjdp 489378828Sobrien /* Let check_eh_frame know that data is being emitted. nbytes == -1 is 489478828Sobrien a signal that this is leb128 data. It shouldn't optimize this away. */ 4895218822Sdim nbytes = (unsigned int) -1; 489678828Sobrien if (check_eh_frame (exp, &nbytes)) 489778828Sobrien abort (); 489878828Sobrien 489978828Sobrien /* Let the backend know that subsequent data may be byte aligned. */ 490078828Sobrien#ifdef md_cons_align 490178828Sobrien md_cons_align (1); 490278828Sobrien#endif 490378828Sobrien 490438889Sjdp if (op == O_constant) 490538889Sjdp { 490638889Sjdp /* If we've got a constant, emit the thing directly right now. */ 490738889Sjdp 490838889Sjdp valueT value = exp->X_add_number; 490938889Sjdp int size; 491038889Sjdp char *p; 491138889Sjdp 491238889Sjdp size = sizeof_leb128 (value, sign); 491338889Sjdp p = frag_more (size); 491438889Sjdp output_leb128 (p, value, sign); 491538889Sjdp } 491638889Sjdp else if (op == O_big) 491738889Sjdp { 491838889Sjdp /* O_big is a different sort of constant. */ 491938889Sjdp 492038889Sjdp int size; 492138889Sjdp char *p; 492238889Sjdp 492338889Sjdp size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign); 492438889Sjdp p = frag_more (size); 492538889Sjdp output_big_leb128 (p, generic_bignum, exp->X_add_number, sign); 492638889Sjdp } 492738889Sjdp else 492838889Sjdp { 492977298Sobrien /* Otherwise, we have to create a variable sized fragment and 493038889Sjdp resolve things later. */ 493138889Sjdp 493277298Sobrien frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign, 493338889Sjdp make_expr_symbol (exp), 0, (char *) NULL); 493438889Sjdp } 493538889Sjdp} 493638889Sjdp 493738889Sjdp/* Parse the .sleb128 and .uleb128 pseudos. */ 493838889Sjdp 493938889Sjdpvoid 4940130561Sobriens_leb128 (int sign) 494138889Sjdp{ 494238889Sjdp expressionS exp; 494338889Sjdp 4944130561Sobrien#ifdef md_flush_pending_output 4945130561Sobrien md_flush_pending_output (); 4946130561Sobrien#endif 4947130561Sobrien 494877298Sobrien do 494977298Sobrien { 495077298Sobrien expression (&exp); 495177298Sobrien emit_leb128_expr (&exp, sign); 495277298Sobrien } 495377298Sobrien while (*input_line_pointer++ == ','); 495438889Sjdp 495538889Sjdp input_line_pointer--; 495638889Sjdp demand_empty_rest_of_line (); 495738889Sjdp} 495838889Sjdp 495977298Sobrien/* We read 0 or more ',' separated, double-quoted strings. 496077298Sobrien Caller should have checked need_pass_2 is FALSE because we don't 496177298Sobrien check it. */ 496233965Sjdp 496377298Sobrienvoid 4964130561Sobrienstringer (/* Worker to do .ascii etc statements. */ 4965130561Sobrien /* Checks end-of-line. */ 4966130561Sobrien register int append_zero /* 0: don't append '\0', else 1. */) 496733965Sjdp{ 496833965Sjdp register unsigned int c; 496938889Sjdp char *start; 497033965Sjdp 497133965Sjdp#ifdef md_flush_pending_output 497233965Sjdp md_flush_pending_output (); 497333965Sjdp#endif 497433965Sjdp 497577298Sobrien /* The following awkward logic is to parse ZERO or more strings, 497677298Sobrien comma separated. Recall a string expression includes spaces 497777298Sobrien before the opening '\"' and spaces after the closing '\"'. 497877298Sobrien We fake a leading ',' if there is (supposed to be) 497977298Sobrien a 1st, expression. We keep demanding expressions for each ','. */ 498033965Sjdp if (is_it_end_of_statement ()) 498133965Sjdp { 498277298Sobrien c = 0; /* Skip loop. */ 498377298Sobrien ++input_line_pointer; /* Compensate for end of loop. */ 498433965Sjdp } 498533965Sjdp else 498633965Sjdp { 498777298Sobrien c = ','; /* Do loop. */ 498833965Sjdp } 4989104834Sobrien /* If we have been switched into the abs_section then we 4990104834Sobrien will not have an obstack onto which we can hang strings. */ 4991104834Sobrien if (now_seg == absolute_section) 4992104834Sobrien { 4993104834Sobrien as_bad (_("strings must be placed into a section")); 4994104834Sobrien c = 0; 4995104834Sobrien ignore_rest_of_line (); 4996104834Sobrien } 4997130561Sobrien 499833965Sjdp while (c == ',' || c == '<' || c == '"') 499933965Sjdp { 500033965Sjdp SKIP_WHITESPACE (); 500133965Sjdp switch (*input_line_pointer) 500233965Sjdp { 500333965Sjdp case '\"': 500477298Sobrien ++input_line_pointer; /*->1st char of string. */ 500538889Sjdp start = input_line_pointer; 500633965Sjdp while (is_a_char (c = next_char_of_string ())) 500733965Sjdp { 500833965Sjdp FRAG_APPEND_1_CHAR (c); 500933965Sjdp } 501033965Sjdp if (append_zero) 501133965Sjdp { 501233965Sjdp FRAG_APPEND_1_CHAR (0); 501333965Sjdp } 501433965Sjdp know (input_line_pointer[-1] == '\"'); 501538889Sjdp 501638889Sjdp#ifndef NO_LISTING 501738889Sjdp#ifdef OBJ_ELF 501838889Sjdp /* In ELF, when gcc is emitting DWARF 1 debugging output, it 5019130561Sobrien will emit .string with a filename in the .debug section 5020130561Sobrien after a sequence of constants. See the comment in 5021130561Sobrien emit_expr for the sequence. emit_expr will set 5022130561Sobrien dwarf_file_string to non-zero if this string might be a 5023130561Sobrien source file name. */ 502438889Sjdp if (strcmp (segment_name (now_seg), ".debug") != 0) 502538889Sjdp dwarf_file_string = 0; 502638889Sjdp else if (dwarf_file_string) 502738889Sjdp { 502838889Sjdp c = input_line_pointer[-1]; 502938889Sjdp input_line_pointer[-1] = '\0'; 503038889Sjdp listing_source_file (start); 503138889Sjdp input_line_pointer[-1] = c; 503238889Sjdp } 503338889Sjdp#endif 503438889Sjdp#endif 503538889Sjdp 503633965Sjdp break; 503733965Sjdp case '<': 503833965Sjdp input_line_pointer++; 503933965Sjdp c = get_single_number (); 504033965Sjdp FRAG_APPEND_1_CHAR (c); 504133965Sjdp if (*input_line_pointer != '>') 504233965Sjdp { 504389857Sobrien as_bad (_("expected <nn>")); 504433965Sjdp } 504533965Sjdp input_line_pointer++; 504633965Sjdp break; 504733965Sjdp case ',': 504833965Sjdp input_line_pointer++; 504933965Sjdp break; 505033965Sjdp } 505133965Sjdp SKIP_WHITESPACE (); 505233965Sjdp c = *input_line_pointer; 505333965Sjdp } 505433965Sjdp 505533965Sjdp demand_empty_rest_of_line (); 505633965Sjdp} /* stringer() */ 505733965Sjdp 505833965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the 505933965Sjdp high bits set. We'll probably also have trouble with 506033965Sjdp multibyte chars, wide chars, etc. Also be careful about 506177298Sobrien returning values bigger than 1 byte. xoxorich. */ 506233965Sjdp 506377298Sobrienunsigned int 5064130561Sobriennext_char_of_string (void) 506533965Sjdp{ 506633965Sjdp register unsigned int c; 506733965Sjdp 506833965Sjdp c = *input_line_pointer++ & CHAR_MASK; 506933965Sjdp switch (c) 507033965Sjdp { 507133965Sjdp case '\"': 507233965Sjdp c = NOT_A_CHAR; 507333965Sjdp break; 507433965Sjdp 507533965Sjdp case '\n': 507689857Sobrien as_warn (_("unterminated string; newline inserted")); 507733965Sjdp bump_line_counters (); 507833965Sjdp break; 507933965Sjdp 508033965Sjdp#ifndef NO_STRING_ESCAPES 508133965Sjdp case '\\': 508233965Sjdp switch (c = *input_line_pointer++) 508333965Sjdp { 508433965Sjdp case 'b': 508533965Sjdp c = '\b'; 508633965Sjdp break; 508733965Sjdp 508833965Sjdp case 'f': 508933965Sjdp c = '\f'; 509033965Sjdp break; 509133965Sjdp 509233965Sjdp case 'n': 509333965Sjdp c = '\n'; 509433965Sjdp break; 509533965Sjdp 509633965Sjdp case 'r': 509733965Sjdp c = '\r'; 509833965Sjdp break; 509933965Sjdp 510033965Sjdp case 't': 510133965Sjdp c = '\t'; 510233965Sjdp break; 510333965Sjdp 510433965Sjdp case 'v': 510533965Sjdp c = '\013'; 510633965Sjdp break; 510733965Sjdp 510833965Sjdp case '\\': 510933965Sjdp case '"': 511077298Sobrien break; /* As itself. */ 511133965Sjdp 511233965Sjdp case '0': 511333965Sjdp case '1': 511433965Sjdp case '2': 511533965Sjdp case '3': 511633965Sjdp case '4': 511733965Sjdp case '5': 511833965Sjdp case '6': 511933965Sjdp case '7': 512033965Sjdp case '8': 512133965Sjdp case '9': 512233965Sjdp { 512333965Sjdp long number; 512433965Sjdp int i; 512533965Sjdp 512677298Sobrien for (i = 0, number = 0; 512789857Sobrien ISDIGIT (c) && i < 3; 512877298Sobrien c = *input_line_pointer++, i++) 512933965Sjdp { 513033965Sjdp number = number * 8 + c - '0'; 513133965Sjdp } 513277298Sobrien 513333965Sjdp c = number & 0xff; 513433965Sjdp } 513533965Sjdp --input_line_pointer; 513633965Sjdp break; 513733965Sjdp 513833965Sjdp case 'x': 513933965Sjdp case 'X': 514033965Sjdp { 514133965Sjdp long number; 514233965Sjdp 514333965Sjdp number = 0; 514433965Sjdp c = *input_line_pointer++; 514589857Sobrien while (ISXDIGIT (c)) 514633965Sjdp { 514789857Sobrien if (ISDIGIT (c)) 514833965Sjdp number = number * 16 + c - '0'; 514989857Sobrien else if (ISUPPER (c)) 515033965Sjdp number = number * 16 + c - 'A' + 10; 515133965Sjdp else 515233965Sjdp number = number * 16 + c - 'a' + 10; 515333965Sjdp c = *input_line_pointer++; 515433965Sjdp } 515533965Sjdp c = number & 0xff; 515633965Sjdp --input_line_pointer; 515733965Sjdp } 515833965Sjdp break; 515933965Sjdp 516033965Sjdp case '\n': 516177298Sobrien /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ 516289857Sobrien as_warn (_("unterminated string; newline inserted")); 516333965Sjdp c = '\n'; 516433965Sjdp bump_line_counters (); 516533965Sjdp break; 516633965Sjdp 516733965Sjdp default: 516833965Sjdp 516933965Sjdp#ifdef ONLY_STANDARD_ESCAPES 517089857Sobrien as_bad (_("bad escaped character in string")); 517133965Sjdp c = '?'; 517233965Sjdp#endif /* ONLY_STANDARD_ESCAPES */ 517333965Sjdp 517433965Sjdp break; 517577298Sobrien } 517633965Sjdp break; 517733965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */ 517833965Sjdp 517933965Sjdp default: 518033965Sjdp break; 518177298Sobrien } 518233965Sjdp return (c); 518377298Sobrien} 518433965Sjdp 518533965Sjdpstatic segT 5186130561Sobrienget_segmented_expression (register expressionS *expP) 518733965Sjdp{ 518833965Sjdp register segT retval; 518933965Sjdp 519033965Sjdp retval = expression (expP); 519133965Sjdp if (expP->X_op == O_illegal 519233965Sjdp || expP->X_op == O_absent 519333965Sjdp || expP->X_op == O_big) 519433965Sjdp { 519589857Sobrien as_bad (_("expected address expression")); 519633965Sjdp expP->X_op = O_constant; 519733965Sjdp expP->X_add_number = 0; 519833965Sjdp retval = absolute_section; 519933965Sjdp } 520033965Sjdp return retval; 520133965Sjdp} 520233965Sjdp 520377298Sobrienstatic segT 5204130561Sobrienget_known_segmented_expression (register expressionS *expP) 520533965Sjdp{ 520633965Sjdp register segT retval; 520733965Sjdp 520833965Sjdp if ((retval = get_segmented_expression (expP)) == undefined_section) 520933965Sjdp { 521033965Sjdp /* There is no easy way to extract the undefined symbol from the 521133965Sjdp expression. */ 521233965Sjdp if (expP->X_add_symbol != NULL 521333965Sjdp && S_GET_SEGMENT (expP->X_add_symbol) != expr_section) 521460484Sobrien as_warn (_("symbol \"%s\" undefined; zero assumed"), 521533965Sjdp S_GET_NAME (expP->X_add_symbol)); 521633965Sjdp else 521760484Sobrien as_warn (_("some symbol undefined; zero assumed")); 521833965Sjdp retval = absolute_section; 521933965Sjdp expP->X_op = O_constant; 522033965Sjdp expP->X_add_number = 0; 522133965Sjdp } 522233965Sjdp know (retval == absolute_section || SEG_NORMAL (retval)); 522333965Sjdp return (retval); 522477298Sobrien} 522533965Sjdp 522677298Sobrienchar /* Return terminator. */ 5227130561Sobrienget_absolute_expression_and_terminator (long *val_pointer /* Return value of expression. */) 522833965Sjdp{ 522933965Sjdp /* FIXME: val_pointer should probably be offsetT *. */ 523033965Sjdp *val_pointer = (long) get_absolute_expression (); 523133965Sjdp return (*input_line_pointer++); 523233965Sjdp} 523333965Sjdp 523477298Sobrien/* Like demand_copy_string, but return NULL if the string contains any '\0's. 523577298Sobrien Give a warning if that happens. */ 523677298Sobrien 523733965Sjdpchar * 5238130561Sobriendemand_copy_C_string (int *len_pointer) 523933965Sjdp{ 524033965Sjdp register char *s; 524133965Sjdp 524233965Sjdp if ((s = demand_copy_string (len_pointer)) != 0) 524333965Sjdp { 524433965Sjdp register int len; 524533965Sjdp 524633965Sjdp for (len = *len_pointer; len > 0; len--) 524733965Sjdp { 524833965Sjdp if (*s == 0) 524933965Sjdp { 525033965Sjdp s = 0; 525133965Sjdp len = 1; 525233965Sjdp *len_pointer = 0; 525389857Sobrien as_bad (_("this string may not contain \'\\0\'")); 525433965Sjdp } 525533965Sjdp } 525633965Sjdp } 525777298Sobrien 525833965Sjdp return s; 525933965Sjdp} 526033965Sjdp 526177298Sobrien/* Demand string, but return a safe (=private) copy of the string. 526277298Sobrien Return NULL if we can't read a string here. */ 526377298Sobrien 526433965Sjdpchar * 5265130561Sobriendemand_copy_string (int *lenP) 526633965Sjdp{ 526733965Sjdp register unsigned int c; 526833965Sjdp register int len; 526933965Sjdp char *retval; 527033965Sjdp 527133965Sjdp len = 0; 527233965Sjdp SKIP_WHITESPACE (); 527333965Sjdp if (*input_line_pointer == '\"') 527433965Sjdp { 527577298Sobrien input_line_pointer++; /* Skip opening quote. */ 527633965Sjdp 527733965Sjdp while (is_a_char (c = next_char_of_string ())) 527833965Sjdp { 527933965Sjdp obstack_1grow (¬es, c); 528033965Sjdp len++; 528133965Sjdp } 528233965Sjdp /* JF this next line is so demand_copy_C_string will return a 528377298Sobrien null terminated string. */ 528433965Sjdp obstack_1grow (¬es, '\0'); 528533965Sjdp retval = obstack_finish (¬es); 528633965Sjdp } 528733965Sjdp else 528833965Sjdp { 5289130561Sobrien as_bad (_("missing string")); 529033965Sjdp retval = NULL; 529133965Sjdp ignore_rest_of_line (); 529233965Sjdp } 529333965Sjdp *lenP = len; 529433965Sjdp return (retval); 529577298Sobrien} 529633965Sjdp 529777298Sobrien/* In: Input_line_pointer->next character. 529877298Sobrien 529977298Sobrien Do: Skip input_line_pointer over all whitespace. 530077298Sobrien 530177298Sobrien Out: 1 if input_line_pointer->end-of-line. */ 530277298Sobrien 530377298Sobrienint 5304130561Sobrienis_it_end_of_statement (void) 530533965Sjdp{ 530633965Sjdp SKIP_WHITESPACE (); 530733965Sjdp return (is_end_of_line[(unsigned char) *input_line_pointer]); 530877298Sobrien} 530933965Sjdp 531077298Sobrienvoid 5311130561Sobrienequals (char *sym_name, int reassign) 531233965Sjdp{ 531338889Sjdp char *stop = NULL; 5314218822Sdim char stopc = 0; 531533965Sjdp 531633965Sjdp input_line_pointer++; 531733965Sjdp if (*input_line_pointer == '=') 531833965Sjdp input_line_pointer++; 5319218822Sdim if (reassign < 0 && *input_line_pointer == '=') 5320218822Sdim input_line_pointer++; 532133965Sjdp 532233965Sjdp while (*input_line_pointer == ' ' || *input_line_pointer == '\t') 532333965Sjdp input_line_pointer++; 532433965Sjdp 532533965Sjdp if (flag_mri) 532633965Sjdp stop = mri_comment_field (&stopc); 532733965Sjdp 5328218822Sdim assign_symbol (sym_name, reassign >= 0 ? !reassign : reassign); 532933965Sjdp 533033965Sjdp if (flag_mri) 533177298Sobrien { 5332130561Sobrien demand_empty_rest_of_line (); 533377298Sobrien mri_comment_end (stop, stopc); 533477298Sobrien } 533577298Sobrien} 533633965Sjdp 533789857Sobrien/* .incbin -- include a file verbatim at the current location. */ 533889857Sobrien 533989857Sobrienvoid 5340130561Sobriens_incbin (int x ATTRIBUTE_UNUSED) 534189857Sobrien{ 534289857Sobrien FILE * binfile; 534389857Sobrien char * path; 534489857Sobrien char * filename; 534589857Sobrien char * binfrag; 534689857Sobrien long skip = 0; 534789857Sobrien long count = 0; 534889857Sobrien long bytes; 534989857Sobrien int len; 535089857Sobrien 535189857Sobrien#ifdef md_flush_pending_output 535289857Sobrien md_flush_pending_output (); 535389857Sobrien#endif 535489857Sobrien 535589857Sobrien SKIP_WHITESPACE (); 535689857Sobrien filename = demand_copy_string (& len); 535789857Sobrien if (filename == NULL) 535889857Sobrien return; 535989857Sobrien 536089857Sobrien SKIP_WHITESPACE (); 536189857Sobrien 536289857Sobrien /* Look for optional skip and count. */ 536389857Sobrien if (* input_line_pointer == ',') 536489857Sobrien { 536589857Sobrien ++ input_line_pointer; 536689857Sobrien skip = get_absolute_expression (); 536789857Sobrien 536889857Sobrien SKIP_WHITESPACE (); 536989857Sobrien 537089857Sobrien if (* input_line_pointer == ',') 537189857Sobrien { 537289857Sobrien ++ input_line_pointer; 537389857Sobrien 537489857Sobrien count = get_absolute_expression (); 537589857Sobrien if (count == 0) 537689857Sobrien as_warn (_(".incbin count zero, ignoring `%s'"), filename); 537789857Sobrien 537889857Sobrien SKIP_WHITESPACE (); 537989857Sobrien } 538089857Sobrien } 538189857Sobrien 538289857Sobrien demand_empty_rest_of_line (); 538389857Sobrien 538489857Sobrien /* Try opening absolute path first, then try include dirs. */ 538589857Sobrien binfile = fopen (filename, FOPEN_RB); 538689857Sobrien if (binfile == NULL) 538789857Sobrien { 538889857Sobrien int i; 538989857Sobrien 539089857Sobrien path = xmalloc ((unsigned long) len + include_dir_maxlen + 5); 539189857Sobrien 539289857Sobrien for (i = 0; i < include_dir_count; i++) 539389857Sobrien { 539489857Sobrien sprintf (path, "%s/%s", include_dirs[i], filename); 539589857Sobrien 539689857Sobrien binfile = fopen (path, FOPEN_RB); 539789857Sobrien if (binfile != NULL) 539889857Sobrien break; 539989857Sobrien } 540089857Sobrien 540189857Sobrien if (binfile == NULL) 540289857Sobrien as_bad (_("file not found: %s"), filename); 540389857Sobrien } 540489857Sobrien else 540589857Sobrien path = xstrdup (filename); 540689857Sobrien 540789857Sobrien if (binfile) 540889857Sobrien { 540989857Sobrien long file_len; 541089857Sobrien 541189857Sobrien register_dependency (path); 541289857Sobrien 541389857Sobrien /* Compute the length of the file. */ 541489857Sobrien if (fseek (binfile, 0, SEEK_END) != 0) 541589857Sobrien { 541689857Sobrien as_bad (_("seek to end of .incbin file failed `%s'"), path); 541789857Sobrien goto done; 541889857Sobrien } 541989857Sobrien file_len = ftell (binfile); 542089857Sobrien 5421218822Sdim /* If a count was not specified use the remainder of the file. */ 542289857Sobrien if (count == 0) 5423218822Sdim count = file_len - skip; 542489857Sobrien 5425218822Sdim if (skip < 0 || count < 0 || file_len < 0 || skip + count > file_len) 542689857Sobrien { 5427218822Sdim as_bad (_("skip (%ld) or count (%ld) invalid for file size (%ld)"), 542889857Sobrien skip, count, file_len); 542989857Sobrien goto done; 543089857Sobrien } 543189857Sobrien 543289857Sobrien if (fseek (binfile, skip, SEEK_SET) != 0) 543389857Sobrien { 543489857Sobrien as_bad (_("could not skip to %ld in file `%s'"), skip, path); 543589857Sobrien goto done; 543689857Sobrien } 543789857Sobrien 543889857Sobrien /* Allocate frag space and store file contents in it. */ 543989857Sobrien binfrag = frag_more (count); 544089857Sobrien 544189857Sobrien bytes = fread (binfrag, 1, count, binfile); 544289857Sobrien if (bytes < count) 544389857Sobrien as_warn (_("truncated file `%s', %ld of %ld bytes read"), 544489857Sobrien path, bytes, count); 544589857Sobrien } 544689857Sobriendone: 544789857Sobrien if (binfile != NULL) 544889857Sobrien fclose (binfile); 544989857Sobrien if (path) 545089857Sobrien free (path); 545189857Sobrien} 545289857Sobrien 545377298Sobrien/* .include -- include a file at this point. */ 545433965Sjdp 545577298Sobrienvoid 5456130561Sobriens_include (int arg ATTRIBUTE_UNUSED) 545733965Sjdp{ 545833965Sjdp char *filename; 545933965Sjdp int i; 546033965Sjdp FILE *try; 546133965Sjdp char *path; 546233965Sjdp 546377298Sobrien if (!flag_m68k_mri) 546438889Sjdp { 546538889Sjdp filename = demand_copy_string (&i); 546638889Sjdp if (filename == NULL) 546738889Sjdp { 546838889Sjdp /* demand_copy_string has already printed an error and 5469130561Sobrien called ignore_rest_of_line. */ 547038889Sjdp return; 547138889Sjdp } 547238889Sjdp } 547333965Sjdp else 547433965Sjdp { 547533965Sjdp SKIP_WHITESPACE (); 547633965Sjdp i = 0; 547777298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer] 547833965Sjdp && *input_line_pointer != ' ' 547933965Sjdp && *input_line_pointer != '\t') 548033965Sjdp { 548133965Sjdp obstack_1grow (¬es, *input_line_pointer); 548233965Sjdp ++input_line_pointer; 548333965Sjdp ++i; 548433965Sjdp } 548577298Sobrien 548633965Sjdp obstack_1grow (¬es, '\0'); 548733965Sjdp filename = obstack_finish (¬es); 548877298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 548933965Sjdp ++input_line_pointer; 549033965Sjdp } 549177298Sobrien 549233965Sjdp demand_empty_rest_of_line (); 549333965Sjdp path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ ); 549477298Sobrien 549533965Sjdp for (i = 0; i < include_dir_count; i++) 549633965Sjdp { 549733965Sjdp strcpy (path, include_dirs[i]); 549833965Sjdp strcat (path, "/"); 549933965Sjdp strcat (path, filename); 550089857Sobrien if (0 != (try = fopen (path, FOPEN_RT))) 550133965Sjdp { 550233965Sjdp fclose (try); 550333965Sjdp goto gotit; 550433965Sjdp } 550533965Sjdp } 550677298Sobrien 550733965Sjdp free (path); 550833965Sjdp path = filename; 550933965Sjdpgotit: 551077298Sobrien /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ 551138889Sjdp register_dependency (path); 551260484Sobrien input_scrub_insert_file (path); 551377298Sobrien} 551433965Sjdp 551577298Sobrienvoid 5516130561Sobrienadd_include_dir (char *path) 551733965Sjdp{ 551833965Sjdp int i; 551933965Sjdp 552033965Sjdp if (include_dir_count == 0) 552133965Sjdp { 552233965Sjdp include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs)); 552377298Sobrien include_dirs[0] = "."; /* Current dir. */ 552433965Sjdp include_dir_count = 2; 552533965Sjdp } 552633965Sjdp else 552733965Sjdp { 552833965Sjdp include_dir_count++; 552977298Sobrien include_dirs = 553077298Sobrien (char **) realloc (include_dirs, 553177298Sobrien include_dir_count * sizeof (*include_dirs)); 553233965Sjdp } 553333965Sjdp 553477298Sobrien include_dirs[include_dir_count - 1] = path; /* New one. */ 553533965Sjdp 553633965Sjdp i = strlen (path); 553733965Sjdp if (i > include_dir_maxlen) 553833965Sjdp include_dir_maxlen = i; 553977298Sobrien} 554060484Sobrien 554160484Sobrien/* Output debugging information to denote the source file. */ 554233965Sjdp 554360484Sobrienstatic void 5544130561Sobriengenerate_file_debug (void) 554560484Sobrien{ 554660484Sobrien if (debug_type == DEBUG_STABS) 554760484Sobrien stabs_generate_asm_file (); 554860484Sobrien} 554960484Sobrien 555060484Sobrien/* Output line number debugging information for the current source line. */ 555160484Sobrien 555260484Sobrienvoid 5553130561Sobriengenerate_lineno_debug (void) 555460484Sobrien{ 555560484Sobrien switch (debug_type) 555660484Sobrien { 555760484Sobrien case DEBUG_UNSPECIFIED: 555860484Sobrien case DEBUG_NONE: 555977298Sobrien case DEBUG_DWARF: 556060484Sobrien break; 556160484Sobrien case DEBUG_STABS: 556260484Sobrien stabs_generate_asm_lineno (); 556360484Sobrien break; 556460484Sobrien case DEBUG_ECOFF: 556560484Sobrien ecoff_generate_asm_lineno (); 556660484Sobrien break; 556760484Sobrien case DEBUG_DWARF2: 556877298Sobrien /* ??? We could here indicate to dwarf2dbg.c that something 556977298Sobrien has changed. However, since there is additional backend 557077298Sobrien support that is required (calling dwarf2_emit_insn), we 557177298Sobrien let dwarf2dbg.c call as_where on its own. */ 557260484Sobrien break; 557360484Sobrien } 557460484Sobrien} 557560484Sobrien 557660484Sobrien/* Output debugging information to mark a function entry point or end point. 557760484Sobrien END_P is zero for .func, and non-zero for .endfunc. */ 557860484Sobrien 557960484Sobrienvoid 5580130561Sobriens_func (int end_p) 558160484Sobrien{ 558260484Sobrien do_s_func (end_p, NULL); 558360484Sobrien} 558460484Sobrien 558560484Sobrien/* Subroutine of s_func so targets can choose a different default prefix. 558660484Sobrien If DEFAULT_PREFIX is NULL, use the target's "leading char". */ 558760484Sobrien 5588218822Sdimstatic void 5589130561Sobriendo_s_func (int end_p, const char *default_prefix) 559060484Sobrien{ 559160484Sobrien /* Record the current function so that we can issue an error message for 559260484Sobrien misplaced .func,.endfunc, and also so that .endfunc needs no 559360484Sobrien arguments. */ 559460484Sobrien static char *current_name; 559560484Sobrien static char *current_label; 559660484Sobrien 559760484Sobrien if (end_p) 559860484Sobrien { 559960484Sobrien if (current_name == NULL) 560060484Sobrien { 560160484Sobrien as_bad (_("missing .func")); 560260484Sobrien ignore_rest_of_line (); 560360484Sobrien return; 560460484Sobrien } 560560484Sobrien 560660484Sobrien if (debug_type == DEBUG_STABS) 560760484Sobrien stabs_generate_asm_endfunc (current_name, current_label); 560860484Sobrien 560960484Sobrien current_name = current_label = NULL; 561060484Sobrien } 561160484Sobrien else /* ! end_p */ 561260484Sobrien { 561377298Sobrien char *name, *label; 561477298Sobrien char delim1, delim2; 561560484Sobrien 561660484Sobrien if (current_name != NULL) 561760484Sobrien { 561860484Sobrien as_bad (_(".endfunc missing for previous .func")); 561960484Sobrien ignore_rest_of_line (); 562060484Sobrien return; 562160484Sobrien } 562260484Sobrien 562360484Sobrien name = input_line_pointer; 562460484Sobrien delim1 = get_symbol_end (); 562560484Sobrien name = xstrdup (name); 562660484Sobrien *input_line_pointer = delim1; 562760484Sobrien SKIP_WHITESPACE (); 562860484Sobrien if (*input_line_pointer != ',') 562960484Sobrien { 563060484Sobrien if (default_prefix) 563160484Sobrien asprintf (&label, "%s%s", default_prefix, name); 563260484Sobrien else 563360484Sobrien { 5634218822Sdim char leading_char = bfd_get_symbol_leading_char (stdoutput); 563560484Sobrien /* Missing entry point, use function's name with the leading 563660484Sobrien char prepended. */ 563760484Sobrien if (leading_char) 563860484Sobrien asprintf (&label, "%c%s", leading_char, name); 563960484Sobrien else 564060484Sobrien label = name; 564160484Sobrien } 564260484Sobrien } 564360484Sobrien else 564460484Sobrien { 564560484Sobrien ++input_line_pointer; 564660484Sobrien SKIP_WHITESPACE (); 564760484Sobrien label = input_line_pointer; 564860484Sobrien delim2 = get_symbol_end (); 564960484Sobrien label = xstrdup (label); 565060484Sobrien *input_line_pointer = delim2; 565160484Sobrien } 565260484Sobrien 565360484Sobrien if (debug_type == DEBUG_STABS) 565460484Sobrien stabs_generate_asm_func (name, label); 565560484Sobrien 565660484Sobrien current_name = name; 565760484Sobrien current_label = label; 565860484Sobrien } 565960484Sobrien 566060484Sobrien demand_empty_rest_of_line (); 566160484Sobrien} 566260484Sobrien 566377298Sobrienvoid 5664130561Sobriens_ignore (int arg ATTRIBUTE_UNUSED) 566533965Sjdp{ 5666218822Sdim ignore_rest_of_line (); 566733965Sjdp} 566833965Sjdp 566933965Sjdpvoid 5670130561Sobrienread_print_statistics (FILE *file) 567133965Sjdp{ 567233965Sjdp hash_print_statistics (file, "pseudo-op table", po_hash); 567333965Sjdp} 567433965Sjdp 567577298Sobrien/* Inserts the given line into the input stream. 567677298Sobrien 567760484Sobrien This call avoids macro/conditionals nesting checking, since the contents of 567860484Sobrien the line are assumed to replace the contents of a line already scanned. 567960484Sobrien 5680130561Sobrien An appropriate use of this function would be substitution of input lines when 568160484Sobrien called by md_start_line_hook(). The given line is assumed to already be 568260484Sobrien properly scrubbed. */ 568360484Sobrien 568460484Sobrienvoid 5685130561Sobrieninput_scrub_insert_line (const char *line) 568660484Sobrien{ 568760484Sobrien sb newline; 568860484Sobrien sb_new (&newline); 568960484Sobrien sb_add_string (&newline, line); 569060484Sobrien input_scrub_include_sb (&newline, input_line_pointer, 0); 569160484Sobrien sb_kill (&newline); 569260484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 569360484Sobrien} 569460484Sobrien 569560484Sobrien/* Insert a file into the input stream; the path must resolve to an actual 569677298Sobrien file; no include path searching or dependency registering is performed. */ 569760484Sobrien 569860484Sobrienvoid 5699130561Sobrieninput_scrub_insert_file (char *path) 570060484Sobrien{ 570160484Sobrien input_scrub_include_file (path, input_line_pointer); 570260484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 570360484Sobrien} 5704218822Sdim 5705218822Sdim/* Find the end of a line, considering quotation and escaping of quotes. */ 5706218822Sdim 5707218822Sdim#if !defined(TC_SINGLE_QUOTE_STRINGS) && defined(SINGLE_QUOTE_STRINGS) 5708218822Sdim# define TC_SINGLE_QUOTE_STRINGS 1 5709218822Sdim#endif 5710218822Sdim 5711218822Sdimstatic char * 5712218822Sdim_find_end_of_line (char *s, int mri_string, int insn ATTRIBUTE_UNUSED) 5713218822Sdim{ 5714218822Sdim char inquote = '\0'; 5715218822Sdim int inescape = 0; 5716218822Sdim 5717218822Sdim while (!is_end_of_line[(unsigned char) *s] 5718218822Sdim || (inquote && !ISCNTRL (*s)) 5719218822Sdim || (inquote == '\'' && flag_mri) 5720218822Sdim#ifdef TC_EOL_IN_INSN 5721218822Sdim || (insn && TC_EOL_IN_INSN (s)) 5722218822Sdim#endif 5723218822Sdim ) 5724218822Sdim { 5725218822Sdim if (mri_string && *s == '\'') 5726218822Sdim inquote ^= *s; 5727218822Sdim else if (inescape) 5728218822Sdim inescape = 0; 5729218822Sdim else if (*s == '\\') 5730218822Sdim inescape = 1; 5731218822Sdim else if (!inquote 5732218822Sdim ? *s == '"' 5733218822Sdim#ifdef TC_SINGLE_QUOTE_STRINGS 5734218822Sdim || (TC_SINGLE_QUOTE_STRINGS && *s == '\'') 5735218822Sdim#endif 5736218822Sdim : *s == inquote) 5737218822Sdim inquote ^= *s; 5738218822Sdim ++s; 5739218822Sdim } 5740218822Sdim if (inquote) 5741218822Sdim as_warn (_("missing closing `%c'"), inquote); 5742218822Sdim if (inescape) 5743218822Sdim as_warn (_("stray `\\'")); 5744218822Sdim return s; 5745218822Sdim} 5746218822Sdim 5747218822Sdimchar * 5748218822Sdimfind_end_of_line (char *s, int mri_string) 5749218822Sdim{ 5750218822Sdim return _find_end_of_line (s, mri_string, 0); 5751218822Sdim} 5752