read.c revision 130561
133965Sjdp/* read.c - read a source file - 278828Sobrien Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 3130561Sobrien 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 433965Sjdp 533965SjdpThis file is part of GAS, the GNU Assembler. 633965Sjdp 733965SjdpGAS is free software; you can redistribute it and/or modify 833965Sjdpit under the terms of the GNU General Public License as published by 933965Sjdpthe Free Software Foundation; either version 2, or (at your option) 1033965Sjdpany later version. 1133965Sjdp 1233965SjdpGAS is distributed in the hope that it will be useful, 1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965SjdpGNU General Public License for more details. 1633965Sjdp 1733965SjdpYou should have received a copy of the GNU General Public License 1833965Sjdpalong with GAS; see the file COPYING. If not, write to the Free 1933965SjdpSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2077298Sobrien02111-1307, USA. */ 2133965Sjdp 2233965Sjdp#if 0 2377298Sobrien/* If your chars aren't 8 bits, you will change this a bit. 2477298Sobrien But then, GNU isn't spozed to run on your machine anyway. 2577298Sobrien (RMS is so shortsighted sometimes.) */ 2677298Sobrien#define MASK_CHAR (0xFF) 2733965Sjdp#else 2877298Sobrien#define MASK_CHAR ((int)(unsigned char) -1) 2933965Sjdp#endif 3033965Sjdp 3133965Sjdp/* This is the largest known floating point format (for now). It will 3277298Sobrien grow when we do 4361 style flonums. */ 3333965Sjdp#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) 3433965Sjdp 35130561Sobrien/* Routines that read assembler source text to build spaghetti in memory. 3633965Sjdp Another group of these functions is in the expr.c module. */ 3733965Sjdp 3833965Sjdp#include "as.h" 3989857Sobrien#include "safe-ctype.h" 4033965Sjdp#include "subsegs.h" 4133965Sjdp#include "sb.h" 4233965Sjdp#include "macro.h" 4333965Sjdp#include "obstack.h" 4433965Sjdp#include "listing.h" 4533965Sjdp#include "ecoff.h" 46130561Sobrien#include "dw2gencfi.h" 4733965Sjdp 4833965Sjdp#ifndef TC_START_LABEL 49104834Sobrien#define TC_START_LABEL(x,y) (x == ':') 5033965Sjdp#endif 5133965Sjdp 5260484Sobrien/* Set by the object-format or the target. */ 5360484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT 54130561Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ 5577298Sobrien do \ 56130561Sobrien { \ 57130561Sobrien if ((SIZE) >= 8) \ 58130561Sobrien (P2VAR) = 3; \ 59130561Sobrien else if ((SIZE) >= 4) \ 60130561Sobrien (P2VAR) = 2; \ 61130561Sobrien else if ((SIZE) >= 2) \ 62130561Sobrien (P2VAR) = 1; \ 63130561Sobrien else \ 64130561Sobrien (P2VAR) = 0; \ 6577298Sobrien } \ 6677298Sobrien while (0) 6760484Sobrien#endif 6860484Sobrien 6977298Sobrienchar *input_line_pointer; /*->next char of source file to parse. */ 7033965Sjdp 7133965Sjdp#if BITS_PER_CHAR != 8 7233965Sjdp/* The following table is indexed by[(char)] and will break if 7333965Sjdp a char does not have exactly 256 states (hopefully 0:255!)! */ 7433965Sjdpdie horribly; 7533965Sjdp#endif 7633965Sjdp 7733965Sjdp#ifndef LEX_AT 7833965Sjdp/* The m88k unfortunately uses @ as a label beginner. */ 7933965Sjdp#define LEX_AT 0 8033965Sjdp#endif 8133965Sjdp 8233965Sjdp#ifndef LEX_BR 8333965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */ 8433965Sjdp#define LEX_BR 0 8533965Sjdp#endif 8633965Sjdp 8733965Sjdp#ifndef LEX_PCT 8833965Sjdp/* The Delta 68k assembler permits % inside label names. */ 8933965Sjdp#define LEX_PCT 0 9033965Sjdp#endif 9133965Sjdp 9233965Sjdp#ifndef LEX_QM 9333965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names. */ 9433965Sjdp#define LEX_QM 0 9533965Sjdp#endif 9633965Sjdp 9760484Sobrien#ifndef LEX_HASH 9877298Sobrien/* The IA-64 assembler uses # as a suffix designating a symbol. We include 9977298Sobrien it in the symbol and strip it out in tc_canonicalize_symbol_name. */ 10060484Sobrien#define LEX_HASH 0 10160484Sobrien#endif 10260484Sobrien 10333965Sjdp#ifndef LEX_DOLLAR 10433965Sjdp/* The a29k assembler does not permits labels to start with $. */ 10533965Sjdp#define LEX_DOLLAR 3 10633965Sjdp#endif 10733965Sjdp 10833965Sjdp#ifndef LEX_TILDE 10933965Sjdp/* The Delta 68k assembler permits ~ at start of label names. */ 11033965Sjdp#define LEX_TILDE 0 11133965Sjdp#endif 11233965Sjdp 11377298Sobrien/* Used by is_... macros. our ctype[]. */ 11477298Sobrienchar lex_type[256] = { 11533965Sjdp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ 11633965Sjdp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ 11760484Sobrien 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ 11833965Sjdp 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */ 11933965Sjdp LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ 12033965Sjdp 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */ 12133965Sjdp 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ 12277298Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */ 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, 12560484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12660484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12760484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12860484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12960484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 13060484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 13133965Sjdp}; 13233965Sjdp 13377298Sobrien/* In: a character. 13477298Sobrien Out: 1 if this character ends a line. */ 13577298Sobrienchar is_end_of_line[256] = { 13633965Sjdp#ifdef CR_EOL 13777298Sobrien 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, /* @abcdefghijklmno */ 13833965Sjdp#else 13977298Sobrien 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* @abcdefghijklmno */ 14033965Sjdp#endif 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, /* 0123456789:;<=>? */ 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, /* */ 15077298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 15177298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 15277298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 15377298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 15477298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 15577298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* */ 15633965Sjdp}; 15733965Sjdp 158130561Sobrien#ifndef TC_CASE_SENSITIVE 15977298Sobrienchar original_case_string[128]; 16077298Sobrien#endif 16133965Sjdp 16277298Sobrien/* Functions private to this file. */ 16333965Sjdp 16477298Sobrienstatic char *buffer; /* 1st char of each buffer of lines is here. */ 16577298Sobrienstatic char *buffer_limit; /*->1 + last char in buffer. */ 16677298Sobrien 16777298Sobrien/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 16877298Sobrien in the tc-<CPU>.h file. See the "Porting GAS" section of the 16977298Sobrien internals manual. */ 17033965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN; 17133965Sjdp 17277298Sobrien/* Variables for handling include file directory table. */ 17333965Sjdp 17477298Sobrien/* Table of pointers to directories to search for .include's. */ 17577298Sobrienchar **include_dirs; 17633965Sjdp 17777298Sobrien/* How many are in the table. */ 17877298Sobrienint include_dir_count; 17977298Sobrien 18077298Sobrien/* Length of longest in table. */ 18177298Sobrienint include_dir_maxlen = 1; 18277298Sobrien 18333965Sjdp#ifndef WORKING_DOT_WORD 18433965Sjdpstruct broken_word *broken_words; 18533965Sjdpint new_broken_words; 18633965Sjdp#endif 18733965Sjdp 18833965Sjdp/* The current offset into the absolute section. We don't try to 18933965Sjdp build frags in the absolute section, since no data can be stored 19033965Sjdp there. We just keep track of the current offset. */ 19133965SjdpaddressT abs_section_offset; 19233965Sjdp 19333965Sjdp/* If this line had an MRI style label, it is stored in this variable. 19433965Sjdp This is used by some of the MRI pseudo-ops. */ 19533965SjdpsymbolS *line_label; 19633965Sjdp 19733965Sjdp/* This global variable is used to support MRI common sections. We 19833965Sjdp translate such sections into a common symbol. This variable is 19933965Sjdp non-NULL when we are in an MRI common section. */ 20033965SjdpsymbolS *mri_common_symbol; 20133965Sjdp 20233965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we 20333965Sjdp need to align to an even byte boundary unless the next pseudo-op is 20433965Sjdp dc.b, ds.b, or dcb.b. This variable is set to 1 if an alignment 20533965Sjdp may be needed. */ 20633965Sjdpstatic int mri_pending_align; 20733965Sjdp 20838889Sjdp#ifndef NO_LISTING 20938889Sjdp#ifdef OBJ_ELF 21038889Sjdp/* This variable is set to be non-zero if the next string we see might 21138889Sjdp be the name of the source file in DWARF debugging information. See 21238889Sjdp the comment in emit_expr for the format we look for. */ 21338889Sjdpstatic int dwarf_file_string; 21438889Sjdp#endif 21538889Sjdp#endif 21638889Sjdp 217130561Sobrienstatic void do_align (int, char *, int, int); 218130561Sobrienstatic void s_align (int, int); 219130561Sobrienstatic int hex_float (int, char *); 220130561Sobrienstatic segT get_known_segmented_expression (expressionS * expP); 221130561Sobrienstatic void pobegin (void); 222130561Sobrienstatic int get_line_sb (sb *); 223130561Sobrienstatic void generate_file_debug (void); 22433965Sjdp 22533965Sjdpvoid 226130561Sobrienread_begin (void) 22733965Sjdp{ 22833965Sjdp const char *p; 22933965Sjdp 23033965Sjdp pobegin (); 23133965Sjdp obj_read_begin_hook (); 23233965Sjdp 23333965Sjdp /* Something close -- but not too close -- to a multiple of 1024. 23433965Sjdp The debugging malloc I'm using has 24 bytes of overhead. */ 23533965Sjdp obstack_begin (¬es, chunksize); 23633965Sjdp obstack_begin (&cond_obstack, chunksize); 23733965Sjdp 23877298Sobrien /* Use machine dependent syntax. */ 23933965Sjdp for (p = line_separator_chars; *p; p++) 24033965Sjdp is_end_of_line[(unsigned char) *p] = 1; 24177298Sobrien /* Use more. FIXME-SOMEDAY. */ 24233965Sjdp 24333965Sjdp if (flag_mri) 24433965Sjdp lex_type['?'] = 3; 24533965Sjdp} 24633965Sjdp 24777298Sobrien/* Set up pseudo-op tables. */ 24833965Sjdp 24933965Sjdpstatic struct hash_control *po_hash; 25033965Sjdp 25177298Sobrienstatic const pseudo_typeS potable[] = { 25233965Sjdp {"abort", s_abort, 0}, 25333965Sjdp {"align", s_align_ptwo, 0}, 25433965Sjdp {"ascii", stringer, 0}, 25533965Sjdp {"asciz", stringer, 1}, 25633965Sjdp {"balign", s_align_bytes, 0}, 25733965Sjdp {"balignw", s_align_bytes, -2}, 25833965Sjdp {"balignl", s_align_bytes, -4}, 25977298Sobrien/* block */ 26033965Sjdp {"byte", cons, 1}, 26133965Sjdp {"comm", s_comm, 0}, 26233965Sjdp {"common", s_mri_common, 0}, 26333965Sjdp {"common.s", s_mri_common, 1}, 26433965Sjdp {"data", s_data, 0}, 26533965Sjdp {"dc", cons, 2}, 26633965Sjdp {"dc.b", cons, 1}, 26733965Sjdp {"dc.d", float_cons, 'd'}, 26833965Sjdp {"dc.l", cons, 4}, 26933965Sjdp {"dc.s", float_cons, 'f'}, 27033965Sjdp {"dc.w", cons, 2}, 27133965Sjdp {"dc.x", float_cons, 'x'}, 27233965Sjdp {"dcb", s_space, 2}, 27333965Sjdp {"dcb.b", s_space, 1}, 27433965Sjdp {"dcb.d", s_float_space, 'd'}, 27533965Sjdp {"dcb.l", s_space, 4}, 27633965Sjdp {"dcb.s", s_float_space, 'f'}, 27733965Sjdp {"dcb.w", s_space, 2}, 27833965Sjdp {"dcb.x", s_float_space, 'x'}, 27933965Sjdp {"ds", s_space, 2}, 28033965Sjdp {"ds.b", s_space, 1}, 28133965Sjdp {"ds.d", s_space, 8}, 28233965Sjdp {"ds.l", s_space, 4}, 28333965Sjdp {"ds.p", s_space, 12}, 28433965Sjdp {"ds.s", s_space, 4}, 28533965Sjdp {"ds.w", s_space, 2}, 28633965Sjdp {"ds.x", s_space, 12}, 28733965Sjdp {"debug", s_ignore, 0}, 28833965Sjdp#ifdef S_SET_DESC 28933965Sjdp {"desc", s_desc, 0}, 29033965Sjdp#endif 29177298Sobrien/* dim */ 29233965Sjdp {"double", float_cons, 'd'}, 29377298Sobrien/* dsect */ 29477298Sobrien {"eject", listing_eject, 0}, /* Formfeed listing. */ 29533965Sjdp {"else", s_else, 0}, 29633965Sjdp {"elsec", s_else, 0}, 29760484Sobrien {"elseif", s_elseif, (int) O_ne}, 29833965Sjdp {"end", s_end, 0}, 29933965Sjdp {"endc", s_endif, 0}, 30060484Sobrien {"endfunc", s_func, 1}, 30133965Sjdp {"endif", s_endif, 0}, 30289857Sobrien {"endr", s_bad_endr, 0}, 30377298Sobrien/* endef */ 30433965Sjdp {"equ", s_set, 0}, 30533965Sjdp {"equiv", s_set, 1}, 30633965Sjdp {"err", s_err, 0}, 30733965Sjdp {"exitm", s_mexit, 0}, 30877298Sobrien/* extend */ 30977298Sobrien {"extern", s_ignore, 0}, /* We treat all undef as ext. */ 31033965Sjdp {"appfile", s_app_file, 1}, 31133965Sjdp {"appline", s_app_line, 0}, 31233965Sjdp {"fail", s_fail, 0}, 31333965Sjdp {"file", s_app_file, 0}, 31433965Sjdp {"fill", s_fill, 0}, 31533965Sjdp {"float", float_cons, 'f'}, 31633965Sjdp {"format", s_ignore, 0}, 31760484Sobrien {"func", s_func, 0}, 31833965Sjdp {"global", s_globl, 0}, 31933965Sjdp {"globl", s_globl, 0}, 32033965Sjdp {"hword", cons, 2}, 32133965Sjdp {"if", s_if, (int) O_ne}, 32233965Sjdp {"ifc", s_ifc, 0}, 32333965Sjdp {"ifdef", s_ifdef, 0}, 32433965Sjdp {"ifeq", s_if, (int) O_eq}, 32533965Sjdp {"ifeqs", s_ifeqs, 0}, 32633965Sjdp {"ifge", s_if, (int) O_ge}, 32733965Sjdp {"ifgt", s_if, (int) O_gt}, 32833965Sjdp {"ifle", s_if, (int) O_le}, 32933965Sjdp {"iflt", s_if, (int) O_lt}, 33033965Sjdp {"ifnc", s_ifc, 1}, 33133965Sjdp {"ifndef", s_ifdef, 1}, 33233965Sjdp {"ifne", s_if, (int) O_ne}, 33333965Sjdp {"ifnes", s_ifeqs, 1}, 33433965Sjdp {"ifnotdef", s_ifdef, 1}, 33589857Sobrien {"incbin", s_incbin, 0}, 33633965Sjdp {"include", s_include, 0}, 33733965Sjdp {"int", cons, 4}, 33833965Sjdp {"irp", s_irp, 0}, 33933965Sjdp {"irep", s_irp, 0}, 34033965Sjdp {"irpc", s_irp, 1}, 34133965Sjdp {"irepc", s_irp, 1}, 34233965Sjdp {"lcomm", s_lcomm, 0}, 34377298Sobrien {"lflags", listing_flags, 0}, /* Listing flags. */ 34433965Sjdp {"linkonce", s_linkonce, 0}, 34577298Sobrien {"list", listing_list, 1}, /* Turn listing on. */ 34633965Sjdp {"llen", listing_psize, 1}, 34733965Sjdp {"long", cons, 4}, 34833965Sjdp {"lsym", s_lsym, 0}, 34933965Sjdp {"macro", s_macro, 0}, 35033965Sjdp {"mexit", s_mexit, 0}, 35133965Sjdp {"mri", s_mri, 0}, 35233965Sjdp {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */ 35333965Sjdp {"name", s_ignore, 0}, 35433965Sjdp {"noformat", s_ignore, 0}, 35577298Sobrien {"nolist", listing_list, 0}, /* Turn listing off. */ 35633965Sjdp {"nopage", listing_nopage, 0}, 35733965Sjdp {"octa", cons, 16}, 35833965Sjdp {"offset", s_struct, 0}, 35933965Sjdp {"org", s_org, 0}, 36033965Sjdp {"p2align", s_align_ptwo, 0}, 36133965Sjdp {"p2alignw", s_align_ptwo, -2}, 36233965Sjdp {"p2alignl", s_align_ptwo, -4}, 36333965Sjdp {"page", listing_eject, 0}, 36433965Sjdp {"plen", listing_psize, 0}, 36533965Sjdp {"print", s_print, 0}, 36677298Sobrien {"psize", listing_psize, 0}, /* Set paper size. */ 36733965Sjdp {"purgem", s_purgem, 0}, 36833965Sjdp {"quad", cons, 8}, 36933965Sjdp {"rep", s_rept, 0}, 37033965Sjdp {"rept", s_rept, 0}, 37133965Sjdp {"rva", s_rva, 4}, 37277298Sobrien {"sbttl", listing_title, 1}, /* Subtitle of listing. */ 37377298Sobrien/* scl */ 37477298Sobrien/* sect */ 37533965Sjdp {"set", s_set, 0}, 37633965Sjdp {"short", cons, 2}, 37733965Sjdp {"single", float_cons, 'f'}, 37877298Sobrien/* size */ 37933965Sjdp {"space", s_space, 0}, 38033965Sjdp {"skip", s_space, 0}, 38138889Sjdp {"sleb128", s_leb128, 1}, 38233965Sjdp {"spc", s_ignore, 0}, 38333965Sjdp {"stabd", s_stab, 'd'}, 38433965Sjdp {"stabn", s_stab, 'n'}, 38533965Sjdp {"stabs", s_stab, 's'}, 38633965Sjdp {"string", stringer, 1}, 38733965Sjdp {"struct", s_struct, 0}, 38877298Sobrien/* tag */ 38933965Sjdp {"text", s_text, 0}, 39033965Sjdp 39133965Sjdp /* This is for gcc to use. It's only just been added (2/94), so gcc 39233965Sjdp won't be able to use it for a while -- probably a year or more. 39333965Sjdp But once this has been released, check with gcc maintainers 39433965Sjdp before deleting it or even changing the spelling. */ 39533965Sjdp {"this_GCC_requires_the_GNU_assembler", s_ignore, 0}, 39633965Sjdp /* If we're folding case -- done for some targets, not necessarily 39733965Sjdp all -- the above string in an input file will be converted to 39833965Sjdp this one. Match it either way... */ 39933965Sjdp {"this_gcc_requires_the_gnu_assembler", s_ignore, 0}, 40033965Sjdp 40177298Sobrien {"title", listing_title, 0}, /* Listing title. */ 40233965Sjdp {"ttl", listing_title, 0}, 40377298Sobrien/* type */ 40438889Sjdp {"uleb128", s_leb128, 0}, 40577298Sobrien/* use */ 40677298Sobrien/* val */ 40733965Sjdp {"xcom", s_comm, 0}, 40833965Sjdp {"xdef", s_globl, 0}, 40933965Sjdp {"xref", s_ignore, 0}, 41033965Sjdp {"xstabs", s_xstab, 's'}, 41133965Sjdp {"word", cons, 2}, 41233965Sjdp {"zero", s_space, 0}, 41377298Sobrien {NULL, NULL, 0} /* End sentinel. */ 41433965Sjdp}; 41533965Sjdp 41633965Sjdpstatic int pop_override_ok = 0; 41733965Sjdpstatic const char *pop_table_name; 41833965Sjdp 41933965Sjdpvoid 420130561Sobrienpop_insert (const pseudo_typeS *table) 42133965Sjdp{ 42233965Sjdp const char *errtxt; 42333965Sjdp const pseudo_typeS *pop; 42433965Sjdp for (pop = table; pop->poc_name; pop++) 42533965Sjdp { 42633965Sjdp errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); 42733965Sjdp if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists"))) 42860484Sobrien as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name, 42933965Sjdp errtxt); 43033965Sjdp } 43133965Sjdp} 43233965Sjdp 43333965Sjdp#ifndef md_pop_insert 43433965Sjdp#define md_pop_insert() pop_insert(md_pseudo_table) 43533965Sjdp#endif 43633965Sjdp 43733965Sjdp#ifndef obj_pop_insert 43833965Sjdp#define obj_pop_insert() pop_insert(obj_pseudo_table) 43933965Sjdp#endif 44033965Sjdp 441130561Sobrien#ifndef cfi_pop_insert 442130561Sobrien#define cfi_pop_insert() pop_insert(cfi_pseudo_table) 443130561Sobrien#endif 444130561Sobrien 44577298Sobrienstatic void 446130561Sobrienpobegin (void) 44733965Sjdp{ 44833965Sjdp po_hash = hash_new (); 44933965Sjdp 45077298Sobrien /* Do the target-specific pseudo ops. */ 45133965Sjdp pop_table_name = "md"; 45233965Sjdp md_pop_insert (); 45333965Sjdp 45477298Sobrien /* Now object specific. Skip any that were in the target table. */ 45533965Sjdp pop_table_name = "obj"; 45633965Sjdp pop_override_ok = 1; 45733965Sjdp obj_pop_insert (); 45833965Sjdp 45977298Sobrien /* Now portable ones. Skip any that we've seen already. */ 46033965Sjdp pop_table_name = "standard"; 46133965Sjdp pop_insert (potable); 462130561Sobrien 463130561Sobrien#ifdef TARGET_USE_CFIPOP 464130561Sobrien pop_table_name = "cfi"; 465130561Sobrien pop_override_ok = 1; 466130561Sobrien cfi_pop_insert (); 467130561Sobrien#endif 46833965Sjdp} 46933965Sjdp 47033965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY() \ 47133965Sjdp if (ignore_input ()) \ 47233965Sjdp { \ 47377298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer++]) \ 47433965Sjdp if (input_line_pointer == buffer_limit) \ 47533965Sjdp break; \ 47633965Sjdp continue; \ 47733965Sjdp } 47833965Sjdp 47933965Sjdp/* This function is used when scrubbing the characters between #APP 48033965Sjdp and #NO_APP. */ 48133965Sjdp 48233965Sjdpstatic char *scrub_string; 48333965Sjdpstatic char *scrub_string_end; 48433965Sjdp 48533965Sjdpstatic int 486130561Sobrienscrub_from_string (char *buf, int buflen) 48733965Sjdp{ 48860484Sobrien int copy; 48933965Sjdp 49060484Sobrien copy = scrub_string_end - scrub_string; 49160484Sobrien if (copy > buflen) 49260484Sobrien copy = buflen; 49360484Sobrien memcpy (buf, scrub_string, copy); 49460484Sobrien scrub_string += copy; 49560484Sobrien return copy; 49633965Sjdp} 49733965Sjdp 49877298Sobrien/* We read the file, putting things into a web that represents what we 49977298Sobrien have been reading. */ 50077298Sobrienvoid 501130561Sobrienread_a_source_file (char *name) 50233965Sjdp{ 50333965Sjdp register char c; 50477298Sobrien register char *s; /* String of symbol, '\0' appended. */ 50533965Sjdp register int temp; 50633965Sjdp pseudo_typeS *pop; 50733965Sjdp 50877298Sobrien#ifdef WARN_COMMENTS 50977298Sobrien found_comment = 0; 51077298Sobrien#endif 51177298Sobrien 51233965Sjdp buffer = input_scrub_new_file (name); 51333965Sjdp 51433965Sjdp listing_file (name); 51538889Sjdp listing_newline (NULL); 51638889Sjdp register_dependency (name); 51733965Sjdp 51860484Sobrien /* Generate debugging information before we've read anything in to denote 51960484Sobrien this file as the "main" source file and not a subordinate one 52060484Sobrien (e.g. N_SO vs N_SOL in stabs). */ 52160484Sobrien generate_file_debug (); 52260484Sobrien 52333965Sjdp while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0) 52477298Sobrien { /* We have another line to parse. */ 52577298Sobrien know (buffer_limit[-1] == '\n'); /* Must have a sentinel. */ 526130561Sobrien 52733965Sjdp while (input_line_pointer < buffer_limit) 52833965Sjdp { 52977298Sobrien /* We have more of this buffer to parse. */ 53033965Sjdp 53177298Sobrien /* We now have input_line_pointer->1st char of next line. 53277298Sobrien If input_line_pointer [-1] == '\n' then we just 53377298Sobrien scanned another line: so bump line counters. */ 53433965Sjdp if (is_end_of_line[(unsigned char) input_line_pointer[-1]]) 53533965Sjdp { 53633965Sjdp#ifdef md_start_line_hook 53733965Sjdp md_start_line_hook (); 53833965Sjdp#endif 53933965Sjdp if (input_line_pointer[-1] == '\n') 54033965Sjdp bump_line_counters (); 54133965Sjdp 54233965Sjdp line_label = NULL; 54333965Sjdp 54460484Sobrien if (LABELS_WITHOUT_COLONS || flag_m68k_mri) 54533965Sjdp { 54633965Sjdp /* Text at the start of a line must be a label, we 54733965Sjdp run down and stick a colon in. */ 54833965Sjdp if (is_name_beginner (*input_line_pointer)) 54933965Sjdp { 55033965Sjdp char *line_start = input_line_pointer; 55133965Sjdp char c; 55233965Sjdp int mri_line_macro; 55333965Sjdp 55433965Sjdp LISTING_NEWLINE (); 55533965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 55633965Sjdp 55733965Sjdp c = get_symbol_end (); 55833965Sjdp 55933965Sjdp /* In MRI mode, the EQU and MACRO pseudoops must 56033965Sjdp be handled specially. */ 56133965Sjdp mri_line_macro = 0; 56233965Sjdp if (flag_m68k_mri) 56333965Sjdp { 56433965Sjdp char *rest = input_line_pointer + 1; 56533965Sjdp 56633965Sjdp if (*rest == ':') 56733965Sjdp ++rest; 56833965Sjdp if (*rest == ' ' || *rest == '\t') 56933965Sjdp ++rest; 57033965Sjdp if ((strncasecmp (rest, "EQU", 3) == 0 57133965Sjdp || strncasecmp (rest, "SET", 3) == 0) 57233965Sjdp && (rest[3] == ' ' || rest[3] == '\t')) 57333965Sjdp { 57433965Sjdp input_line_pointer = rest + 3; 57533965Sjdp equals (line_start, 57633965Sjdp strncasecmp (rest, "SET", 3) == 0); 57733965Sjdp continue; 57833965Sjdp } 57933965Sjdp if (strncasecmp (rest, "MACRO", 5) == 0 58033965Sjdp && (rest[5] == ' ' 58133965Sjdp || rest[5] == '\t' 58233965Sjdp || is_end_of_line[(unsigned char) rest[5]])) 58333965Sjdp mri_line_macro = 1; 58433965Sjdp } 58533965Sjdp 58633965Sjdp /* In MRI mode, we need to handle the MACRO 587130561Sobrien pseudo-op specially: we don't want to put the 588130561Sobrien symbol in the symbol table. */ 58977298Sobrien if (!mri_line_macro 59060484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON 59177298Sobrien && TC_START_LABEL_WITHOUT_COLON(c, 59277298Sobrien input_line_pointer) 59360484Sobrien#endif 59477298Sobrien ) 59533965Sjdp line_label = colon (line_start); 59633965Sjdp else 59733965Sjdp line_label = symbol_create (line_start, 59833965Sjdp absolute_section, 59933965Sjdp (valueT) 0, 60033965Sjdp &zero_address_frag); 60133965Sjdp 60233965Sjdp *input_line_pointer = c; 60333965Sjdp if (c == ':') 60433965Sjdp input_line_pointer++; 60533965Sjdp } 60633965Sjdp } 60733965Sjdp } 60833965Sjdp 609130561Sobrien /* We are at the beginning of a line, or similar place. 61077298Sobrien We expect a well-formed assembler statement. 61177298Sobrien A "symbol-name:" is a statement. 61277298Sobrien 61377298Sobrien Depending on what compiler is used, the order of these tests 61477298Sobrien may vary to catch most common case 1st. 61577298Sobrien Each test is independent of all other tests at the (top) level. 61677298Sobrien PLEASE make a compiler that doesn't use this assembler. 61777298Sobrien It is crufty to waste a compiler's time encoding things for this 61877298Sobrien assembler, which then wastes more time decoding it. 61977298Sobrien (And communicating via (linear) files is silly! 62077298Sobrien If you must pass stuff, please pass a tree!) */ 62133965Sjdp if ((c = *input_line_pointer++) == '\t' 62233965Sjdp || c == ' ' 62333965Sjdp || c == '\f' 62433965Sjdp || c == 0) 62577298Sobrien c = *input_line_pointer++; 62638889Sjdp 62777298Sobrien know (c != ' '); /* No further leading whitespace. */ 62877298Sobrien 62938889Sjdp#ifndef NO_LISTING 63038889Sjdp /* If listing is on, and we are expanding a macro, then give 63138889Sjdp the listing code the contents of the expanded line. */ 63238889Sjdp if (listing) 63338889Sjdp { 63438889Sjdp if ((listing & LISTING_MACEXP) && macro_nest > 0) 63538889Sjdp { 63638889Sjdp char *copy; 63738889Sjdp int len; 63838889Sjdp 63938889Sjdp /* Find the end of the current expanded macro line. */ 64077298Sobrien for (s = input_line_pointer - 1; *s; ++s) 64138889Sjdp if (is_end_of_line[(unsigned char) *s]) 64238889Sjdp break; 64338889Sjdp 64438889Sjdp /* Copy it for safe keeping. Also give an indication of 64538889Sjdp how much macro nesting is involved at this point. */ 64677298Sobrien len = s - (input_line_pointer - 1); 64738889Sjdp copy = (char *) xmalloc (len + macro_nest + 2); 64838889Sjdp memset (copy, '>', macro_nest); 64938889Sjdp copy[macro_nest] = ' '; 65077298Sobrien memcpy (copy + macro_nest + 1, input_line_pointer - 1, len); 65177298Sobrien copy[macro_nest + 1 + len] = '\0'; 65238889Sjdp 65338889Sjdp /* Install the line with the listing facility. */ 65438889Sjdp listing_newline (copy); 65538889Sjdp } 65638889Sjdp else 65738889Sjdp listing_newline (NULL); 65838889Sjdp } 65938889Sjdp#endif 66077298Sobrien /* C is the 1st significant character. 66177298Sobrien Input_line_pointer points after that character. */ 66233965Sjdp if (is_name_beginner (c)) 66333965Sjdp { 66477298Sobrien /* Want user-defined label or pseudo/opcode. */ 66533965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 66633965Sjdp 66733965Sjdp s = --input_line_pointer; 66877298Sobrien c = get_symbol_end (); /* name's delimiter. */ 66977298Sobrien 67077298Sobrien /* C is character after symbol. 671130561Sobrien That character's place in the input line is now '\0'. 672130561Sobrien S points to the beginning of the symbol. 673130561Sobrien [In case of pseudo-op, s->'.'.] 674130561Sobrien Input_line_pointer->'\0' where c was. */ 67577298Sobrien if (TC_START_LABEL (c, input_line_pointer)) 67633965Sjdp { 67733965Sjdp if (flag_m68k_mri) 67833965Sjdp { 67933965Sjdp char *rest = input_line_pointer + 1; 68033965Sjdp 68133965Sjdp /* In MRI mode, \tsym: set 0 is permitted. */ 68233965Sjdp if (*rest == ':') 68333965Sjdp ++rest; 68477298Sobrien 68533965Sjdp if (*rest == ' ' || *rest == '\t') 68633965Sjdp ++rest; 68777298Sobrien 68833965Sjdp if ((strncasecmp (rest, "EQU", 3) == 0 68933965Sjdp || strncasecmp (rest, "SET", 3) == 0) 69033965Sjdp && (rest[3] == ' ' || rest[3] == '\t')) 69133965Sjdp { 69233965Sjdp input_line_pointer = rest + 3; 69333965Sjdp equals (s, 1); 69433965Sjdp continue; 69533965Sjdp } 69633965Sjdp } 69733965Sjdp 69877298Sobrien line_label = colon (s); /* User-defined label. */ 69977298Sobrien /* Put ':' back for error messages' sake. */ 70077298Sobrien *input_line_pointer++ = ':'; 701130561Sobrien#ifdef tc_check_label 702130561Sobrien tc_check_label (line_label); 703130561Sobrien#endif 70477298Sobrien /* Input_line_pointer->after ':'. */ 70533965Sjdp SKIP_WHITESPACE (); 70633965Sjdp } 70733965Sjdp else if (c == '=' 70833965Sjdp || ((c == ' ' || c == '\t') 70933965Sjdp && input_line_pointer[1] == '=' 71033965Sjdp#ifdef TC_EQUAL_IN_INSN 71177298Sobrien && !TC_EQUAL_IN_INSN (c, input_line_pointer) 71233965Sjdp#endif 71333965Sjdp )) 71433965Sjdp { 71533965Sjdp equals (s, 1); 71633965Sjdp demand_empty_rest_of_line (); 71733965Sjdp } 71833965Sjdp else 71977298Sobrien { 72077298Sobrien /* Expect pseudo-op or machine instruction. */ 72133965Sjdp pop = NULL; 72233965Sjdp 723130561Sobrien#ifndef TC_CASE_SENSITIVE 72433965Sjdp { 72533965Sjdp char *s2 = s; 72677298Sobrien 72777298Sobrien strncpy (original_case_string, s2, sizeof (original_case_string)); 72877298Sobrien original_case_string[sizeof (original_case_string) - 1] = 0; 72977298Sobrien 73033965Sjdp while (*s2) 73133965Sjdp { 73289857Sobrien *s2 = TOLOWER (*s2); 73333965Sjdp s2++; 73433965Sjdp } 73533965Sjdp } 73633965Sjdp#endif 73760484Sobrien if (NO_PSEUDO_DOT || flag_m68k_mri) 73833965Sjdp { 73933965Sjdp /* The MRI assembler and the m88k use pseudo-ops 740130561Sobrien without a period. */ 74133965Sjdp pop = (pseudo_typeS *) hash_find (po_hash, s); 74233965Sjdp if (pop != NULL && pop->poc_handler == NULL) 74333965Sjdp pop = NULL; 74433965Sjdp } 74533965Sjdp 74633965Sjdp if (pop != NULL 74777298Sobrien || (!flag_m68k_mri && *s == '.')) 74833965Sjdp { 74977298Sobrien /* PSEUDO - OP. 75033965Sjdp 751130561Sobrien WARNING: c has next char, which may be end-of-line. 752130561Sobrien We lookup the pseudo-op table with s+1 because we 753130561Sobrien already know that the pseudo-op begins with a '.'. */ 75477298Sobrien 75533965Sjdp if (pop == NULL) 75633965Sjdp pop = (pseudo_typeS *) hash_find (po_hash, s + 1); 757130561Sobrien if (pop && !pop->poc_handler) 758130561Sobrien pop = NULL; 75933965Sjdp 76033965Sjdp /* In MRI mode, we may need to insert an 761130561Sobrien automatic alignment directive. What a hack 762130561Sobrien this is. */ 76333965Sjdp if (mri_pending_align 76433965Sjdp && (pop == NULL 76577298Sobrien || !((pop->poc_handler == cons 76677298Sobrien && pop->poc_val == 1) 76777298Sobrien || (pop->poc_handler == s_space 76877298Sobrien && pop->poc_val == 1) 76933965Sjdp#ifdef tc_conditional_pseudoop 77077298Sobrien || tc_conditional_pseudoop (pop) 77133965Sjdp#endif 77277298Sobrien || pop->poc_handler == s_if 77377298Sobrien || pop->poc_handler == s_ifdef 77477298Sobrien || pop->poc_handler == s_ifc 77577298Sobrien || pop->poc_handler == s_ifeqs 77677298Sobrien || pop->poc_handler == s_else 77777298Sobrien || pop->poc_handler == s_endif 77877298Sobrien || pop->poc_handler == s_globl 77977298Sobrien || pop->poc_handler == s_ignore))) 78033965Sjdp { 78133965Sjdp do_align (1, (char *) NULL, 0, 0); 78233965Sjdp mri_pending_align = 0; 78377298Sobrien 78433965Sjdp if (line_label != NULL) 78533965Sjdp { 78660484Sobrien symbol_set_frag (line_label, frag_now); 78733965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 78833965Sjdp } 78933965Sjdp } 79033965Sjdp 79177298Sobrien /* Print the error msg now, while we still can. */ 79233965Sjdp if (pop == NULL) 79333965Sjdp { 79489857Sobrien as_bad (_("unknown pseudo-op: `%s'"), s); 79533965Sjdp *input_line_pointer = c; 79633965Sjdp s_ignore (0); 79733965Sjdp continue; 79833965Sjdp } 79933965Sjdp 80077298Sobrien /* Put it back for error messages etc. */ 80133965Sjdp *input_line_pointer = c; 80233965Sjdp /* The following skip of whitespace is compulsory. 80333965Sjdp A well shaped space is sometimes all that separates 80477298Sobrien keyword from operands. */ 80533965Sjdp if (c == ' ' || c == '\t') 80633965Sjdp input_line_pointer++; 80777298Sobrien 80877298Sobrien /* Input_line is restored. 809130561Sobrien Input_line_pointer->1st non-blank char 810130561Sobrien after pseudo-operation. */ 81133965Sjdp (*pop->poc_handler) (pop->poc_val); 81233965Sjdp 81333965Sjdp /* If that was .end, just get out now. */ 81433965Sjdp if (pop->poc_handler == s_end) 81533965Sjdp goto quit; 81633965Sjdp } 81733965Sjdp else 81833965Sjdp { 81933965Sjdp int inquote = 0; 82060484Sobrien#ifdef QUOTES_IN_INSN 82160484Sobrien int inescape = 0; 82260484Sobrien#endif 82333965Sjdp 82477298Sobrien /* WARNING: c has char, which may be end-of-line. */ 82577298Sobrien /* Also: input_line_pointer->`\0` where c was. */ 82633965Sjdp *input_line_pointer = c; 82733965Sjdp while (!is_end_of_line[(unsigned char) *input_line_pointer] 82833965Sjdp || inquote 82933965Sjdp#ifdef TC_EOL_IN_INSN 83033965Sjdp || TC_EOL_IN_INSN (input_line_pointer) 83133965Sjdp#endif 83233965Sjdp ) 83333965Sjdp { 83433965Sjdp if (flag_m68k_mri && *input_line_pointer == '\'') 83577298Sobrien inquote = !inquote; 83660484Sobrien#ifdef QUOTES_IN_INSN 83760484Sobrien if (inescape) 83860484Sobrien inescape = 0; 83960484Sobrien else if (*input_line_pointer == '"') 84077298Sobrien inquote = !inquote; 84160484Sobrien else if (*input_line_pointer == '\\') 84260484Sobrien inescape = 1; 84360484Sobrien#endif 84433965Sjdp input_line_pointer++; 84533965Sjdp } 84633965Sjdp 84733965Sjdp c = *input_line_pointer; 84833965Sjdp *input_line_pointer = '\0'; 84933965Sjdp 85060484Sobrien generate_lineno_debug (); 85138889Sjdp 85233965Sjdp if (macro_defined) 85333965Sjdp { 85433965Sjdp sb out; 85533965Sjdp const char *err; 85677298Sobrien macro_entry *macro; 85733965Sjdp 858130561Sobrien if (check_macro (s, &out, &err, ¯o)) 85933965Sjdp { 86033965Sjdp if (err != NULL) 86160484Sobrien as_bad ("%s", err); 86233965Sjdp *input_line_pointer++ = c; 86333965Sjdp input_scrub_include_sb (&out, 86460484Sobrien input_line_pointer, 1); 86533965Sjdp sb_kill (&out); 86633965Sjdp buffer_limit = 86733965Sjdp input_scrub_next_buffer (&input_line_pointer); 86860484Sobrien#ifdef md_macro_info 86977298Sobrien md_macro_info (macro); 87060484Sobrien#endif 87133965Sjdp continue; 87233965Sjdp } 87333965Sjdp } 87433965Sjdp 87533965Sjdp if (mri_pending_align) 87633965Sjdp { 87733965Sjdp do_align (1, (char *) NULL, 0, 0); 87833965Sjdp mri_pending_align = 0; 87933965Sjdp if (line_label != NULL) 88033965Sjdp { 88160484Sobrien symbol_set_frag (line_label, frag_now); 88233965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 88333965Sjdp } 88433965Sjdp } 88533965Sjdp 88677298Sobrien md_assemble (s); /* Assemble 1 instruction. */ 88733965Sjdp 88833965Sjdp *input_line_pointer++ = c; 88933965Sjdp 89033965Sjdp /* We resume loop AFTER the end-of-line from 89177298Sobrien this instruction. */ 89277298Sobrien } 89377298Sobrien } 89433965Sjdp continue; 89577298Sobrien } 89633965Sjdp 89733965Sjdp /* Empty statement? */ 89833965Sjdp if (is_end_of_line[(unsigned char) c]) 89933965Sjdp continue; 90033965Sjdp 90189857Sobrien if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c)) 90233965Sjdp { 90377298Sobrien /* local label ("4:") */ 90433965Sjdp char *backup = input_line_pointer; 90533965Sjdp 90633965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 90733965Sjdp 90833965Sjdp temp = c - '0'; 90933965Sjdp 91077298Sobrien /* Read the whole number. */ 91189857Sobrien while (ISDIGIT (*input_line_pointer)) 91233965Sjdp { 91333965Sjdp temp = (temp * 10) + *input_line_pointer - '0'; 91433965Sjdp ++input_line_pointer; 91577298Sobrien } 91633965Sjdp 91733965Sjdp if (LOCAL_LABELS_DOLLAR 91833965Sjdp && *input_line_pointer == '$' 91933965Sjdp && *(input_line_pointer + 1) == ':') 92033965Sjdp { 92133965Sjdp input_line_pointer += 2; 92233965Sjdp 92333965Sjdp if (dollar_label_defined (temp)) 92433965Sjdp { 92560484Sobrien as_fatal (_("label \"%d$\" redefined"), temp); 92633965Sjdp } 92733965Sjdp 92833965Sjdp define_dollar_label (temp); 92933965Sjdp colon (dollar_label_name (temp, 0)); 93033965Sjdp continue; 93133965Sjdp } 93233965Sjdp 93333965Sjdp if (LOCAL_LABELS_FB 93433965Sjdp && *input_line_pointer++ == ':') 93533965Sjdp { 93633965Sjdp fb_label_instance_inc (temp); 93733965Sjdp colon (fb_label_name (temp, 0)); 93833965Sjdp continue; 93933965Sjdp } 94033965Sjdp 94133965Sjdp input_line_pointer = backup; 94233965Sjdp } /* local label ("4:") */ 94333965Sjdp 94433965Sjdp if (c && strchr (line_comment_chars, c)) 94577298Sobrien { /* Its a comment. Better say APP or NO_APP. */ 946130561Sobrien sb sbuf; 94733965Sjdp char *ends; 94833965Sjdp char *new_buf; 94933965Sjdp char *new_tmp; 95033965Sjdp unsigned int new_length; 95133965Sjdp char *tmp_buf = 0; 95233965Sjdp 95333965Sjdp bump_line_counters (); 95433965Sjdp s = input_line_pointer; 95533965Sjdp if (strncmp (s, "APP\n", 4)) 95633965Sjdp continue; /* We ignore it */ 95733965Sjdp s += 4; 95833965Sjdp 959130561Sobrien sb_new (&sbuf); 96033965Sjdp ends = strstr (s, "#NO_APP\n"); 96133965Sjdp 96233965Sjdp if (!ends) 96333965Sjdp { 96433965Sjdp unsigned int tmp_len; 96533965Sjdp unsigned int num; 96633965Sjdp 96733965Sjdp /* The end of the #APP wasn't in this buffer. We 96833965Sjdp keep reading in buffers until we find the #NO_APP 96933965Sjdp that goes with this #APP There is one. The specs 970130561Sobrien guarantee it... */ 97133965Sjdp tmp_len = buffer_limit - s; 97233965Sjdp tmp_buf = xmalloc (tmp_len + 1); 97333965Sjdp memcpy (tmp_buf, s, tmp_len); 97433965Sjdp do 97533965Sjdp { 97633965Sjdp new_tmp = input_scrub_next_buffer (&buffer); 97733965Sjdp if (!new_tmp) 97833965Sjdp break; 97933965Sjdp else 98033965Sjdp buffer_limit = new_tmp; 98133965Sjdp input_line_pointer = buffer; 98233965Sjdp ends = strstr (buffer, "#NO_APP\n"); 98333965Sjdp if (ends) 98433965Sjdp num = ends - buffer; 98533965Sjdp else 98633965Sjdp num = buffer_limit - buffer; 98733965Sjdp 98833965Sjdp tmp_buf = xrealloc (tmp_buf, tmp_len + num); 98933965Sjdp memcpy (tmp_buf + tmp_len, buffer, num); 99033965Sjdp tmp_len += num; 99133965Sjdp } 99233965Sjdp while (!ends); 99333965Sjdp 99433965Sjdp input_line_pointer = ends ? ends + 8 : NULL; 99533965Sjdp 99633965Sjdp s = tmp_buf; 99733965Sjdp ends = s + tmp_len; 99833965Sjdp 99933965Sjdp } 100033965Sjdp else 100133965Sjdp { 100233965Sjdp input_line_pointer = ends + 8; 100333965Sjdp } 100433965Sjdp 100533965Sjdp scrub_string = s; 100633965Sjdp scrub_string_end = ends; 100733965Sjdp 100833965Sjdp new_length = ends - s; 100933965Sjdp new_buf = (char *) xmalloc (new_length); 101033965Sjdp new_tmp = new_buf; 101133965Sjdp for (;;) 101233965Sjdp { 101333965Sjdp int space; 101433965Sjdp int size; 101533965Sjdp 101633965Sjdp space = (new_buf + new_length) - new_tmp; 101733965Sjdp size = do_scrub_chars (scrub_from_string, new_tmp, space); 101833965Sjdp 101933965Sjdp if (size < space) 102033965Sjdp { 1021130561Sobrien new_tmp[size] = 0; 102233965Sjdp break; 102333965Sjdp } 102433965Sjdp 102533965Sjdp new_buf = xrealloc (new_buf, new_length + 100); 102633965Sjdp new_tmp = new_buf + new_length; 102733965Sjdp new_length += 100; 102833965Sjdp } 102933965Sjdp 103033965Sjdp if (tmp_buf) 103133965Sjdp free (tmp_buf); 103277298Sobrien 1033130561Sobrien /* We've "scrubbed" input to the preferred format. In the 1034130561Sobrien process we may have consumed the whole of the remaining 1035130561Sobrien file (and included files). We handle this formatted 1036130561Sobrien input similar to that of macro expansion, letting 1037130561Sobrien actual macro expansion (possibly nested) and other 1038130561Sobrien input expansion work. Beware that in messages, line 1039130561Sobrien numbers and possibly file names will be incorrect. */ 1040130561Sobrien sb_add_string (&sbuf, new_buf); 1041130561Sobrien input_scrub_include_sb (&sbuf, input_line_pointer, 0); 1042130561Sobrien sb_kill (&sbuf); 1043130561Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 1044130561Sobrien free (new_buf); 104533965Sjdp continue; 104633965Sjdp } 104733965Sjdp 104833965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 104933965Sjdp 105033965Sjdp#ifdef tc_unrecognized_line 105133965Sjdp if (tc_unrecognized_line (c)) 105233965Sjdp continue; 105333965Sjdp#endif 105489857Sobrien input_line_pointer--; 105589857Sobrien /* Report unknown char as ignored. */ 1056130561Sobrien demand_empty_rest_of_line (); 105777298Sobrien } 105833965Sjdp 105933965Sjdp#ifdef md_after_pass_hook 106033965Sjdp md_after_pass_hook (); 106133965Sjdp#endif 106277298Sobrien } 106333965Sjdp 106433965Sjdp quit: 106533965Sjdp 106633965Sjdp#ifdef md_cleanup 106777298Sobrien md_cleanup (); 106833965Sjdp#endif 106977298Sobrien /* Close the input file. */ 107077298Sobrien input_scrub_close (); 107177298Sobrien#ifdef WARN_COMMENTS 107277298Sobrien { 107377298Sobrien if (warn_comment && found_comment) 107477298Sobrien as_warn_where (found_comment_file, found_comment, 107577298Sobrien "first comment found here"); 107677298Sobrien } 107777298Sobrien#endif 107833965Sjdp} 107933965Sjdp 108033965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first 108133965Sjdp nonquoted space. This function looks for that point, stuffs a null 108233965Sjdp in, and sets *STOPCP to the character that used to be there, and 108333965Sjdp returns the location. 108433965Sjdp 108533965Sjdp Until I hear otherwise, I am going to assume that this is only true 108633965Sjdp for the m68k MRI assembler. */ 108733965Sjdp 108833965Sjdpchar * 1089130561Sobrienmri_comment_field (char *stopcp) 109033965Sjdp{ 109177298Sobrien char *s; 109233965Sjdp#ifdef TC_M68K 109333965Sjdp int inquote = 0; 109433965Sjdp 109533965Sjdp know (flag_m68k_mri); 109633965Sjdp 109733965Sjdp for (s = input_line_pointer; 109877298Sobrien ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t') 109933965Sjdp || inquote); 110033965Sjdp s++) 110133965Sjdp { 110233965Sjdp if (*s == '\'') 110377298Sobrien inquote = !inquote; 110433965Sjdp } 110533965Sjdp#else 110677298Sobrien for (s = input_line_pointer; 110777298Sobrien !is_end_of_line[(unsigned char) *s]; 110877298Sobrien s++) 110933965Sjdp ; 111077298Sobrien#endif 111133965Sjdp *stopcp = *s; 111233965Sjdp *s = '\0'; 111377298Sobrien 111433965Sjdp return s; 111533965Sjdp} 111633965Sjdp 111733965Sjdp/* Skip to the end of an MRI comment field. */ 111833965Sjdp 111933965Sjdpvoid 1120130561Sobrienmri_comment_end (char *stop, int stopc) 112133965Sjdp{ 112233965Sjdp know (flag_mri); 112333965Sjdp 112433965Sjdp input_line_pointer = stop; 112533965Sjdp *stop = stopc; 112677298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 112733965Sjdp ++input_line_pointer; 112833965Sjdp} 112933965Sjdp 113077298Sobrienvoid 1131130561Sobriens_abort (int ignore ATTRIBUTE_UNUSED) 113233965Sjdp{ 113360484Sobrien as_fatal (_(".abort detected. Abandoning ship.")); 113433965Sjdp} 113533965Sjdp 113633965Sjdp/* Guts of .align directive. N is the power of two to which to align. 113733965Sjdp FILL may be NULL, or it may point to the bytes of the fill pattern. 113833965Sjdp LEN is the length of whatever FILL points to, if anything. MAX is 113933965Sjdp the maximum number of characters to skip when doing the alignment, 114033965Sjdp or 0 if there is no maximum. */ 114133965Sjdp 114277298Sobrienstatic void 1143130561Sobriendo_align (int n, char *fill, int len, int max) 114433965Sjdp{ 114589857Sobrien if (now_seg == absolute_section) 114689857Sobrien { 114789857Sobrien if (fill != NULL) 114889857Sobrien while (len-- > 0) 114989857Sobrien if (*fill++ != '\0') 115089857Sobrien { 115189857Sobrien as_warn (_("ignoring fill value in absolute section")); 115289857Sobrien break; 115389857Sobrien } 115489857Sobrien fill = NULL; 115589857Sobrien len = 0; 115689857Sobrien } 115789857Sobrien 115833965Sjdp#ifdef md_do_align 115933965Sjdp md_do_align (n, fill, len, max, just_record_alignment); 116033965Sjdp#endif 116133965Sjdp 116277298Sobrien /* Only make a frag if we HAVE to... */ 116333965Sjdp if (n != 0 && !need_pass_2) 116433965Sjdp { 116577298Sobrien if (fill == NULL) 116677298Sobrien { 116777298Sobrien if (subseg_text_p (now_seg)) 116877298Sobrien frag_align_code (n, max); 116977298Sobrien else 117077298Sobrien frag_align (n, 0, max); 117177298Sobrien } 117277298Sobrien else if (len <= 1) 117333965Sjdp frag_align (n, *fill, max); 117433965Sjdp else 117533965Sjdp frag_align_pattern (n, fill, len, max); 117633965Sjdp } 117733965Sjdp 117833965Sjdp#ifdef md_do_align 1179130561Sobrien just_record_alignment: ATTRIBUTE_UNUSED_LABEL 118033965Sjdp#endif 118133965Sjdp 118260484Sobrien record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER); 118333965Sjdp} 118433965Sjdp 118533965Sjdp/* Handle the .align pseudo-op. A positive ARG is a default alignment 118633965Sjdp (in bytes). A negative ARG is the negative of the length of the 118733965Sjdp fill pattern. BYTES_P is non-zero if the alignment value should be 118833965Sjdp interpreted as the byte boundary, rather than the power of 2. */ 118933965Sjdp 119033965Sjdpstatic void 1191130561Sobriens_align (int arg, int bytes_p) 119233965Sjdp{ 119333965Sjdp register unsigned int align; 119433965Sjdp char *stop = NULL; 119533965Sjdp char stopc; 119633965Sjdp offsetT fill = 0; 119733965Sjdp int max; 119833965Sjdp int fill_p; 119933965Sjdp 120033965Sjdp if (flag_mri) 120133965Sjdp stop = mri_comment_field (&stopc); 120233965Sjdp 120333965Sjdp if (is_end_of_line[(unsigned char) *input_line_pointer]) 120433965Sjdp { 120533965Sjdp if (arg < 0) 120633965Sjdp align = 0; 120733965Sjdp else 120877298Sobrien align = arg; /* Default value from pseudo-op table. */ 120933965Sjdp } 121033965Sjdp else 121133965Sjdp { 121233965Sjdp align = get_absolute_expression (); 121333965Sjdp SKIP_WHITESPACE (); 121433965Sjdp } 121533965Sjdp 121633965Sjdp if (bytes_p) 121733965Sjdp { 121833965Sjdp /* Convert to a power of 2. */ 121933965Sjdp if (align != 0) 122033965Sjdp { 122133965Sjdp unsigned int i; 122233965Sjdp 122333965Sjdp for (i = 0; (align & 1) == 0; align >>= 1, ++i) 122433965Sjdp ; 122533965Sjdp if (align != 1) 122689857Sobrien as_bad (_("alignment not a power of 2")); 122777298Sobrien 122833965Sjdp align = i; 122933965Sjdp } 123033965Sjdp } 123133965Sjdp 123233965Sjdp if (align > 15) 123333965Sjdp { 123433965Sjdp align = 15; 123589857Sobrien as_warn (_("alignment too large: %u assumed"), align); 123633965Sjdp } 123733965Sjdp 123833965Sjdp if (*input_line_pointer != ',') 123933965Sjdp { 124033965Sjdp fill_p = 0; 124133965Sjdp max = 0; 124233965Sjdp } 124333965Sjdp else 124433965Sjdp { 124533965Sjdp ++input_line_pointer; 124633965Sjdp if (*input_line_pointer == ',') 124733965Sjdp fill_p = 0; 124833965Sjdp else 124933965Sjdp { 125033965Sjdp fill = get_absolute_expression (); 125133965Sjdp SKIP_WHITESPACE (); 125233965Sjdp fill_p = 1; 125333965Sjdp } 125433965Sjdp 125533965Sjdp if (*input_line_pointer != ',') 125633965Sjdp max = 0; 125733965Sjdp else 125833965Sjdp { 125933965Sjdp ++input_line_pointer; 126033965Sjdp max = get_absolute_expression (); 126133965Sjdp } 126233965Sjdp } 126333965Sjdp 126477298Sobrien if (!fill_p) 126533965Sjdp { 126633965Sjdp if (arg < 0) 126760484Sobrien as_warn (_("expected fill pattern missing")); 126833965Sjdp do_align (align, (char *) NULL, 0, max); 126933965Sjdp } 127033965Sjdp else 127133965Sjdp { 127233965Sjdp int fill_len; 127333965Sjdp 127433965Sjdp if (arg >= 0) 127533965Sjdp fill_len = 1; 127633965Sjdp else 127777298Sobrien fill_len = -arg; 127833965Sjdp if (fill_len <= 1) 127933965Sjdp { 128033965Sjdp char fill_char; 128133965Sjdp 128233965Sjdp fill_char = fill; 128333965Sjdp do_align (align, &fill_char, fill_len, max); 128433965Sjdp } 128533965Sjdp else 128633965Sjdp { 128733965Sjdp char ab[16]; 128833965Sjdp 128938889Sjdp if ((size_t) fill_len > sizeof ab) 129033965Sjdp abort (); 129133965Sjdp md_number_to_chars (ab, fill, fill_len); 129233965Sjdp do_align (align, ab, fill_len, max); 129333965Sjdp } 129433965Sjdp } 129533965Sjdp 129660484Sobrien demand_empty_rest_of_line (); 129760484Sobrien 129833965Sjdp if (flag_mri) 129933965Sjdp mri_comment_end (stop, stopc); 130033965Sjdp} 130133965Sjdp 130233965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means 130333965Sjdp align to a 4 byte boundary. */ 130433965Sjdp 130577298Sobrienvoid 1306130561Sobriens_align_bytes (int arg) 130733965Sjdp{ 130833965Sjdp s_align (arg, 1); 130933965Sjdp} 131033965Sjdp 131138889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align 131233965Sjdp to a 2**4 boundary. */ 131333965Sjdp 131477298Sobrienvoid 1315130561Sobriens_align_ptwo (int arg) 131633965Sjdp{ 131733965Sjdp s_align (arg, 0); 131833965Sjdp} 131933965Sjdp 1320130561SobriensymbolS * 1321130561Sobriens_comm_internal (int param, 1322130561Sobrien symbolS *(*comm_parse_extra) (int, symbolS *, addressT)) 132333965Sjdp{ 1324130561Sobrien char *name; 1325130561Sobrien char c; 1326130561Sobrien char *p; 1327130561Sobrien offsetT temp, size; 1328130561Sobrien symbolS *symbolP = NULL; 132933965Sjdp char *stop = NULL; 133033965Sjdp char stopc; 1331130561Sobrien expressionS exp; 133233965Sjdp 133333965Sjdp if (flag_mri) 133433965Sjdp stop = mri_comment_field (&stopc); 133533965Sjdp 133633965Sjdp name = input_line_pointer; 133733965Sjdp c = get_symbol_end (); 133877298Sobrien /* Just after name is now '\0'. */ 133933965Sjdp p = input_line_pointer; 134033965Sjdp *p = c; 134189857Sobrien 134289857Sobrien if (name == p) 134389857Sobrien { 134489857Sobrien as_bad (_("expected symbol name")); 134589857Sobrien discard_rest_of_line (); 1346130561Sobrien goto out; 134789857Sobrien } 134889857Sobrien 134933965Sjdp SKIP_WHITESPACE (); 135077298Sobrien 1351130561Sobrien /* Accept an optional comma after the name. The comma used to be 1352130561Sobrien required, but Irix 5 cc does not generate it for .lcomm. */ 1353130561Sobrien if (*input_line_pointer == ',') 1354130561Sobrien input_line_pointer++; 1355130561Sobrien 1356130561Sobrien *p = 0; 1357130561Sobrien temp = get_absolute_expr (&exp); 1358130561Sobrien size = temp; 1359130561Sobrien#ifdef BFD_ASSEMBLER 1360130561Sobrien size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1; 1361130561Sobrien#endif 1362130561Sobrien if (exp.X_op == O_absent) 136333965Sjdp { 1364130561Sobrien as_bad (_("missing size expression")); 136589857Sobrien *p = c; 136660484Sobrien ignore_rest_of_line (); 1367130561Sobrien goto out; 136833965Sjdp } 1369130561Sobrien else if (temp != size || !exp.X_unsigned) 137033965Sjdp { 1371130561Sobrien as_warn (_("size (%ld) out of range, ignored"), (long) temp); 1372130561Sobrien *p = c; 137360484Sobrien ignore_rest_of_line (); 1374130561Sobrien goto out; 137533965Sjdp } 137677298Sobrien 137733965Sjdp symbolP = symbol_find_or_make (name); 137877298Sobrien if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP)) 137933965Sjdp { 1380130561Sobrien symbolP = NULL; 1381130561Sobrien as_bad (_("symbol `%s' is already defined"), name); 1382130561Sobrien *p = c; 138360484Sobrien ignore_rest_of_line (); 1384130561Sobrien goto out; 138533965Sjdp } 138677298Sobrien 1387130561Sobrien size = S_GET_VALUE (symbolP); 1388130561Sobrien if (size == 0) 1389130561Sobrien size = temp; 1390130561Sobrien else if (size != temp) 1391130561Sobrien as_warn (_("size of \"%s\" is already %ld; not changing to %ld"), 1392130561Sobrien name, (long) size, (long) temp); 1393130561Sobrien 1394130561Sobrien *p = c; 1395130561Sobrien if (comm_parse_extra != NULL) 1396130561Sobrien symbolP = (*comm_parse_extra) (param, symbolP, size); 139733965Sjdp else 139833965Sjdp { 1399130561Sobrien S_SET_VALUE (symbolP, (valueT) size); 140033965Sjdp S_SET_EXTERNAL (symbolP); 1401130561Sobrien#ifdef OBJ_VMS 1402130561Sobrien { 1403130561Sobrien extern int flag_one; 1404130561Sobrien if (size == 0 || !flag_one) 1405130561Sobrien S_GET_OTHER (symbolP) = const_flag; 1406130561Sobrien } 1407130561Sobrien#endif 140833965Sjdp } 140933965Sjdp 1410130561Sobrien know (symbolP == NULL || symbolP->sy_frag == &zero_address_frag); 141160484Sobrien demand_empty_rest_of_line (); 1412130561Sobrien out: 141333965Sjdp if (flag_mri) 141433965Sjdp mri_comment_end (stop, stopc); 1415130561Sobrien return symbolP; 1416130561Sobrien} 141733965Sjdp 1418130561Sobrienvoid 1419130561Sobriens_comm (int ignore) 1420130561Sobrien{ 1421130561Sobrien s_comm_internal (ignore, NULL); 1422130561Sobrien} 1423130561Sobrien 142433965Sjdp/* The MRI COMMON pseudo-op. We handle this by creating a common 142533965Sjdp symbol with the appropriate name. We make s_space do the right 142633965Sjdp thing by increasing the size. */ 142733965Sjdp 142833965Sjdpvoid 1429130561Sobriens_mri_common (int small ATTRIBUTE_UNUSED) 143033965Sjdp{ 143133965Sjdp char *name; 143233965Sjdp char c; 143333965Sjdp char *alc = NULL; 143433965Sjdp symbolS *sym; 143533965Sjdp offsetT align; 143633965Sjdp char *stop = NULL; 143733965Sjdp char stopc; 143833965Sjdp 143977298Sobrien if (!flag_mri) 144033965Sjdp { 144133965Sjdp s_comm (0); 144233965Sjdp return; 144333965Sjdp } 144433965Sjdp 144533965Sjdp stop = mri_comment_field (&stopc); 144633965Sjdp 144733965Sjdp SKIP_WHITESPACE (); 144833965Sjdp 144933965Sjdp name = input_line_pointer; 145089857Sobrien if (!ISDIGIT (*name)) 145133965Sjdp c = get_symbol_end (); 145233965Sjdp else 145333965Sjdp { 145433965Sjdp do 145533965Sjdp { 145633965Sjdp ++input_line_pointer; 145733965Sjdp } 145889857Sobrien while (ISDIGIT (*input_line_pointer)); 145977298Sobrien 146033965Sjdp c = *input_line_pointer; 146133965Sjdp *input_line_pointer = '\0'; 146233965Sjdp 146333965Sjdp if (line_label != NULL) 146433965Sjdp { 146533965Sjdp alc = (char *) xmalloc (strlen (S_GET_NAME (line_label)) 146633965Sjdp + (input_line_pointer - name) 146733965Sjdp + 1); 146833965Sjdp sprintf (alc, "%s%s", name, S_GET_NAME (line_label)); 146933965Sjdp name = alc; 147033965Sjdp } 147133965Sjdp } 147233965Sjdp 147333965Sjdp sym = symbol_find_or_make (name); 147433965Sjdp *input_line_pointer = c; 147533965Sjdp if (alc != NULL) 147633965Sjdp free (alc); 147733965Sjdp 147833965Sjdp if (*input_line_pointer != ',') 147933965Sjdp align = 0; 148033965Sjdp else 148133965Sjdp { 148233965Sjdp ++input_line_pointer; 148333965Sjdp align = get_absolute_expression (); 148433965Sjdp } 148533965Sjdp 148677298Sobrien if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym)) 148733965Sjdp { 148889857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym)); 148960484Sobrien ignore_rest_of_line (); 149033965Sjdp mri_comment_end (stop, stopc); 149133965Sjdp return; 149233965Sjdp } 149333965Sjdp 149433965Sjdp S_SET_EXTERNAL (sym); 149533965Sjdp mri_common_symbol = sym; 149633965Sjdp 149733965Sjdp#ifdef S_SET_ALIGN 149833965Sjdp if (align != 0) 149933965Sjdp S_SET_ALIGN (sym, align); 150033965Sjdp#endif 150133965Sjdp 150233965Sjdp if (line_label != NULL) 150333965Sjdp { 150460484Sobrien expressionS exp; 150560484Sobrien exp.X_op = O_symbol; 150660484Sobrien exp.X_add_symbol = sym; 150760484Sobrien exp.X_add_number = 0; 150860484Sobrien symbol_set_value_expression (line_label, &exp); 150960484Sobrien symbol_set_frag (line_label, &zero_address_frag); 151033965Sjdp S_SET_SEGMENT (line_label, expr_section); 151133965Sjdp } 151233965Sjdp 151333965Sjdp /* FIXME: We just ignore the small argument, which distinguishes 151433965Sjdp COMMON and COMMON.S. I don't know what we can do about it. */ 151533965Sjdp 151633965Sjdp /* Ignore the type and hptype. */ 151733965Sjdp if (*input_line_pointer == ',') 151833965Sjdp input_line_pointer += 2; 151933965Sjdp if (*input_line_pointer == ',') 152033965Sjdp input_line_pointer += 2; 152133965Sjdp 152260484Sobrien demand_empty_rest_of_line (); 152360484Sobrien 152433965Sjdp mri_comment_end (stop, stopc); 152533965Sjdp} 152633965Sjdp 152733965Sjdpvoid 1528130561Sobriens_data (int ignore ATTRIBUTE_UNUSED) 152933965Sjdp{ 153033965Sjdp segT section; 153133965Sjdp register int temp; 153233965Sjdp 153333965Sjdp temp = get_absolute_expression (); 153433965Sjdp if (flag_readonly_data_in_text) 153533965Sjdp { 153633965Sjdp section = text_section; 153733965Sjdp temp += 1000; 153833965Sjdp } 153933965Sjdp else 154033965Sjdp section = data_section; 154133965Sjdp 154233965Sjdp subseg_set (section, (subsegT) temp); 154333965Sjdp 154433965Sjdp#ifdef OBJ_VMS 154533965Sjdp const_flag = 0; 154633965Sjdp#endif 154733965Sjdp demand_empty_rest_of_line (); 154833965Sjdp} 154933965Sjdp 155033965Sjdp/* Handle the .appfile pseudo-op. This is automatically generated by 155133965Sjdp do_scrub_chars when a preprocessor # line comment is seen with a 155233965Sjdp file name. This default definition may be overridden by the object 155333965Sjdp or CPU specific pseudo-ops. This function is also the default 155433965Sjdp definition for .file; the APPFILE argument is 1 for .appfile, 0 for 155533965Sjdp .file. */ 155633965Sjdp 155777298Sobrienvoid 1558130561Sobriens_app_file_string (char *file) 1559104834Sobrien{ 1560104834Sobrien#ifdef LISTING 1561104834Sobrien if (listing) 1562104834Sobrien listing_source_file (file); 1563104834Sobrien#endif 1564104834Sobrien register_dependency (file); 1565104834Sobrien#ifdef obj_app_file 1566104834Sobrien obj_app_file (file); 1567104834Sobrien#endif 1568104834Sobrien} 1569104834Sobrien 1570104834Sobrienvoid 1571130561Sobriens_app_file (int appfile) 157233965Sjdp{ 157333965Sjdp register char *s; 157433965Sjdp int length; 157533965Sjdp 157677298Sobrien /* Some assemblers tolerate immediately following '"'. */ 157733965Sjdp if ((s = demand_copy_string (&length)) != 0) 157833965Sjdp { 157933965Sjdp /* If this is a fake .appfile, a fake newline was inserted into 158033965Sjdp the buffer. Passing -2 to new_logical_line tells it to 158133965Sjdp account for it. */ 158238889Sjdp int may_omit 158377298Sobrien = (!new_logical_line (s, appfile ? -2 : -1) && appfile); 158433965Sjdp 158533965Sjdp /* In MRI mode, the preprocessor may have inserted an extraneous 1586130561Sobrien backquote. */ 158733965Sjdp if (flag_m68k_mri 158833965Sjdp && *input_line_pointer == '\'' 158933965Sjdp && is_end_of_line[(unsigned char) input_line_pointer[1]]) 159033965Sjdp ++input_line_pointer; 159133965Sjdp 159233965Sjdp demand_empty_rest_of_line (); 159377298Sobrien if (!may_omit) 1594104834Sobrien s_app_file_string (s); 159538889Sjdp } 159633965Sjdp} 159733965Sjdp 159833965Sjdp/* Handle the .appline pseudo-op. This is automatically generated by 159933965Sjdp do_scrub_chars when a preprocessor # line comment is seen. This 160033965Sjdp default definition may be overridden by the object or CPU specific 160133965Sjdp pseudo-ops. */ 160233965Sjdp 160333965Sjdpvoid 1604130561Sobriens_app_line (int ignore ATTRIBUTE_UNUSED) 160533965Sjdp{ 160633965Sjdp int l; 160733965Sjdp 160833965Sjdp /* The given number is that of the next line. */ 160933965Sjdp l = get_absolute_expression () - 1; 161033965Sjdp if (l < 0) 161133965Sjdp /* Some of the back ends can't deal with non-positive line numbers. 161233965Sjdp Besides, it's silly. */ 161389857Sobrien as_warn (_("line numbers must be positive; line number %d rejected"), 161477298Sobrien l + 1); 161533965Sjdp else 161633965Sjdp { 161733965Sjdp new_logical_line ((char *) NULL, l); 161833965Sjdp#ifdef LISTING 161933965Sjdp if (listing) 162033965Sjdp listing_source_line (l); 162133965Sjdp#endif 162233965Sjdp } 162333965Sjdp demand_empty_rest_of_line (); 162433965Sjdp} 162533965Sjdp 162633965Sjdp/* Handle the .end pseudo-op. Actually, the real work is done in 162733965Sjdp read_a_source_file. */ 162833965Sjdp 162933965Sjdpvoid 1630130561Sobriens_end (int ignore ATTRIBUTE_UNUSED) 163133965Sjdp{ 163233965Sjdp if (flag_mri) 163333965Sjdp { 163433965Sjdp /* The MRI assembler permits the start symbol to follow .end, 1635130561Sobrien but we don't support that. */ 163633965Sjdp SKIP_WHITESPACE (); 163777298Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer] 163833965Sjdp && *input_line_pointer != '*' 163933965Sjdp && *input_line_pointer != '!') 164060484Sobrien as_warn (_("start address not supported")); 164133965Sjdp } 164233965Sjdp} 164333965Sjdp 164433965Sjdp/* Handle the .err pseudo-op. */ 164533965Sjdp 164633965Sjdpvoid 1647130561Sobriens_err (int ignore ATTRIBUTE_UNUSED) 164833965Sjdp{ 164960484Sobrien as_bad (_(".err encountered")); 165033965Sjdp demand_empty_rest_of_line (); 165133965Sjdp} 165233965Sjdp 165333965Sjdp/* Handle the MRI fail pseudo-op. */ 165433965Sjdp 165533965Sjdpvoid 1656130561Sobriens_fail (int ignore ATTRIBUTE_UNUSED) 165733965Sjdp{ 165833965Sjdp offsetT temp; 165933965Sjdp char *stop = NULL; 166033965Sjdp char stopc; 166133965Sjdp 166233965Sjdp if (flag_mri) 166333965Sjdp stop = mri_comment_field (&stopc); 166433965Sjdp 166533965Sjdp temp = get_absolute_expression (); 166633965Sjdp if (temp >= 500) 166760484Sobrien as_warn (_(".fail %ld encountered"), (long) temp); 166833965Sjdp else 166960484Sobrien as_bad (_(".fail %ld encountered"), (long) temp); 167033965Sjdp 167160484Sobrien demand_empty_rest_of_line (); 167260484Sobrien 167333965Sjdp if (flag_mri) 167433965Sjdp mri_comment_end (stop, stopc); 167533965Sjdp} 167633965Sjdp 167777298Sobrienvoid 1678130561Sobriens_fill (int ignore ATTRIBUTE_UNUSED) 167933965Sjdp{ 168038889Sjdp expressionS rep_exp; 168138889Sjdp long size = 1; 168238889Sjdp register long fill = 0; 168333965Sjdp char *p; 168433965Sjdp 168533965Sjdp#ifdef md_flush_pending_output 168633965Sjdp md_flush_pending_output (); 168733965Sjdp#endif 168833965Sjdp 168938889Sjdp get_known_segmented_expression (&rep_exp); 169033965Sjdp if (*input_line_pointer == ',') 169133965Sjdp { 169233965Sjdp input_line_pointer++; 169338889Sjdp size = get_absolute_expression (); 169433965Sjdp if (*input_line_pointer == ',') 169533965Sjdp { 169633965Sjdp input_line_pointer++; 169738889Sjdp fill = get_absolute_expression (); 169833965Sjdp } 169933965Sjdp } 170038889Sjdp 170133965Sjdp /* This is to be compatible with BSD 4.2 AS, not for any rational reason. */ 170233965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8) 170338889Sjdp if (size > BSD_FILL_SIZE_CROCK_8) 170433965Sjdp { 170589857Sobrien as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8); 170638889Sjdp size = BSD_FILL_SIZE_CROCK_8; 170733965Sjdp } 170838889Sjdp if (size < 0) 170933965Sjdp { 171089857Sobrien as_warn (_("size negative; .fill ignored")); 171138889Sjdp size = 0; 171233965Sjdp } 171338889Sjdp else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0) 171433965Sjdp { 171538889Sjdp if (rep_exp.X_add_number < 0) 171689857Sobrien as_warn (_("repeat < 0; .fill ignored")); 171738889Sjdp size = 0; 171833965Sjdp } 171933965Sjdp 172038889Sjdp if (size && !need_pass_2) 172133965Sjdp { 172238889Sjdp if (rep_exp.X_op == O_constant) 172338889Sjdp { 172438889Sjdp p = frag_var (rs_fill, (int) size, (int) size, 172538889Sjdp (relax_substateT) 0, (symbolS *) 0, 172638889Sjdp (offsetT) rep_exp.X_add_number, 172738889Sjdp (char *) 0); 172838889Sjdp } 172938889Sjdp else 173038889Sjdp { 173138889Sjdp /* We don't have a constant repeat count, so we can't use 173238889Sjdp rs_fill. We can get the same results out of rs_space, 173338889Sjdp but its argument is in bytes, so we must multiply the 173438889Sjdp repeat count by size. */ 173538889Sjdp 173638889Sjdp symbolS *rep_sym; 173738889Sjdp rep_sym = make_expr_symbol (&rep_exp); 173838889Sjdp if (size != 1) 173938889Sjdp { 174038889Sjdp expressionS size_exp; 174138889Sjdp size_exp.X_op = O_constant; 174238889Sjdp size_exp.X_add_number = size; 174338889Sjdp 174438889Sjdp rep_exp.X_op = O_multiply; 174538889Sjdp rep_exp.X_add_symbol = rep_sym; 174638889Sjdp rep_exp.X_op_symbol = make_expr_symbol (&size_exp); 174738889Sjdp rep_exp.X_add_number = 0; 174838889Sjdp rep_sym = make_expr_symbol (&rep_exp); 174938889Sjdp } 175038889Sjdp 175138889Sjdp p = frag_var (rs_space, (int) size, (int) size, 175238889Sjdp (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0); 175338889Sjdp } 175477298Sobrien 175538889Sjdp memset (p, 0, (unsigned int) size); 175677298Sobrien 175733965Sjdp /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX 1758130561Sobrien flavoured AS. The following bizarre behaviour is to be 1759130561Sobrien compatible with above. I guess they tried to take up to 8 1760130561Sobrien bytes from a 4-byte expression and they forgot to sign 1761130561Sobrien extend. */ 176233965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4) 176338889Sjdp md_number_to_chars (p, (valueT) fill, 176438889Sjdp (size > BSD_FILL_SIZE_CROCK_4 176533965Sjdp ? BSD_FILL_SIZE_CROCK_4 176638889Sjdp : (int) size)); 176733965Sjdp /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) 1768130561Sobrien but emits no error message because it seems a legal thing to do. 1769130561Sobrien It is a degenerate case of .fill but could be emitted by a 177077298Sobrien compiler. */ 177133965Sjdp } 177233965Sjdp demand_empty_rest_of_line (); 177333965Sjdp} 177433965Sjdp 177577298Sobrienvoid 1776130561Sobriens_globl (int ignore ATTRIBUTE_UNUSED) 177733965Sjdp{ 177833965Sjdp char *name; 177933965Sjdp int c; 178033965Sjdp symbolS *symbolP; 178133965Sjdp char *stop = NULL; 178233965Sjdp char stopc; 178333965Sjdp 178433965Sjdp if (flag_mri) 178533965Sjdp stop = mri_comment_field (&stopc); 178633965Sjdp 178733965Sjdp do 178833965Sjdp { 178933965Sjdp name = input_line_pointer; 179033965Sjdp c = get_symbol_end (); 179133965Sjdp symbolP = symbol_find_or_make (name); 179260484Sobrien S_SET_EXTERNAL (symbolP); 179360484Sobrien 179433965Sjdp *input_line_pointer = c; 179533965Sjdp SKIP_WHITESPACE (); 179660484Sobrien c = *input_line_pointer; 179733965Sjdp if (c == ',') 179833965Sjdp { 179933965Sjdp input_line_pointer++; 180033965Sjdp SKIP_WHITESPACE (); 180189857Sobrien if (is_end_of_line[(unsigned char) *input_line_pointer]) 180233965Sjdp c = '\n'; 180333965Sjdp } 180433965Sjdp } 180533965Sjdp while (c == ','); 180633965Sjdp 180760484Sobrien demand_empty_rest_of_line (); 180860484Sobrien 180933965Sjdp if (flag_mri) 181033965Sjdp mri_comment_end (stop, stopc); 181133965Sjdp} 181233965Sjdp 181333965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops. */ 181433965Sjdp 181533965Sjdpvoid 1816130561Sobriens_irp (int irpc) 181733965Sjdp{ 181833965Sjdp char *file; 181933965Sjdp unsigned int line; 182033965Sjdp sb s; 182133965Sjdp const char *err; 182233965Sjdp sb out; 182333965Sjdp 182433965Sjdp as_where (&file, &line); 182533965Sjdp 182633965Sjdp sb_new (&s); 182777298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 182833965Sjdp sb_add_char (&s, *input_line_pointer++); 182933965Sjdp 183033965Sjdp sb_new (&out); 183133965Sjdp 1832130561Sobrien err = expand_irp (irpc, 0, &s, &out, get_line_sb); 183333965Sjdp if (err != NULL) 183433965Sjdp as_bad_where (file, line, "%s", err); 183533965Sjdp 183633965Sjdp sb_kill (&s); 183733965Sjdp 183860484Sobrien input_scrub_include_sb (&out, input_line_pointer, 1); 183933965Sjdp sb_kill (&out); 184033965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 184133965Sjdp} 184233965Sjdp 184333965Sjdp/* Handle the .linkonce pseudo-op. This tells the assembler to mark 184433965Sjdp the section to only be linked once. However, this is not supported 184533965Sjdp by most object file formats. This takes an optional argument, 184633965Sjdp which is what to do about duplicates. */ 184733965Sjdp 184833965Sjdpvoid 1849130561Sobriens_linkonce (int ignore ATTRIBUTE_UNUSED) 185033965Sjdp{ 185133965Sjdp enum linkonce_type type; 185233965Sjdp 185333965Sjdp SKIP_WHITESPACE (); 185433965Sjdp 185533965Sjdp type = LINKONCE_DISCARD; 185633965Sjdp 185777298Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer]) 185833965Sjdp { 185933965Sjdp char *s; 186033965Sjdp char c; 186133965Sjdp 186233965Sjdp s = input_line_pointer; 186333965Sjdp c = get_symbol_end (); 186433965Sjdp if (strcasecmp (s, "discard") == 0) 186533965Sjdp type = LINKONCE_DISCARD; 186633965Sjdp else if (strcasecmp (s, "one_only") == 0) 186733965Sjdp type = LINKONCE_ONE_ONLY; 186833965Sjdp else if (strcasecmp (s, "same_size") == 0) 186933965Sjdp type = LINKONCE_SAME_SIZE; 187033965Sjdp else if (strcasecmp (s, "same_contents") == 0) 187133965Sjdp type = LINKONCE_SAME_CONTENTS; 187233965Sjdp else 187360484Sobrien as_warn (_("unrecognized .linkonce type `%s'"), s); 187433965Sjdp 187533965Sjdp *input_line_pointer = c; 187633965Sjdp } 187733965Sjdp 187833965Sjdp#ifdef obj_handle_link_once 187933965Sjdp obj_handle_link_once (type); 188033965Sjdp#else /* ! defined (obj_handle_link_once) */ 188133965Sjdp#ifdef BFD_ASSEMBLER 188233965Sjdp { 188333965Sjdp flagword flags; 188433965Sjdp 188533965Sjdp if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0) 188660484Sobrien as_warn (_(".linkonce is not supported for this object file format")); 188733965Sjdp 188833965Sjdp flags = bfd_get_section_flags (stdoutput, now_seg); 188933965Sjdp flags |= SEC_LINK_ONCE; 189033965Sjdp switch (type) 189133965Sjdp { 189233965Sjdp default: 189333965Sjdp abort (); 189433965Sjdp case LINKONCE_DISCARD: 189533965Sjdp flags |= SEC_LINK_DUPLICATES_DISCARD; 189633965Sjdp break; 189733965Sjdp case LINKONCE_ONE_ONLY: 189833965Sjdp flags |= SEC_LINK_DUPLICATES_ONE_ONLY; 189933965Sjdp break; 190033965Sjdp case LINKONCE_SAME_SIZE: 190133965Sjdp flags |= SEC_LINK_DUPLICATES_SAME_SIZE; 190233965Sjdp break; 190333965Sjdp case LINKONCE_SAME_CONTENTS: 190433965Sjdp flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS; 190533965Sjdp break; 190633965Sjdp } 190777298Sobrien if (!bfd_set_section_flags (stdoutput, now_seg, flags)) 190860484Sobrien as_bad (_("bfd_set_section_flags: %s"), 190933965Sjdp bfd_errmsg (bfd_get_error ())); 191033965Sjdp } 191133965Sjdp#else /* ! defined (BFD_ASSEMBLER) */ 191260484Sobrien as_warn (_(".linkonce is not supported for this object file format")); 191333965Sjdp#endif /* ! defined (BFD_ASSEMBLER) */ 191433965Sjdp#endif /* ! defined (obj_handle_link_once) */ 191533965Sjdp 191633965Sjdp demand_empty_rest_of_line (); 191733965Sjdp} 191833965Sjdp 1919130561Sobrienvoid 1920130561Sobrienbss_alloc (symbolS *symbolP, addressT size, int align) 192133965Sjdp{ 1922130561Sobrien char *pfrag; 192333965Sjdp segT current_seg = now_seg; 192433965Sjdp subsegT current_subseg = now_subseg; 192533965Sjdp segT bss_seg = bss_section; 192633965Sjdp 192733965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA) 192833965Sjdp if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour 192933965Sjdp || OUTPUT_FLAVOR == bfd_target_elf_flavour) 193033965Sjdp { 193133965Sjdp /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */ 1932130561Sobrien if (size <= bfd_get_gp_size (stdoutput)) 193333965Sjdp { 193433965Sjdp bss_seg = subseg_new (".sbss", 1); 193533965Sjdp seg_info (bss_seg)->bss = 1; 193633965Sjdp#ifdef BFD_ASSEMBLER 193777298Sobrien if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) 193860484Sobrien as_warn (_("error setting flags for \".sbss\": %s"), 193933965Sjdp bfd_errmsg (bfd_get_error ())); 194033965Sjdp#endif 194133965Sjdp } 194233965Sjdp } 194333965Sjdp#endif 1944130561Sobrien subseg_set (bss_seg, 1); 194560484Sobrien 1946130561Sobrien if (align) 194777298Sobrien { 1948130561Sobrien record_alignment (bss_seg, align); 1949130561Sobrien frag_align (align, 0, 0); 195077298Sobrien } 195133965Sjdp 1952130561Sobrien /* Detach from old frag. */ 1953130561Sobrien if (S_GET_SEGMENT (symbolP) == bss_seg) 1954130561Sobrien symbol_get_frag (symbolP)->fr_symbol = NULL; 195577298Sobrien 1956130561Sobrien symbol_set_frag (symbolP, frag_now); 1957130561Sobrien pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL); 1958130561Sobrien *pfrag = 0; 195977298Sobrien 1960130561Sobrien#ifdef S_SET_SIZE 1961130561Sobrien S_SET_SIZE (symbolP, size); 1962130561Sobrien#endif 1963130561Sobrien S_SET_SEGMENT (symbolP, bss_seg); 196477298Sobrien 1965130561Sobrien#ifdef OBJ_COFF 1966130561Sobrien /* The symbol may already have been created with a preceding 1967130561Sobrien ".globl" directive -- be careful not to step on storage class 1968130561Sobrien in that case. Otherwise, set it to static. */ 1969130561Sobrien if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 1970130561Sobrien S_SET_STORAGE_CLASS (symbolP, C_STAT); 1971130561Sobrien#endif /* OBJ_COFF */ 197277298Sobrien 1973130561Sobrien subseg_set (current_seg, current_subseg); 1974130561Sobrien} 197577298Sobrien 1976130561SobrienoffsetT 1977130561Sobrienparse_align (int align_bytes) 1978130561Sobrien{ 1979130561Sobrien expressionS exp; 1980130561Sobrien addressT align; 198138889Sjdp 1982130561Sobrien SKIP_WHITESPACE (); 1983130561Sobrien if (*input_line_pointer != ',') 1984130561Sobrien { 1985130561Sobrien no_align: 1986130561Sobrien as_bad (_("expected alignment after size")); 1987130561Sobrien ignore_rest_of_line (); 1988130561Sobrien return -1; 1989130561Sobrien } 199077298Sobrien 1991130561Sobrien input_line_pointer++; 1992130561Sobrien SKIP_WHITESPACE (); 199377298Sobrien 1994130561Sobrien align = get_absolute_expr (&exp); 1995130561Sobrien if (exp.X_op == O_absent) 1996130561Sobrien goto no_align; 1997130561Sobrien 1998130561Sobrien if (!exp.X_unsigned) 1999130561Sobrien { 2000130561Sobrien as_warn (_("alignment negative; 0 assumed")); 2001130561Sobrien align = 0; 200277298Sobrien } 2003130561Sobrien 2004130561Sobrien if (align_bytes && align != 0) 200533965Sjdp { 2006130561Sobrien /* convert to a power of 2 alignment */ 2007130561Sobrien unsigned int alignp2 = 0; 2008130561Sobrien while ((align & 1) == 0) 2009130561Sobrien align >>= 1, ++alignp2; 2010130561Sobrien if (align != 1) 201133965Sjdp { 2012130561Sobrien as_bad (_("alignment not a power of 2")); 2013130561Sobrien ignore_rest_of_line (); 2014130561Sobrien return -1; 201533965Sjdp } 2016130561Sobrien align = alignp2; 201733965Sjdp } 2018130561Sobrien return align; 2019130561Sobrien} 202033965Sjdp 2021130561Sobrien/* Called from s_comm_internal after symbol name and size have been 2022130561Sobrien parsed. NEEDS_ALIGN is 0 if it was an ".lcomm" (2 args only), 2023130561Sobrien 1 if this was a ".bss" directive which has a 3rd argument 2024130561Sobrien (alignment as a power of 2), or 2 if this was a ".bss" directive 2025130561Sobrien with alignment in bytes. */ 202633965Sjdp 2027130561SobriensymbolS * 2028130561Sobriens_lcomm_internal (int needs_align, symbolS *symbolP, addressT size) 2029130561Sobrien{ 2030130561Sobrien addressT align = 0; 2031130561Sobrien 2032130561Sobrien if (needs_align) 203333965Sjdp { 2034130561Sobrien align = parse_align (needs_align - 1); 2035130561Sobrien if (align == (addressT) -1) 2036130561Sobrien return NULL; 203733965Sjdp } 203833965Sjdp else 2039130561Sobrien /* Assume some objects may require alignment on some systems. */ 2040130561Sobrien TC_IMPLICIT_LCOMM_ALIGNMENT (size, align); 204133965Sjdp 2042130561Sobrien bss_alloc (symbolP, size, align); 2043130561Sobrien return symbolP; 204477298Sobrien} 204533965Sjdp 204638889Sjdpvoid 2047130561Sobriens_lcomm (int needs_align) 204838889Sjdp{ 2049130561Sobrien s_comm_internal (needs_align, s_lcomm_internal); 205038889Sjdp} 205138889Sjdp 205277298Sobrienvoid 2053130561Sobriens_lcomm_bytes (int needs_align) 205438889Sjdp{ 2055130561Sobrien s_comm_internal (needs_align * 2, s_lcomm_internal); 205638889Sjdp} 205738889Sjdp 205877298Sobrienvoid 2059130561Sobriens_lsym (int ignore ATTRIBUTE_UNUSED) 206033965Sjdp{ 206133965Sjdp register char *name; 206233965Sjdp register char c; 206333965Sjdp register char *p; 206433965Sjdp expressionS exp; 206533965Sjdp register symbolS *symbolP; 206633965Sjdp 206777298Sobrien /* We permit ANY defined expression: BSD4.2 demands constants. */ 206833965Sjdp name = input_line_pointer; 206933965Sjdp c = get_symbol_end (); 207033965Sjdp p = input_line_pointer; 207133965Sjdp *p = c; 207289857Sobrien 207389857Sobrien if (name == p) 207489857Sobrien { 207589857Sobrien as_bad (_("expected symbol name")); 207689857Sobrien discard_rest_of_line (); 207789857Sobrien return; 207889857Sobrien } 207989857Sobrien 208033965Sjdp SKIP_WHITESPACE (); 208177298Sobrien 208233965Sjdp if (*input_line_pointer != ',') 208333965Sjdp { 208433965Sjdp *p = 0; 208589857Sobrien as_bad (_("expected comma after \"%s\""), name); 208633965Sjdp *p = c; 208733965Sjdp ignore_rest_of_line (); 208833965Sjdp return; 208933965Sjdp } 209077298Sobrien 209133965Sjdp input_line_pointer++; 209233965Sjdp expression (&exp); 209377298Sobrien 209433965Sjdp if (exp.X_op != O_constant 209533965Sjdp && exp.X_op != O_register) 209633965Sjdp { 209760484Sobrien as_bad (_("bad expression")); 209833965Sjdp ignore_rest_of_line (); 209933965Sjdp return; 210033965Sjdp } 210177298Sobrien 210233965Sjdp *p = 0; 210333965Sjdp symbolP = symbol_find_or_make (name); 210433965Sjdp 210533965Sjdp /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 && 210633965Sjdp symbolP->sy_desc == 0) out of this test because coff doesn't have 210733965Sjdp those fields, and I can't see when they'd ever be tripped. I 210833965Sjdp don't think I understand why they were here so I may have 210933965Sjdp introduced a bug. As recently as 1.37 didn't have this test 211077298Sobrien anyway. xoxorich. */ 211133965Sjdp 211233965Sjdp if (S_GET_SEGMENT (symbolP) == undefined_section 211333965Sjdp && S_GET_VALUE (symbolP) == 0) 211433965Sjdp { 211533965Sjdp /* The name might be an undefined .global symbol; be sure to 211677298Sobrien keep the "external" bit. */ 211733965Sjdp S_SET_SEGMENT (symbolP, 211833965Sjdp (exp.X_op == O_constant 211933965Sjdp ? absolute_section 212033965Sjdp : reg_section)); 212133965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 212233965Sjdp } 212333965Sjdp else 212433965Sjdp { 212589857Sobrien as_bad (_("symbol `%s' is already defined"), name); 212633965Sjdp } 212777298Sobrien 212833965Sjdp *p = c; 212933965Sjdp demand_empty_rest_of_line (); 213077298Sobrien} 213133965Sjdp 2132130561Sobrien/* Read a line into an sb. Returns the character that ended the line 2133130561Sobrien or zero if there are no more lines. */ 213433965Sjdp 213533965Sjdpstatic int 2136130561Sobrienget_line_sb (sb *line) 213733965Sjdp{ 213833965Sjdp char quote1, quote2, inquote; 2139130561Sobrien unsigned char c; 214033965Sjdp 214133965Sjdp if (input_line_pointer[-1] == '\n') 214233965Sjdp bump_line_counters (); 214333965Sjdp 214433965Sjdp if (input_line_pointer >= buffer_limit) 214533965Sjdp { 214633965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 214733965Sjdp if (buffer_limit == 0) 214833965Sjdp return 0; 214933965Sjdp } 215033965Sjdp 215133965Sjdp /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this 215233965Sjdp code needs to be changed. */ 215377298Sobrien if (!flag_m68k_mri) 215433965Sjdp quote1 = '"'; 215533965Sjdp else 215633965Sjdp quote1 = '\0'; 215733965Sjdp 215833965Sjdp quote2 = '\0'; 215933965Sjdp if (flag_m68k_mri) 216033965Sjdp quote2 = '\''; 216133965Sjdp#ifdef LEX_IS_STRINGQUOTE 216233965Sjdp quote2 = '\''; 216333965Sjdp#endif 216433965Sjdp 216533965Sjdp inquote = '\0'; 216677298Sobrien 2167130561Sobrien while ((c = * input_line_pointer ++) != 0 2168130561Sobrien && (!is_end_of_line[c] 2169130561Sobrien || (inquote != '\0' && c != '\n'))) 217033965Sjdp { 2171130561Sobrien if (inquote == c) 217233965Sjdp inquote = '\0'; 217333965Sjdp else if (inquote == '\0') 217433965Sjdp { 2175130561Sobrien if (c == quote1) 217633965Sjdp inquote = quote1; 2177130561Sobrien else if (c == quote2) 217833965Sjdp inquote = quote2; 217933965Sjdp } 218077298Sobrien 2181130561Sobrien sb_add_char (line, c); 218233965Sjdp } 218377298Sobrien 2184130561Sobrien /* Don't skip multiple end-of-line characters, because that breaks support 2185130561Sobrien for the IA-64 stop bit (;;) which looks like two consecutive end-of-line 2186130561Sobrien characters but isn't. Instead just skip one end of line character and 2187130561Sobrien return the character skipped so that the caller can re-insert it if 2188130561Sobrien necessary. */ 2189130561Sobrien return c; 219033965Sjdp} 219133965Sjdp 2192130561Sobrien/* Define a macro. This is an interface to macro.c. */ 219333965Sjdp 219433965Sjdpvoid 2195130561Sobriens_macro (int ignore ATTRIBUTE_UNUSED) 219633965Sjdp{ 219733965Sjdp char *file; 219833965Sjdp unsigned int line; 219933965Sjdp sb s; 220033965Sjdp sb label; 220133965Sjdp const char *err; 220233965Sjdp const char *name; 220333965Sjdp 220433965Sjdp as_where (&file, &line); 220533965Sjdp 220633965Sjdp sb_new (&s); 220777298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 220833965Sjdp sb_add_char (&s, *input_line_pointer++); 220933965Sjdp 221033965Sjdp sb_new (&label); 221133965Sjdp if (line_label != NULL) 221233965Sjdp sb_add_string (&label, S_GET_NAME (line_label)); 221333965Sjdp 221433965Sjdp err = define_macro (0, &s, &label, get_line_sb, &name); 221533965Sjdp if (err != NULL) 221633965Sjdp as_bad_where (file, line, "%s", err); 221733965Sjdp else 221833965Sjdp { 221933965Sjdp if (line_label != NULL) 222033965Sjdp { 222133965Sjdp S_SET_SEGMENT (line_label, undefined_section); 222233965Sjdp S_SET_VALUE (line_label, 0); 222360484Sobrien symbol_set_frag (line_label, &zero_address_frag); 222433965Sjdp } 222533965Sjdp 222660484Sobrien if (((NO_PSEUDO_DOT || flag_m68k_mri) 222733965Sjdp && hash_find (po_hash, name) != NULL) 222877298Sobrien || (!flag_m68k_mri 222933965Sjdp && *name == '.' 223033965Sjdp && hash_find (po_hash, name + 1) != NULL)) 223160484Sobrien as_warn (_("attempt to redefine pseudo-op `%s' ignored"), 223233965Sjdp name); 223333965Sjdp } 223433965Sjdp 223533965Sjdp sb_kill (&s); 223633965Sjdp} 223733965Sjdp 223833965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro 223933965Sjdp expansion. */ 224033965Sjdp 224133965Sjdpvoid 2242130561Sobriens_mexit (int ignore ATTRIBUTE_UNUSED) 224333965Sjdp{ 224433965Sjdp cond_exit_macro (macro_nest); 224533965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 224633965Sjdp} 224733965Sjdp 224833965Sjdp/* Switch in and out of MRI mode. */ 224933965Sjdp 225033965Sjdpvoid 2251130561Sobriens_mri (int ignore ATTRIBUTE_UNUSED) 225233965Sjdp{ 225333965Sjdp int on, old_flag; 225433965Sjdp 225533965Sjdp on = get_absolute_expression (); 225633965Sjdp old_flag = flag_mri; 225733965Sjdp if (on != 0) 225833965Sjdp { 225933965Sjdp flag_mri = 1; 226033965Sjdp#ifdef TC_M68K 226133965Sjdp flag_m68k_mri = 1; 226233965Sjdp#endif 226360484Sobrien macro_mri_mode (1); 226433965Sjdp } 226533965Sjdp else 226633965Sjdp { 226733965Sjdp flag_mri = 0; 226860484Sobrien#ifdef TC_M68K 226933965Sjdp flag_m68k_mri = 0; 227060484Sobrien#endif 227160484Sobrien macro_mri_mode (0); 227233965Sjdp } 227333965Sjdp 227460484Sobrien /* Operator precedence changes in m68k MRI mode, so we need to 227560484Sobrien update the operator rankings. */ 227660484Sobrien expr_set_precedence (); 227760484Sobrien 227833965Sjdp#ifdef MRI_MODE_CHANGE 227933965Sjdp if (on != old_flag) 228033965Sjdp MRI_MODE_CHANGE (on); 228133965Sjdp#endif 228233965Sjdp 228333965Sjdp demand_empty_rest_of_line (); 228433965Sjdp} 228533965Sjdp 228633965Sjdp/* Handle changing the location counter. */ 228733965Sjdp 228833965Sjdpstatic void 2289130561Sobriendo_org (segT segment, expressionS *exp, int fill) 229033965Sjdp{ 229133965Sjdp if (segment != now_seg && segment != absolute_section) 229289857Sobrien as_bad (_("invalid segment \"%s\""), segment_name (segment)); 229333965Sjdp 229433965Sjdp if (now_seg == absolute_section) 229533965Sjdp { 229633965Sjdp if (fill != 0) 229760484Sobrien as_warn (_("ignoring fill value in absolute section")); 229833965Sjdp if (exp->X_op != O_constant) 229933965Sjdp { 230060484Sobrien as_bad (_("only constant offsets supported in absolute section")); 230133965Sjdp exp->X_add_number = 0; 230233965Sjdp } 230333965Sjdp abs_section_offset = exp->X_add_number; 230433965Sjdp } 230533965Sjdp else 230633965Sjdp { 230733965Sjdp char *p; 230878828Sobrien symbolS *sym = exp->X_add_symbol; 230978828Sobrien offsetT off = exp->X_add_number * OCTETS_PER_BYTE; 231033965Sjdp 231178828Sobrien if (exp->X_op != O_constant && exp->X_op != O_symbol) 231278828Sobrien { 231378828Sobrien /* Handle complex expressions. */ 231478828Sobrien sym = make_expr_symbol (exp); 231578828Sobrien off = 0; 231678828Sobrien } 231778828Sobrien 231878828Sobrien p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0); 231933965Sjdp *p = fill; 232033965Sjdp } 232133965Sjdp} 232233965Sjdp 232377298Sobrienvoid 2324130561Sobriens_org (int ignore ATTRIBUTE_UNUSED) 232533965Sjdp{ 232633965Sjdp register segT segment; 232733965Sjdp expressionS exp; 232833965Sjdp register long temp_fill; 232933965Sjdp 233060484Sobrien#ifdef md_flush_pending_output 233160484Sobrien md_flush_pending_output (); 233260484Sobrien#endif 233360484Sobrien 233433965Sjdp /* The m68k MRI assembler has a different meaning for .org. It 233533965Sjdp means to create an absolute section at a given address. We can't 233633965Sjdp support that--use a linker script instead. */ 233733965Sjdp if (flag_m68k_mri) 233833965Sjdp { 233960484Sobrien as_bad (_("MRI style ORG pseudo-op not supported")); 234033965Sjdp ignore_rest_of_line (); 234133965Sjdp return; 234233965Sjdp } 234333965Sjdp 234433965Sjdp /* Don't believe the documentation of BSD 4.2 AS. There is no such 234533965Sjdp thing as a sub-segment-relative origin. Any absolute origin is 234633965Sjdp given a warning, then assumed to be segment-relative. Any 234733965Sjdp segmented origin expression ("foo+42") had better be in the right 234833965Sjdp segment or the .org is ignored. 234933965Sjdp 235033965Sjdp BSD 4.2 AS warns if you try to .org backwards. We cannot because 235133965Sjdp we never know sub-segment sizes when we are reading code. BSD 235233965Sjdp will crash trying to emit negative numbers of filler bytes in 235333965Sjdp certain .orgs. We don't crash, but see as-write for that code. 235433965Sjdp 235533965Sjdp Don't make frag if need_pass_2==1. */ 235633965Sjdp segment = get_known_segmented_expression (&exp); 235733965Sjdp if (*input_line_pointer == ',') 235833965Sjdp { 235933965Sjdp input_line_pointer++; 236033965Sjdp temp_fill = get_absolute_expression (); 236133965Sjdp } 236233965Sjdp else 236333965Sjdp temp_fill = 0; 236433965Sjdp 236533965Sjdp if (!need_pass_2) 236633965Sjdp do_org (segment, &exp, temp_fill); 236733965Sjdp 236833965Sjdp demand_empty_rest_of_line (); 236977298Sobrien} 237033965Sjdp 237133965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op. This should be 237233965Sjdp called by the obj-format routine which handles section changing 237333965Sjdp when in MRI mode. It will create a new section, and return it. It 237433965Sjdp will set *TYPE to the section type: one of 'C' (code), 'D' (data), 237533965Sjdp 'M' (mixed), or 'R' (romable). If BFD_ASSEMBLER is defined, the 237633965Sjdp flags will be set in the section. */ 237733965Sjdp 237833965Sjdpvoid 2379130561Sobriens_mri_sect (char *type ATTRIBUTE_UNUSED) 238033965Sjdp{ 238133965Sjdp#ifdef TC_M68K 238233965Sjdp 238333965Sjdp char *name; 238433965Sjdp char c; 238533965Sjdp segT seg; 238633965Sjdp 238733965Sjdp SKIP_WHITESPACE (); 238877298Sobrien 238933965Sjdp name = input_line_pointer; 239089857Sobrien if (!ISDIGIT (*name)) 239133965Sjdp c = get_symbol_end (); 239233965Sjdp else 239333965Sjdp { 239433965Sjdp do 239533965Sjdp { 239633965Sjdp ++input_line_pointer; 239733965Sjdp } 239889857Sobrien while (ISDIGIT (*input_line_pointer)); 239977298Sobrien 240033965Sjdp c = *input_line_pointer; 240133965Sjdp *input_line_pointer = '\0'; 240233965Sjdp } 240333965Sjdp 240433965Sjdp name = xstrdup (name); 240533965Sjdp 240633965Sjdp *input_line_pointer = c; 240733965Sjdp 240833965Sjdp seg = subseg_new (name, 0); 240933965Sjdp 241033965Sjdp if (*input_line_pointer == ',') 241133965Sjdp { 241233965Sjdp int align; 241333965Sjdp 241433965Sjdp ++input_line_pointer; 241533965Sjdp align = get_absolute_expression (); 241633965Sjdp record_alignment (seg, align); 241733965Sjdp } 241833965Sjdp 241933965Sjdp *type = 'C'; 242033965Sjdp if (*input_line_pointer == ',') 242133965Sjdp { 242233965Sjdp c = *++input_line_pointer; 242389857Sobrien c = TOUPPER (c); 242433965Sjdp if (c == 'C' || c == 'D' || c == 'M' || c == 'R') 242533965Sjdp *type = c; 242633965Sjdp else 242760484Sobrien as_bad (_("unrecognized section type")); 242833965Sjdp ++input_line_pointer; 242933965Sjdp 243033965Sjdp#ifdef BFD_ASSEMBLER 243133965Sjdp { 243233965Sjdp flagword flags; 243333965Sjdp 243433965Sjdp flags = SEC_NO_FLAGS; 243533965Sjdp if (*type == 'C') 243633965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE; 243733965Sjdp else if (*type == 'D' || *type == 'M') 243833965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_DATA; 243933965Sjdp else if (*type == 'R') 244033965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM; 244133965Sjdp if (flags != SEC_NO_FLAGS) 244233965Sjdp { 244377298Sobrien if (!bfd_set_section_flags (stdoutput, seg, flags)) 244460484Sobrien as_warn (_("error setting flags for \"%s\": %s"), 244533965Sjdp bfd_section_name (stdoutput, seg), 244633965Sjdp bfd_errmsg (bfd_get_error ())); 244733965Sjdp } 244833965Sjdp } 244933965Sjdp#endif 245033965Sjdp } 245133965Sjdp 245233965Sjdp /* Ignore the HP type. */ 245333965Sjdp if (*input_line_pointer == ',') 245433965Sjdp input_line_pointer += 2; 245533965Sjdp 245633965Sjdp demand_empty_rest_of_line (); 245733965Sjdp 245833965Sjdp#else /* ! TC_M68K */ 245933965Sjdp#ifdef TC_I960 246033965Sjdp 246133965Sjdp char *name; 246233965Sjdp char c; 246333965Sjdp segT seg; 246433965Sjdp 246533965Sjdp SKIP_WHITESPACE (); 246633965Sjdp 246733965Sjdp name = input_line_pointer; 246833965Sjdp c = get_symbol_end (); 246933965Sjdp 247033965Sjdp name = xstrdup (name); 247133965Sjdp 247233965Sjdp *input_line_pointer = c; 247333965Sjdp 247433965Sjdp seg = subseg_new (name, 0); 247533965Sjdp 247633965Sjdp if (*input_line_pointer != ',') 247733965Sjdp *type = 'C'; 247833965Sjdp else 247933965Sjdp { 248033965Sjdp char *sectype; 248133965Sjdp 248233965Sjdp ++input_line_pointer; 248333965Sjdp SKIP_WHITESPACE (); 248433965Sjdp sectype = input_line_pointer; 248533965Sjdp c = get_symbol_end (); 248633965Sjdp if (*sectype == '\0') 248733965Sjdp *type = 'C'; 248833965Sjdp else if (strcasecmp (sectype, "text") == 0) 248933965Sjdp *type = 'C'; 249033965Sjdp else if (strcasecmp (sectype, "data") == 0) 249133965Sjdp *type = 'D'; 249233965Sjdp else if (strcasecmp (sectype, "romdata") == 0) 249333965Sjdp *type = 'R'; 249433965Sjdp else 249560484Sobrien as_warn (_("unrecognized section type `%s'"), sectype); 249633965Sjdp *input_line_pointer = c; 249733965Sjdp } 249833965Sjdp 249933965Sjdp if (*input_line_pointer == ',') 250033965Sjdp { 250133965Sjdp char *seccmd; 250233965Sjdp 250333965Sjdp ++input_line_pointer; 250433965Sjdp SKIP_WHITESPACE (); 250533965Sjdp seccmd = input_line_pointer; 250633965Sjdp c = get_symbol_end (); 250733965Sjdp if (strcasecmp (seccmd, "absolute") == 0) 250833965Sjdp { 250960484Sobrien as_bad (_("absolute sections are not supported")); 251033965Sjdp *input_line_pointer = c; 251133965Sjdp ignore_rest_of_line (); 251233965Sjdp return; 251333965Sjdp } 251433965Sjdp else if (strcasecmp (seccmd, "align") == 0) 251533965Sjdp { 251633965Sjdp int align; 251733965Sjdp 251833965Sjdp *input_line_pointer = c; 251933965Sjdp align = get_absolute_expression (); 252033965Sjdp record_alignment (seg, align); 252133965Sjdp } 252233965Sjdp else 252333965Sjdp { 252460484Sobrien as_warn (_("unrecognized section command `%s'"), seccmd); 252533965Sjdp *input_line_pointer = c; 252633965Sjdp } 252733965Sjdp } 252833965Sjdp 252977298Sobrien demand_empty_rest_of_line (); 253033965Sjdp 253133965Sjdp#else /* ! TC_I960 */ 253233965Sjdp /* The MRI assembler seems to use different forms of .sect for 253333965Sjdp different targets. */ 253460484Sobrien as_bad ("MRI mode not supported for this target"); 253560484Sobrien ignore_rest_of_line (); 253633965Sjdp#endif /* ! TC_I960 */ 253733965Sjdp#endif /* ! TC_M68K */ 253833965Sjdp} 253933965Sjdp 254033965Sjdp/* Handle the .print pseudo-op. */ 254133965Sjdp 254233965Sjdpvoid 2543130561Sobriens_print (int ignore ATTRIBUTE_UNUSED) 254433965Sjdp{ 254533965Sjdp char *s; 254633965Sjdp int len; 254733965Sjdp 254833965Sjdp s = demand_copy_C_string (&len); 2549130561Sobrien if (s != NULL) 2550130561Sobrien printf ("%s\n", s); 255133965Sjdp demand_empty_rest_of_line (); 255233965Sjdp} 255333965Sjdp 255433965Sjdp/* Handle the .purgem pseudo-op. */ 255533965Sjdp 255633965Sjdpvoid 2557130561Sobriens_purgem (int ignore ATTRIBUTE_UNUSED) 255833965Sjdp{ 255933965Sjdp if (is_it_end_of_statement ()) 256033965Sjdp { 256133965Sjdp demand_empty_rest_of_line (); 256233965Sjdp return; 256333965Sjdp } 256433965Sjdp 256533965Sjdp do 256633965Sjdp { 256733965Sjdp char *name; 256833965Sjdp char c; 256933965Sjdp 257033965Sjdp SKIP_WHITESPACE (); 257133965Sjdp name = input_line_pointer; 257233965Sjdp c = get_symbol_end (); 257333965Sjdp delete_macro (name); 257433965Sjdp *input_line_pointer = c; 257533965Sjdp SKIP_WHITESPACE (); 257633965Sjdp } 257733965Sjdp while (*input_line_pointer++ == ','); 257833965Sjdp 257933965Sjdp --input_line_pointer; 258033965Sjdp demand_empty_rest_of_line (); 258133965Sjdp} 258233965Sjdp 258333965Sjdp/* Handle the .rept pseudo-op. */ 258433965Sjdp 258533965Sjdpvoid 2586130561Sobriens_bad_endr (int ignore ATTRIBUTE_UNUSED) 258789857Sobrien{ 258889857Sobrien as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp")); 258989857Sobrien demand_empty_rest_of_line (); 259089857Sobrien} 259189857Sobrien 259289857Sobrien/* Handle the .rept pseudo-op. */ 259389857Sobrien 259489857Sobrienvoid 2595130561Sobriens_rept (int ignore ATTRIBUTE_UNUSED) 259633965Sjdp{ 259733965Sjdp int count; 259860484Sobrien 259960484Sobrien count = get_absolute_expression (); 260060484Sobrien 260177298Sobrien do_repeat (count, "REPT", "ENDR"); 260260484Sobrien} 260360484Sobrien 260460484Sobrien/* This function provides a generic repeat block implementation. It allows 260577298Sobrien different directives to be used as the start/end keys. */ 260660484Sobrien 260760484Sobrienvoid 2608130561Sobriendo_repeat (int count, const char *start, const char *end) 260960484Sobrien{ 261033965Sjdp sb one; 261133965Sjdp sb many; 261233965Sjdp 261333965Sjdp sb_new (&one); 261477298Sobrien if (!buffer_and_nest (start, end, &one, get_line_sb)) 261533965Sjdp { 261660484Sobrien as_bad (_("%s without %s"), start, end); 261733965Sjdp return; 261833965Sjdp } 261933965Sjdp 262033965Sjdp sb_new (&many); 262133965Sjdp while (count-- > 0) 262233965Sjdp sb_add_sb (&many, &one); 262333965Sjdp 262433965Sjdp sb_kill (&one); 262533965Sjdp 262660484Sobrien input_scrub_include_sb (&many, input_line_pointer, 1); 262733965Sjdp sb_kill (&many); 262833965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 262933965Sjdp} 263033965Sjdp 263160484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional 263260484Sobrien input buffers to skip. Assumes that conditionals preceding the loop end 263377298Sobrien are properly nested. 263460484Sobrien 263560484Sobrien This function makes it easier to implement a premature "break" out of the 263660484Sobrien loop. The EXTRA arg accounts for other buffers we might have inserted, 263777298Sobrien such as line substitutions. */ 263860484Sobrien 263960484Sobrienvoid 2640130561Sobrienend_repeat (int extra) 264160484Sobrien{ 264260484Sobrien cond_exit_macro (macro_nest); 264360484Sobrien while (extra-- >= 0) 264460484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 264560484Sobrien} 264660484Sobrien 264733965Sjdp/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then 264833965Sjdp this is .equiv, and it is an error if the symbol is already 264933965Sjdp defined. */ 265033965Sjdp 265177298Sobrienvoid 2652130561Sobriens_set (int equiv) 265333965Sjdp{ 265433965Sjdp register char *name; 265533965Sjdp register char delim; 265633965Sjdp register char *end_name; 265733965Sjdp register symbolS *symbolP; 265833965Sjdp 265977298Sobrien /* Especial apologies for the random logic: 266077298Sobrien this just grew, and could be parsed much more simply! 266177298Sobrien Dean in haste. */ 266233965Sjdp name = input_line_pointer; 266333965Sjdp delim = get_symbol_end (); 266433965Sjdp end_name = input_line_pointer; 266533965Sjdp *end_name = delim; 266689857Sobrien 266789857Sobrien if (name == end_name) 266889857Sobrien { 266989857Sobrien as_bad (_("expected symbol name")); 267089857Sobrien discard_rest_of_line (); 267189857Sobrien return; 267289857Sobrien } 267389857Sobrien 267433965Sjdp SKIP_WHITESPACE (); 267533965Sjdp 267633965Sjdp if (*input_line_pointer != ',') 267733965Sjdp { 267833965Sjdp *end_name = 0; 267989857Sobrien as_bad (_("expected comma after \"%s\""), name); 268033965Sjdp *end_name = delim; 268133965Sjdp ignore_rest_of_line (); 268233965Sjdp return; 268333965Sjdp } 268433965Sjdp 268533965Sjdp input_line_pointer++; 268633965Sjdp *end_name = 0; 268733965Sjdp 268833965Sjdp if (name[0] == '.' && name[1] == '\0') 268933965Sjdp { 269077298Sobrien /* Turn '. = mumble' into a .org mumble. */ 269133965Sjdp register segT segment; 269233965Sjdp expressionS exp; 269333965Sjdp 269433965Sjdp segment = get_known_segmented_expression (&exp); 269533965Sjdp 269633965Sjdp if (!need_pass_2) 269733965Sjdp do_org (segment, &exp, 0); 269833965Sjdp 269933965Sjdp *end_name = delim; 270033965Sjdp return; 270133965Sjdp } 270233965Sjdp 270333965Sjdp if ((symbolP = symbol_find (name)) == NULL 270433965Sjdp && (symbolP = md_undefined_symbol (name)) == NULL) 270533965Sjdp { 270638889Sjdp#ifndef NO_LISTING 270738889Sjdp /* When doing symbol listings, play games with dummy fragments living 270838889Sjdp outside the normal fragment chain to record the file and line info 2709130561Sobrien for this symbol. */ 271038889Sjdp if (listing & LISTING_SYMBOLS) 271138889Sjdp { 271238889Sjdp extern struct list_info_struct *listing_tail; 271377298Sobrien fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS)); 271477298Sobrien memset (dummy_frag, 0, sizeof (fragS)); 271538889Sjdp dummy_frag->fr_type = rs_fill; 271638889Sjdp dummy_frag->line = listing_tail; 271738889Sjdp symbolP = symbol_new (name, undefined_section, 0, dummy_frag); 271838889Sjdp dummy_frag->fr_symbol = symbolP; 271938889Sjdp } 272038889Sjdp else 272138889Sjdp#endif 272277298Sobrien symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); 272377298Sobrien 272433965Sjdp#ifdef OBJ_COFF 272577298Sobrien /* "set" symbols are local unless otherwise specified. */ 272633965Sjdp SF_SET_LOCAL (symbolP); 272733965Sjdp#endif /* OBJ_COFF */ 272877298Sobrien } 272933965Sjdp 273033965Sjdp symbol_table_insert (symbolP); 273133965Sjdp 273233965Sjdp *end_name = delim; 273333965Sjdp 273433965Sjdp if (equiv 273533965Sjdp && S_IS_DEFINED (symbolP) 273633965Sjdp && S_GET_SEGMENT (symbolP) != reg_section) 273789857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 273833965Sjdp 273933965Sjdp pseudo_set (symbolP); 274033965Sjdp demand_empty_rest_of_line (); 274177298Sobrien} 274233965Sjdp 274377298Sobrienvoid 2744130561Sobriens_space (int mult) 274533965Sjdp{ 274633965Sjdp expressionS exp; 274733965Sjdp expressionS val; 274833965Sjdp char *p = 0; 274933965Sjdp char *stop = NULL; 275033965Sjdp char stopc; 275133965Sjdp int bytes; 275233965Sjdp 275333965Sjdp#ifdef md_flush_pending_output 275433965Sjdp md_flush_pending_output (); 275533965Sjdp#endif 275633965Sjdp 275733965Sjdp if (flag_mri) 275833965Sjdp stop = mri_comment_field (&stopc); 275933965Sjdp 276033965Sjdp /* In m68k MRI mode, we need to align to a word boundary, unless 276133965Sjdp this is ds.b. */ 276233965Sjdp if (flag_m68k_mri && mult > 1) 276333965Sjdp { 276433965Sjdp if (now_seg == absolute_section) 276533965Sjdp { 276633965Sjdp abs_section_offset += abs_section_offset & 1; 276733965Sjdp if (line_label != NULL) 276833965Sjdp S_SET_VALUE (line_label, abs_section_offset); 276933965Sjdp } 277033965Sjdp else if (mri_common_symbol != NULL) 277133965Sjdp { 277233965Sjdp valueT val; 277333965Sjdp 277433965Sjdp val = S_GET_VALUE (mri_common_symbol); 277533965Sjdp if ((val & 1) != 0) 277633965Sjdp { 277733965Sjdp S_SET_VALUE (mri_common_symbol, val + 1); 277833965Sjdp if (line_label != NULL) 277933965Sjdp { 278060484Sobrien expressionS *symexp; 278160484Sobrien 278260484Sobrien symexp = symbol_get_value_expression (line_label); 278360484Sobrien know (symexp->X_op == O_symbol); 278460484Sobrien know (symexp->X_add_symbol == mri_common_symbol); 278560484Sobrien symexp->X_add_number += 1; 278633965Sjdp } 278733965Sjdp } 278833965Sjdp } 278933965Sjdp else 279033965Sjdp { 279133965Sjdp do_align (1, (char *) NULL, 0, 0); 279233965Sjdp if (line_label != NULL) 279333965Sjdp { 279460484Sobrien symbol_set_frag (line_label, frag_now); 279533965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 279633965Sjdp } 279733965Sjdp } 279833965Sjdp } 279933965Sjdp 280033965Sjdp bytes = mult; 280133965Sjdp 280233965Sjdp expression (&exp); 280333965Sjdp 280433965Sjdp SKIP_WHITESPACE (); 280533965Sjdp if (*input_line_pointer == ',') 280633965Sjdp { 280733965Sjdp ++input_line_pointer; 280833965Sjdp expression (&val); 280933965Sjdp } 281033965Sjdp else 281133965Sjdp { 281233965Sjdp val.X_op = O_constant; 281333965Sjdp val.X_add_number = 0; 281433965Sjdp } 281533965Sjdp 281633965Sjdp if (val.X_op != O_constant 281733965Sjdp || val.X_add_number < - 0x80 281833965Sjdp || val.X_add_number > 0xff 281933965Sjdp || (mult != 0 && mult != 1 && val.X_add_number != 0)) 282033965Sjdp { 282133965Sjdp if (exp.X_op != O_constant) 282289857Sobrien as_bad (_("unsupported variable size or fill value")); 282333965Sjdp else 282433965Sjdp { 282533965Sjdp offsetT i; 282633965Sjdp 282733965Sjdp if (mult == 0) 282833965Sjdp mult = 1; 282933965Sjdp bytes = mult * exp.X_add_number; 283033965Sjdp for (i = 0; i < exp.X_add_number; i++) 283133965Sjdp emit_expr (&val, mult); 283233965Sjdp } 283333965Sjdp } 283433965Sjdp else 283533965Sjdp { 283633965Sjdp if (exp.X_op == O_constant) 283733965Sjdp { 283833965Sjdp long repeat; 283933965Sjdp 284033965Sjdp repeat = exp.X_add_number; 284133965Sjdp if (mult) 284233965Sjdp repeat *= mult; 284333965Sjdp bytes = repeat; 284433965Sjdp if (repeat <= 0) 284533965Sjdp { 284677298Sobrien if (!flag_mri) 284760484Sobrien as_warn (_(".space repeat count is zero, ignored")); 284860484Sobrien else if (repeat < 0) 284960484Sobrien as_warn (_(".space repeat count is negative, ignored")); 285033965Sjdp goto getout; 285133965Sjdp } 285233965Sjdp 285333965Sjdp /* If we are in the absolute section, just bump the offset. */ 285433965Sjdp if (now_seg == absolute_section) 285533965Sjdp { 285633965Sjdp abs_section_offset += repeat; 285733965Sjdp goto getout; 285833965Sjdp } 285933965Sjdp 286033965Sjdp /* If we are secretly in an MRI common section, then 286133965Sjdp creating space just increases the size of the common 286233965Sjdp symbol. */ 286333965Sjdp if (mri_common_symbol != NULL) 286433965Sjdp { 286533965Sjdp S_SET_VALUE (mri_common_symbol, 286633965Sjdp S_GET_VALUE (mri_common_symbol) + repeat); 286733965Sjdp goto getout; 286833965Sjdp } 286933965Sjdp 287033965Sjdp if (!need_pass_2) 287133965Sjdp p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, 287233965Sjdp (offsetT) repeat, (char *) 0); 287333965Sjdp } 287433965Sjdp else 287533965Sjdp { 287633965Sjdp if (now_seg == absolute_section) 287733965Sjdp { 287860484Sobrien as_bad (_("space allocation too complex in absolute section")); 287933965Sjdp subseg_set (text_section, 0); 288033965Sjdp } 288177298Sobrien 288233965Sjdp if (mri_common_symbol != NULL) 288333965Sjdp { 288460484Sobrien as_bad (_("space allocation too complex in common section")); 288533965Sjdp mri_common_symbol = NULL; 288633965Sjdp } 288777298Sobrien 288833965Sjdp if (!need_pass_2) 288933965Sjdp p = frag_var (rs_space, 1, 1, (relax_substateT) 0, 289033965Sjdp make_expr_symbol (&exp), (offsetT) 0, (char *) 0); 289133965Sjdp } 289233965Sjdp 289333965Sjdp if (p) 289433965Sjdp *p = val.X_add_number; 289533965Sjdp } 289633965Sjdp 289733965Sjdp getout: 289833965Sjdp 289933965Sjdp /* In MRI mode, after an odd number of bytes, we must align to an 290033965Sjdp even word boundary, unless the next instruction is a dc.b, ds.b 290133965Sjdp or dcb.b. */ 290233965Sjdp if (flag_mri && (bytes & 1) != 0) 290333965Sjdp mri_pending_align = 1; 290433965Sjdp 290560484Sobrien demand_empty_rest_of_line (); 290660484Sobrien 290733965Sjdp if (flag_mri) 290833965Sjdp mri_comment_end (stop, stopc); 290933965Sjdp} 291033965Sjdp 291133965Sjdp/* This is like s_space, but the value is a floating point number with 291233965Sjdp the given precision. This is for the MRI dcb.s pseudo-op and 291333965Sjdp friends. */ 291433965Sjdp 291533965Sjdpvoid 2916130561Sobriens_float_space (int float_type) 291733965Sjdp{ 291833965Sjdp offsetT count; 291933965Sjdp int flen; 292033965Sjdp char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 292133965Sjdp char *stop = NULL; 292233965Sjdp char stopc; 292333965Sjdp 292433965Sjdp if (flag_mri) 292533965Sjdp stop = mri_comment_field (&stopc); 292633965Sjdp 292733965Sjdp count = get_absolute_expression (); 292833965Sjdp 292933965Sjdp SKIP_WHITESPACE (); 293033965Sjdp if (*input_line_pointer != ',') 293133965Sjdp { 293260484Sobrien as_bad (_("missing value")); 293360484Sobrien ignore_rest_of_line (); 293433965Sjdp if (flag_mri) 293533965Sjdp mri_comment_end (stop, stopc); 293633965Sjdp return; 293733965Sjdp } 293833965Sjdp 293933965Sjdp ++input_line_pointer; 294033965Sjdp 294133965Sjdp SKIP_WHITESPACE (); 294233965Sjdp 294333965Sjdp /* Skip any 0{letter} that may be present. Don't even check if the 294433965Sjdp * letter is legal. */ 294538889Sjdp if (input_line_pointer[0] == '0' 294689857Sobrien && ISALPHA (input_line_pointer[1])) 294733965Sjdp input_line_pointer += 2; 294833965Sjdp 294933965Sjdp /* Accept :xxxx, where the x's are hex digits, for a floating point 295033965Sjdp with the exact digits specified. */ 295133965Sjdp if (input_line_pointer[0] == ':') 295233965Sjdp { 295333965Sjdp flen = hex_float (float_type, temp); 295433965Sjdp if (flen < 0) 295533965Sjdp { 295660484Sobrien ignore_rest_of_line (); 295733965Sjdp if (flag_mri) 295833965Sjdp mri_comment_end (stop, stopc); 295933965Sjdp return; 296033965Sjdp } 296133965Sjdp } 296233965Sjdp else 296333965Sjdp { 296433965Sjdp char *err; 296533965Sjdp 296633965Sjdp err = md_atof (float_type, temp, &flen); 296733965Sjdp know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 296833965Sjdp know (flen > 0); 296933965Sjdp if (err) 297033965Sjdp { 297189857Sobrien as_bad (_("bad floating literal: %s"), err); 297260484Sobrien ignore_rest_of_line (); 297333965Sjdp if (flag_mri) 297433965Sjdp mri_comment_end (stop, stopc); 297533965Sjdp return; 297633965Sjdp } 297733965Sjdp } 297833965Sjdp 297933965Sjdp while (--count >= 0) 298033965Sjdp { 298133965Sjdp char *p; 298233965Sjdp 298333965Sjdp p = frag_more (flen); 298433965Sjdp memcpy (p, temp, (unsigned int) flen); 298533965Sjdp } 298633965Sjdp 298760484Sobrien demand_empty_rest_of_line (); 298860484Sobrien 298933965Sjdp if (flag_mri) 299033965Sjdp mri_comment_end (stop, stopc); 299133965Sjdp} 299233965Sjdp 299333965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers. */ 299433965Sjdp 299533965Sjdpvoid 2996130561Sobriens_struct (int ignore ATTRIBUTE_UNUSED) 299733965Sjdp{ 299833965Sjdp char *stop = NULL; 299933965Sjdp char stopc; 300033965Sjdp 300133965Sjdp if (flag_mri) 300233965Sjdp stop = mri_comment_field (&stopc); 300333965Sjdp abs_section_offset = get_absolute_expression (); 300433965Sjdp subseg_set (absolute_section, 0); 300560484Sobrien demand_empty_rest_of_line (); 300633965Sjdp if (flag_mri) 300733965Sjdp mri_comment_end (stop, stopc); 300833965Sjdp} 300933965Sjdp 301033965Sjdpvoid 3011130561Sobriens_text (int ignore ATTRIBUTE_UNUSED) 301233965Sjdp{ 301333965Sjdp register int temp; 301433965Sjdp 301533965Sjdp temp = get_absolute_expression (); 301633965Sjdp subseg_set (text_section, (subsegT) temp); 301733965Sjdp demand_empty_rest_of_line (); 301833965Sjdp#ifdef OBJ_VMS 301933965Sjdp const_flag &= ~IN_DEFAULT_SECTION; 302033965Sjdp#endif 302177298Sobrien} 302233965Sjdp 3023130561Sobrien 3024130561Sobrien/* Verify that we are at the end of a line. If not, issue an error and 3025130561Sobrien skip to EOL. */ 3026130561Sobrien 302777298Sobrienvoid 3028130561Sobriendemand_empty_rest_of_line (void) 302933965Sjdp{ 303033965Sjdp SKIP_WHITESPACE (); 303133965Sjdp if (is_end_of_line[(unsigned char) *input_line_pointer]) 303277298Sobrien input_line_pointer++; 303333965Sjdp else 303433965Sjdp { 303589857Sobrien if (ISPRINT (*input_line_pointer)) 3036130561Sobrien as_bad (_("junk at end of line, first unrecognized character is `%c'"), 303789857Sobrien *input_line_pointer); 303833965Sjdp else 3039130561Sobrien as_bad (_("junk at end of line, first unrecognized character valued 0x%x"), 304089857Sobrien *input_line_pointer); 3041130561Sobrien ignore_rest_of_line (); 304233965Sjdp } 3043130561Sobrien 3044130561Sobrien /* Return pointing just after end-of-line. */ 3045130561Sobrien know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 3046130561Sobrien} 304777298Sobrien 3048130561Sobrien/* Silently advance to the end of line. Use this after already having 3049130561Sobrien issued an error about something bad. */ 3050130561Sobrien 3051130561Sobrienvoid 3052130561Sobrienignore_rest_of_line (void) 3053130561Sobrien{ 3054130561Sobrien while (input_line_pointer < buffer_limit 3055130561Sobrien && !is_end_of_line[(unsigned char) *input_line_pointer]) 3056130561Sobrien input_line_pointer++; 3057130561Sobrien 305877298Sobrien input_line_pointer++; 305977298Sobrien 306077298Sobrien /* Return pointing just after end-of-line. */ 306133965Sjdp know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 306233965Sjdp} 306333965Sjdp 306460484Sobrienvoid 3065130561Sobriendiscard_rest_of_line (void) 306660484Sobrien{ 306760484Sobrien while (input_line_pointer < buffer_limit 306877298Sobrien && !is_end_of_line[(unsigned char) *input_line_pointer]) 306977298Sobrien input_line_pointer++; 307077298Sobrien 307177298Sobrien input_line_pointer++; 307277298Sobrien 307377298Sobrien /* Return pointing just after end-of-line. */ 307460484Sobrien know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 307560484Sobrien} 307660484Sobrien 307777298Sobrien/* In: Pointer to a symbol. 3078130561Sobrien Input_line_pointer->expression. 307977298Sobrien 308077298Sobrien Out: Input_line_pointer->just after any whitespace after expression. 3081130561Sobrien Tried to set symbol to value of expression. 3082130561Sobrien Will change symbols type, value, and frag; */ 308377298Sobrien 308433965Sjdpvoid 3085130561Sobrienpseudo_set (symbolS *symbolP) 308633965Sjdp{ 308733965Sjdp expressionS exp; 308833965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 308933965Sjdp int ext; 309033965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 309133965Sjdp 309277298Sobrien know (symbolP); /* NULL pointer is logic error. */ 309333965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 309433965Sjdp ext = S_IS_EXTERNAL (symbolP); 309533965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 309633965Sjdp 309733965Sjdp (void) expression (&exp); 309833965Sjdp 309933965Sjdp if (exp.X_op == O_illegal) 310089857Sobrien as_bad (_("illegal expression")); 310133965Sjdp else if (exp.X_op == O_absent) 310289857Sobrien as_bad (_("missing expression")); 310333965Sjdp else if (exp.X_op == O_big) 310460484Sobrien { 310560484Sobrien if (exp.X_add_number > 0) 310689857Sobrien as_bad (_("bignum invalid")); 310760484Sobrien else 310889857Sobrien as_bad (_("floating point number invalid")); 310960484Sobrien } 311033965Sjdp else if (exp.X_op == O_subtract 311133965Sjdp && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol)) 311260484Sobrien && (symbol_get_frag (exp.X_add_symbol) 311360484Sobrien == symbol_get_frag (exp.X_op_symbol))) 311433965Sjdp { 311533965Sjdp exp.X_op = O_constant; 311633965Sjdp exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol) 311733965Sjdp - S_GET_VALUE (exp.X_op_symbol)); 311833965Sjdp } 311933965Sjdp 312033965Sjdp switch (exp.X_op) 312133965Sjdp { 312233965Sjdp case O_illegal: 312333965Sjdp case O_absent: 312433965Sjdp case O_big: 312533965Sjdp exp.X_add_number = 0; 312633965Sjdp /* Fall through. */ 312733965Sjdp case O_constant: 312833965Sjdp S_SET_SEGMENT (symbolP, absolute_section); 312933965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 313033965Sjdp if (ext) 313133965Sjdp S_SET_EXTERNAL (symbolP); 313233965Sjdp else 313333965Sjdp S_CLEAR_EXTERNAL (symbolP); 313433965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 313533965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 313638889Sjdp if (exp.X_op != O_constant) 313777298Sobrien symbol_set_frag (symbolP, &zero_address_frag); 313833965Sjdp break; 313933965Sjdp 314033965Sjdp case O_register: 314133965Sjdp S_SET_SEGMENT (symbolP, reg_section); 314233965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 314360484Sobrien symbol_set_frag (symbolP, &zero_address_frag); 314433965Sjdp break; 314533965Sjdp 314633965Sjdp case O_symbol: 314733965Sjdp if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section 314833965Sjdp || exp.X_add_number != 0) 314960484Sobrien symbol_set_value_expression (symbolP, &exp); 315060484Sobrien else if (symbol_section_p (symbolP)) 315189857Sobrien as_bad ("attempt to set value of section symbol"); 315233965Sjdp else 315333965Sjdp { 315433965Sjdp symbolS *s = exp.X_add_symbol; 315533965Sjdp 315633965Sjdp S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s)); 315733965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 315833965Sjdp if (ext) 315933965Sjdp S_SET_EXTERNAL (symbolP); 316033965Sjdp else 316133965Sjdp S_CLEAR_EXTERNAL (symbolP); 316233965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 316333965Sjdp S_SET_VALUE (symbolP, 316433965Sjdp exp.X_add_number + S_GET_VALUE (s)); 316560484Sobrien symbol_set_frag (symbolP, symbol_get_frag (s)); 316633965Sjdp copy_symbol_attributes (symbolP, s); 316733965Sjdp } 316833965Sjdp break; 316933965Sjdp 317033965Sjdp default: 317133965Sjdp /* The value is some complex expression. 317233965Sjdp FIXME: Should we set the segment to anything? */ 317360484Sobrien symbol_set_value_expression (symbolP, &exp); 317433965Sjdp break; 317533965Sjdp } 317633965Sjdp} 317733965Sjdp 3178130561Sobrien/* cons() 317933965Sjdp 318077298Sobrien CONStruct more frag of .bytes, or .words etc. 318177298Sobrien Should need_pass_2 be 1 then emit no frag(s). 318277298Sobrien This understands EXPRESSIONS. 318377298Sobrien 318477298Sobrien Bug (?) 318577298Sobrien 318677298Sobrien This has a split personality. We use expression() to read the 318777298Sobrien value. We can detect if the value won't fit in a byte or word. 318877298Sobrien But we can't detect if expression() discarded significant digits 318977298Sobrien in the case of a long. Not worth the crocks required to fix it. */ 319077298Sobrien 319133965Sjdp/* Select a parser for cons expressions. */ 319233965Sjdp 319333965Sjdp/* Some targets need to parse the expression in various fancy ways. 319433965Sjdp You can define TC_PARSE_CONS_EXPRESSION to do whatever you like 319533965Sjdp (for example, the HPPA does this). Otherwise, you can define 319633965Sjdp BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or 319733965Sjdp REPEAT_CONS_EXPRESSIONS to permit repeat counts. If none of these 319833965Sjdp are defined, which is the normal case, then only simple expressions 319933965Sjdp are permitted. */ 320033965Sjdp 320160484Sobrien#ifdef TC_M68K 320233965Sjdpstatic void 3203130561Sobrienparse_mri_cons (expressionS *exp, unsigned int nbytes); 320460484Sobrien#endif 320533965Sjdp 320633965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION 320733965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS 320833965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES) 320977298Sobrienstatic void 3210130561Sobrienparse_bitfield_cons (expressionS *exp, unsigned int nbytes); 321133965Sjdp#endif 321233965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 321333965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES) 321433965Sjdpstatic void 3215130561Sobrienparse_repeat_cons (expressionS *exp, unsigned int nbytes); 321633965Sjdp#endif 321733965Sjdp 321833965Sjdp/* If we haven't gotten one yet, just call expression. */ 321933965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION 322033965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP) 322133965Sjdp#endif 322233965Sjdp#endif 322333965Sjdp 3224130561Sobrienvoid 3225130561Sobriendo_parse_cons_expression (expressionS *exp, 3226130561Sobrien int nbytes ATTRIBUTE_UNUSED) 3227130561Sobrien{ 3228130561Sobrien TC_PARSE_CONS_EXPRESSION (exp, nbytes); 3229130561Sobrien} 3230130561Sobrien 3231130561Sobrien 323277298Sobrien/* Worker to do .byte etc statements. 323377298Sobrien Clobbers input_line_pointer and checks end-of-line. */ 323477298Sobrien 323577298Sobrienstatic void 3236130561Sobriencons_worker (register int nbytes, /* 1=.byte, 2=.word, 4=.long. */ 3237130561Sobrien int rva) 323833965Sjdp{ 323933965Sjdp int c; 324033965Sjdp expressionS exp; 324133965Sjdp char *stop = NULL; 324233965Sjdp char stopc; 324333965Sjdp 324433965Sjdp#ifdef md_flush_pending_output 324533965Sjdp md_flush_pending_output (); 324633965Sjdp#endif 324733965Sjdp 324833965Sjdp if (flag_mri) 324933965Sjdp stop = mri_comment_field (&stopc); 325033965Sjdp 325133965Sjdp if (is_it_end_of_statement ()) 325233965Sjdp { 325360484Sobrien demand_empty_rest_of_line (); 325433965Sjdp if (flag_mri) 325533965Sjdp mri_comment_end (stop, stopc); 325633965Sjdp return; 325733965Sjdp } 325833965Sjdp 325933965Sjdp#ifdef md_cons_align 326033965Sjdp md_cons_align (nbytes); 326133965Sjdp#endif 326233965Sjdp 326333965Sjdp c = 0; 326433965Sjdp do 326533965Sjdp { 326660484Sobrien#ifdef TC_M68K 326733965Sjdp if (flag_m68k_mri) 326833965Sjdp parse_mri_cons (&exp, (unsigned int) nbytes); 326933965Sjdp else 327060484Sobrien#endif 327133965Sjdp TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); 327233965Sjdp 327333965Sjdp if (rva) 327433965Sjdp { 327533965Sjdp if (exp.X_op == O_symbol) 327633965Sjdp exp.X_op = O_symbol_rva; 327733965Sjdp else 327860484Sobrien as_fatal (_("rva without symbol")); 327933965Sjdp } 328033965Sjdp emit_expr (&exp, (unsigned int) nbytes); 328133965Sjdp ++c; 328233965Sjdp } 328333965Sjdp while (*input_line_pointer++ == ','); 328433965Sjdp 328533965Sjdp /* In MRI mode, after an odd number of bytes, we must align to an 328633965Sjdp even word boundary, unless the next instruction is a dc.b, ds.b 328733965Sjdp or dcb.b. */ 328833965Sjdp if (flag_mri && nbytes == 1 && (c & 1) != 0) 328933965Sjdp mri_pending_align = 1; 329033965Sjdp 329177298Sobrien input_line_pointer--; /* Put terminator back into stream. */ 329233965Sjdp 329360484Sobrien demand_empty_rest_of_line (); 329460484Sobrien 329533965Sjdp if (flag_mri) 329633965Sjdp mri_comment_end (stop, stopc); 329733965Sjdp} 329833965Sjdp 329933965Sjdpvoid 3300130561Sobriencons (int size) 330133965Sjdp{ 330233965Sjdp cons_worker (size, 0); 330333965Sjdp} 330433965Sjdp 330577298Sobrienvoid 3306130561Sobriens_rva (int size) 330733965Sjdp{ 330833965Sjdp cons_worker (size, 1); 330933965Sjdp} 331033965Sjdp 331133965Sjdp/* Put the contents of expression EXP into the object file using 331233965Sjdp NBYTES bytes. If need_pass_2 is 1, this does nothing. */ 331333965Sjdp 331433965Sjdpvoid 3315130561Sobrienemit_expr (expressionS *exp, unsigned int nbytes) 331633965Sjdp{ 331733965Sjdp operatorT op; 331833965Sjdp register char *p; 331933965Sjdp valueT extra_digit = 0; 332033965Sjdp 332133965Sjdp /* Don't do anything if we are going to make another pass. */ 332233965Sjdp if (need_pass_2) 332333965Sjdp return; 332433965Sjdp 3325130561Sobrien dot_value = frag_now_fix (); 3326130561Sobrien 332738889Sjdp#ifndef NO_LISTING 332838889Sjdp#ifdef OBJ_ELF 332938889Sjdp /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will 333038889Sjdp appear as a four byte positive constant in the .line section, 333138889Sjdp followed by a 2 byte 0xffff. Look for that case here. */ 333238889Sjdp { 333338889Sjdp static int dwarf_line = -1; 333438889Sjdp 333538889Sjdp if (strcmp (segment_name (now_seg), ".line") != 0) 333638889Sjdp dwarf_line = -1; 333738889Sjdp else if (dwarf_line >= 0 333838889Sjdp && nbytes == 2 333938889Sjdp && exp->X_op == O_constant 334038889Sjdp && (exp->X_add_number == -1 || exp->X_add_number == 0xffff)) 334138889Sjdp listing_source_line ((unsigned int) dwarf_line); 334238889Sjdp else if (nbytes == 4 334338889Sjdp && exp->X_op == O_constant 334438889Sjdp && exp->X_add_number >= 0) 334538889Sjdp dwarf_line = exp->X_add_number; 334638889Sjdp else 334738889Sjdp dwarf_line = -1; 334838889Sjdp } 334938889Sjdp 335038889Sjdp /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will 335138889Sjdp appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte 335238889Sjdp AT_sibling (0x12) followed by a four byte address of the sibling 335338889Sjdp followed by a 2 byte AT_name (0x38) followed by the name of the 335438889Sjdp file. We look for that case here. */ 335538889Sjdp { 335638889Sjdp static int dwarf_file = 0; 335738889Sjdp 335838889Sjdp if (strcmp (segment_name (now_seg), ".debug") != 0) 335938889Sjdp dwarf_file = 0; 336038889Sjdp else if (dwarf_file == 0 336138889Sjdp && nbytes == 2 336238889Sjdp && exp->X_op == O_constant 336338889Sjdp && exp->X_add_number == 0x11) 336438889Sjdp dwarf_file = 1; 336538889Sjdp else if (dwarf_file == 1 336638889Sjdp && nbytes == 2 336738889Sjdp && exp->X_op == O_constant 336838889Sjdp && exp->X_add_number == 0x12) 336938889Sjdp dwarf_file = 2; 337038889Sjdp else if (dwarf_file == 2 337138889Sjdp && nbytes == 4) 337238889Sjdp dwarf_file = 3; 337338889Sjdp else if (dwarf_file == 3 337438889Sjdp && nbytes == 2 337538889Sjdp && exp->X_op == O_constant 337638889Sjdp && exp->X_add_number == 0x38) 337738889Sjdp dwarf_file = 4; 337838889Sjdp else 337938889Sjdp dwarf_file = 0; 338038889Sjdp 338138889Sjdp /* The variable dwarf_file_string tells stringer that the string 338238889Sjdp may be the name of the source file. */ 338338889Sjdp if (dwarf_file == 4) 338438889Sjdp dwarf_file_string = 1; 338538889Sjdp else 338638889Sjdp dwarf_file_string = 0; 338738889Sjdp } 338838889Sjdp#endif 338938889Sjdp#endif 339038889Sjdp 339138889Sjdp if (check_eh_frame (exp, &nbytes)) 339238889Sjdp return; 339338889Sjdp 339433965Sjdp op = exp->X_op; 339533965Sjdp 339633965Sjdp /* Allow `.word 0' in the absolute section. */ 339733965Sjdp if (now_seg == absolute_section) 339833965Sjdp { 339933965Sjdp if (op != O_constant || exp->X_add_number != 0) 340060484Sobrien as_bad (_("attempt to store value in absolute section")); 340133965Sjdp abs_section_offset += nbytes; 340233965Sjdp return; 340333965Sjdp } 340433965Sjdp 340533965Sjdp /* Handle a negative bignum. */ 340633965Sjdp if (op == O_uminus 340733965Sjdp && exp->X_add_number == 0 340860484Sobrien && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big 340960484Sobrien && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0) 341033965Sjdp { 341133965Sjdp int i; 341233965Sjdp unsigned long carry; 341333965Sjdp 341460484Sobrien exp = symbol_get_value_expression (exp->X_add_symbol); 341533965Sjdp 341633965Sjdp /* Negate the bignum: one's complement each digit and add 1. */ 341733965Sjdp carry = 1; 341833965Sjdp for (i = 0; i < exp->X_add_number; i++) 341933965Sjdp { 342033965Sjdp unsigned long next; 342133965Sjdp 342277298Sobrien next = (((~(generic_bignum[i] & LITTLENUM_MASK)) 342333965Sjdp & LITTLENUM_MASK) 342433965Sjdp + carry); 342533965Sjdp generic_bignum[i] = next & LITTLENUM_MASK; 342633965Sjdp carry = next >> LITTLENUM_NUMBER_OF_BITS; 342733965Sjdp } 342833965Sjdp 342933965Sjdp /* We can ignore any carry out, because it will be handled by 343033965Sjdp extra_digit if it is needed. */ 343133965Sjdp 343233965Sjdp extra_digit = (valueT) -1; 343333965Sjdp op = O_big; 343433965Sjdp } 343533965Sjdp 343633965Sjdp if (op == O_absent || op == O_illegal) 343733965Sjdp { 343860484Sobrien as_warn (_("zero assumed for missing expression")); 343933965Sjdp exp->X_add_number = 0; 344033965Sjdp op = O_constant; 344133965Sjdp } 344233965Sjdp else if (op == O_big && exp->X_add_number <= 0) 344333965Sjdp { 344489857Sobrien as_bad (_("floating point number invalid")); 344533965Sjdp exp->X_add_number = 0; 344633965Sjdp op = O_constant; 344733965Sjdp } 344833965Sjdp else if (op == O_register) 344933965Sjdp { 345060484Sobrien as_warn (_("register value used as expression")); 345133965Sjdp op = O_constant; 345233965Sjdp } 345333965Sjdp 345433965Sjdp p = frag_more ((int) nbytes); 345533965Sjdp 345633965Sjdp#ifndef WORKING_DOT_WORD 345733965Sjdp /* If we have the difference of two symbols in a word, save it on 345833965Sjdp the broken_words list. See the code in write.c. */ 345933965Sjdp if (op == O_subtract && nbytes == 2) 346033965Sjdp { 346133965Sjdp struct broken_word *x; 346233965Sjdp 346333965Sjdp x = (struct broken_word *) xmalloc (sizeof (struct broken_word)); 346433965Sjdp x->next_broken_word = broken_words; 346533965Sjdp broken_words = x; 346660484Sobrien x->seg = now_seg; 346760484Sobrien x->subseg = now_subseg; 346833965Sjdp x->frag = frag_now; 346933965Sjdp x->word_goes_here = p; 347033965Sjdp x->dispfrag = 0; 347133965Sjdp x->add = exp->X_add_symbol; 347233965Sjdp x->sub = exp->X_op_symbol; 347333965Sjdp x->addnum = exp->X_add_number; 347433965Sjdp x->added = 0; 3475130561Sobrien x->use_jump = 0; 347633965Sjdp new_broken_words++; 347733965Sjdp return; 347833965Sjdp } 347933965Sjdp#endif 348033965Sjdp 348133965Sjdp /* If we have an integer, but the number of bytes is too large to 348233965Sjdp pass to md_number_to_chars, handle it as a bignum. */ 348333965Sjdp if (op == O_constant && nbytes > sizeof (valueT)) 348433965Sjdp { 348533965Sjdp valueT val; 348633965Sjdp int gencnt; 348733965Sjdp 348877298Sobrien if (!exp->X_unsigned && exp->X_add_number < 0) 348933965Sjdp extra_digit = (valueT) -1; 349033965Sjdp val = (valueT) exp->X_add_number; 349133965Sjdp gencnt = 0; 349233965Sjdp do 349333965Sjdp { 349433965Sjdp generic_bignum[gencnt] = val & LITTLENUM_MASK; 349533965Sjdp val >>= LITTLENUM_NUMBER_OF_BITS; 349633965Sjdp ++gencnt; 349733965Sjdp } 349833965Sjdp while (val != 0); 349933965Sjdp op = exp->X_op = O_big; 350033965Sjdp exp->X_add_number = gencnt; 350133965Sjdp } 350233965Sjdp 350333965Sjdp if (op == O_constant) 350433965Sjdp { 350533965Sjdp register valueT get; 350633965Sjdp register valueT use; 350733965Sjdp register valueT mask; 350833965Sjdp valueT hibit; 350933965Sjdp register valueT unmask; 351033965Sjdp 351133965Sjdp /* JF << of >= number of bits in the object is undefined. In 351277298Sobrien particular SPARC (Sun 4) has problems. */ 351333965Sjdp if (nbytes >= sizeof (valueT)) 351433965Sjdp { 351533965Sjdp mask = 0; 351633965Sjdp if (nbytes > sizeof (valueT)) 351733965Sjdp hibit = 0; 351833965Sjdp else 351933965Sjdp hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); 352033965Sjdp } 352133965Sjdp else 352233965Sjdp { 352377298Sobrien /* Don't store these bits. */ 352433965Sjdp mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); 352533965Sjdp hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); 352633965Sjdp } 352733965Sjdp 352877298Sobrien unmask = ~mask; /* Do store these bits. */ 352933965Sjdp 353033965Sjdp#ifdef NEVER 353133965Sjdp "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; 353277298Sobrien mask = ~(unmask >> 1); /* Includes sign bit now. */ 353333965Sjdp#endif 353433965Sjdp 353533965Sjdp get = exp->X_add_number; 353633965Sjdp use = get & unmask; 353733965Sjdp if ((get & mask) != 0 353833965Sjdp && ((get & mask) != mask 353933965Sjdp || (get & hibit) == 0)) 354077298Sobrien { /* Leading bits contain both 0s & 1s. */ 354189857Sobrien as_warn (_("value 0x%lx truncated to 0x%lx"), 354233965Sjdp (unsigned long) get, (unsigned long) use); 354333965Sjdp } 354477298Sobrien /* Put bytes in right order. */ 354533965Sjdp md_number_to_chars (p, use, (int) nbytes); 354633965Sjdp } 354733965Sjdp else if (op == O_big) 354833965Sjdp { 354938889Sjdp unsigned int size; 355033965Sjdp LITTLENUM_TYPE *nums; 355133965Sjdp 355233965Sjdp know (nbytes % CHARS_PER_LITTLENUM == 0); 355333965Sjdp 355433965Sjdp size = exp->X_add_number * CHARS_PER_LITTLENUM; 355533965Sjdp if (nbytes < size) 355633965Sjdp { 355789857Sobrien as_warn (_("bignum truncated to %d bytes"), nbytes); 355833965Sjdp size = nbytes; 355933965Sjdp } 356033965Sjdp 356133965Sjdp if (target_big_endian) 356233965Sjdp { 356333965Sjdp while (nbytes > size) 356433965Sjdp { 356533965Sjdp md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); 356633965Sjdp nbytes -= CHARS_PER_LITTLENUM; 356733965Sjdp p += CHARS_PER_LITTLENUM; 356833965Sjdp } 356933965Sjdp 357033965Sjdp nums = generic_bignum + size / CHARS_PER_LITTLENUM; 357189857Sobrien while (size >= CHARS_PER_LITTLENUM) 357233965Sjdp { 357333965Sjdp --nums; 357433965Sjdp md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); 357533965Sjdp size -= CHARS_PER_LITTLENUM; 357633965Sjdp p += CHARS_PER_LITTLENUM; 357733965Sjdp } 357833965Sjdp } 357933965Sjdp else 358033965Sjdp { 358133965Sjdp nums = generic_bignum; 358289857Sobrien while (size >= CHARS_PER_LITTLENUM) 358333965Sjdp { 358433965Sjdp md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); 358533965Sjdp ++nums; 358633965Sjdp size -= CHARS_PER_LITTLENUM; 358733965Sjdp p += CHARS_PER_LITTLENUM; 358833965Sjdp nbytes -= CHARS_PER_LITTLENUM; 358933965Sjdp } 359033965Sjdp 359189857Sobrien while (nbytes >= CHARS_PER_LITTLENUM) 359233965Sjdp { 359333965Sjdp md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); 359433965Sjdp nbytes -= CHARS_PER_LITTLENUM; 359533965Sjdp p += CHARS_PER_LITTLENUM; 359633965Sjdp } 359733965Sjdp } 359833965Sjdp } 359933965Sjdp else 360033965Sjdp { 360133965Sjdp memset (p, 0, nbytes); 360233965Sjdp 360333965Sjdp /* Now we need to generate a fixS to record the symbol value. 360433965Sjdp This is easy for BFD. For other targets it can be more 360533965Sjdp complex. For very complex cases (currently, the HPPA and 360633965Sjdp NS32K), you can define TC_CONS_FIX_NEW to do whatever you 360733965Sjdp want. For simpler cases, you can define TC_CONS_RELOC to be 360833965Sjdp the name of the reloc code that should be stored in the fixS. 360933965Sjdp If neither is defined, the code uses NO_RELOC if it is 361033965Sjdp defined, and otherwise uses 0. */ 361133965Sjdp 361233965Sjdp#ifdef BFD_ASSEMBLER 361333965Sjdp#ifdef TC_CONS_FIX_NEW 361433965Sjdp TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp); 361533965Sjdp#else 361633965Sjdp { 361733965Sjdp bfd_reloc_code_real_type r; 361833965Sjdp 361933965Sjdp switch (nbytes) 362033965Sjdp { 362133965Sjdp case 1: 362233965Sjdp r = BFD_RELOC_8; 362333965Sjdp break; 362433965Sjdp case 2: 362533965Sjdp r = BFD_RELOC_16; 362633965Sjdp break; 362733965Sjdp case 4: 362833965Sjdp r = BFD_RELOC_32; 362933965Sjdp break; 363033965Sjdp case 8: 363133965Sjdp r = BFD_RELOC_64; 363233965Sjdp break; 363333965Sjdp default: 363460484Sobrien as_bad (_("unsupported BFD relocation size %u"), nbytes); 363533965Sjdp r = BFD_RELOC_32; 363633965Sjdp break; 363733965Sjdp } 363833965Sjdp fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 363933965Sjdp 0, r); 364033965Sjdp } 364133965Sjdp#endif 364233965Sjdp#else 364333965Sjdp#ifdef TC_CONS_FIX_NEW 364433965Sjdp TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp); 364533965Sjdp#else 364633965Sjdp /* Figure out which reloc number to use. Use TC_CONS_RELOC if 364733965Sjdp it is defined, otherwise use NO_RELOC if it is defined, 364833965Sjdp otherwise use 0. */ 364933965Sjdp#ifndef TC_CONS_RELOC 365033965Sjdp#ifdef NO_RELOC 365133965Sjdp#define TC_CONS_RELOC NO_RELOC 365233965Sjdp#else 365333965Sjdp#define TC_CONS_RELOC 0 365433965Sjdp#endif 365533965Sjdp#endif 365633965Sjdp fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0, 365733965Sjdp TC_CONS_RELOC); 365833965Sjdp#endif /* TC_CONS_FIX_NEW */ 365933965Sjdp#endif /* BFD_ASSEMBLER */ 366033965Sjdp } 366133965Sjdp} 366233965Sjdp 366333965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS 366433965Sjdp 366533965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as 366633965Sjdp w:x,y:z, where w and y are bitwidths and x and y are values. They 366733965Sjdp then pack them all together. We do a little better in that we allow 366833965Sjdp them in words, longs, etc. and we'll pack them in target byte order 366933965Sjdp for you. 367033965Sjdp 3671130561Sobrien The rules are: pack least significant bit first, if a field doesn't 367233965Sjdp entirely fit, put it in the next unit. Overflowing the bitfield is 367333965Sjdp explicitly *not* even a warning. The bitwidth should be considered 367433965Sjdp a "mask". 367533965Sjdp 367633965Sjdp To use this function the tc-XXX.h file should define 367733965Sjdp BITFIELD_CONS_EXPRESSIONS. */ 367833965Sjdp 367977298Sobrienstatic void 368033965Sjdpparse_bitfield_cons (exp, nbytes) 368133965Sjdp expressionS *exp; 368233965Sjdp unsigned int nbytes; 368333965Sjdp{ 368433965Sjdp unsigned int bits_available = BITS_PER_CHAR * nbytes; 368533965Sjdp char *hold = input_line_pointer; 368633965Sjdp 368733965Sjdp (void) expression (exp); 368833965Sjdp 368933965Sjdp if (*input_line_pointer == ':') 369077298Sobrien { 369177298Sobrien /* Bitfields. */ 369233965Sjdp long value = 0; 369333965Sjdp 369433965Sjdp for (;;) 369533965Sjdp { 369633965Sjdp unsigned long width; 369733965Sjdp 369833965Sjdp if (*input_line_pointer != ':') 369933965Sjdp { 370033965Sjdp input_line_pointer = hold; 370133965Sjdp break; 370277298Sobrien } /* Next piece is not a bitfield. */ 370333965Sjdp 370433965Sjdp /* In the general case, we can't allow 370533965Sjdp full expressions with symbol 370633965Sjdp differences and such. The relocation 370733965Sjdp entries for symbols not defined in this 370833965Sjdp assembly would require arbitrary field 370933965Sjdp widths, positions, and masks which most 371033965Sjdp of our current object formats don't 371133965Sjdp support. 371233965Sjdp 371333965Sjdp In the specific case where a symbol 371433965Sjdp *is* defined in this assembly, we 371533965Sjdp *could* build fixups and track it, but 371633965Sjdp this could lead to confusion for the 371733965Sjdp backends. I'm lazy. I'll take any 371833965Sjdp SEG_ABSOLUTE. I think that means that 371933965Sjdp you can use a previous .set or 372077298Sobrien .equ type symbol. xoxorich. */ 372133965Sjdp 372233965Sjdp if (exp->X_op == O_absent) 372333965Sjdp { 372460484Sobrien as_warn (_("using a bit field width of zero")); 372533965Sjdp exp->X_add_number = 0; 372633965Sjdp exp->X_op = O_constant; 372777298Sobrien } /* Implied zero width bitfield. */ 372833965Sjdp 372933965Sjdp if (exp->X_op != O_constant) 373033965Sjdp { 373133965Sjdp *input_line_pointer = '\0'; 373260484Sobrien as_bad (_("field width \"%s\" too complex for a bitfield"), hold); 373333965Sjdp *input_line_pointer = ':'; 373433965Sjdp demand_empty_rest_of_line (); 373533965Sjdp return; 373677298Sobrien } /* Too complex. */ 373733965Sjdp 373833965Sjdp if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes)) 373933965Sjdp { 374060484Sobrien as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), 374133965Sjdp width, nbytes, (BITS_PER_CHAR * nbytes)); 374233965Sjdp width = BITS_PER_CHAR * nbytes; 374377298Sobrien } /* Too big. */ 374433965Sjdp 374533965Sjdp if (width > bits_available) 374633965Sjdp { 374733965Sjdp /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */ 374833965Sjdp input_line_pointer = hold; 374933965Sjdp exp->X_add_number = value; 375033965Sjdp break; 375177298Sobrien } /* Won't fit. */ 375233965Sjdp 375377298Sobrien /* Skip ':'. */ 375477298Sobrien hold = ++input_line_pointer; 375533965Sjdp 375633965Sjdp (void) expression (exp); 375733965Sjdp if (exp->X_op != O_constant) 375833965Sjdp { 375933965Sjdp char cache = *input_line_pointer; 376033965Sjdp 376133965Sjdp *input_line_pointer = '\0'; 376260484Sobrien as_bad (_("field value \"%s\" too complex for a bitfield"), hold); 376333965Sjdp *input_line_pointer = cache; 376433965Sjdp demand_empty_rest_of_line (); 376533965Sjdp return; 376677298Sobrien } /* Too complex. */ 376733965Sjdp 376833965Sjdp value |= ((~(-1 << width) & exp->X_add_number) 376933965Sjdp << ((BITS_PER_CHAR * nbytes) - bits_available)); 377033965Sjdp 377133965Sjdp if ((bits_available -= width) == 0 377233965Sjdp || is_it_end_of_statement () 377333965Sjdp || *input_line_pointer != ',') 377433965Sjdp { 377533965Sjdp break; 377677298Sobrien } /* All the bitfields we're gonna get. */ 377733965Sjdp 377833965Sjdp hold = ++input_line_pointer; 377933965Sjdp (void) expression (exp); 378077298Sobrien } 378133965Sjdp 378233965Sjdp exp->X_add_number = value; 378333965Sjdp exp->X_op = O_constant; 378433965Sjdp exp->X_unsigned = 1; 378577298Sobrien } 378677298Sobrien} 378733965Sjdp 378833965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */ 378933965Sjdp 379033965Sjdp/* Handle an MRI style string expression. */ 379133965Sjdp 379260484Sobrien#ifdef TC_M68K 379333965Sjdpstatic void 379433965Sjdpparse_mri_cons (exp, nbytes) 379533965Sjdp expressionS *exp; 379633965Sjdp unsigned int nbytes; 379733965Sjdp{ 379833965Sjdp if (*input_line_pointer != '\'' 379933965Sjdp && (input_line_pointer[1] != '\'' 380033965Sjdp || (*input_line_pointer != 'A' 380133965Sjdp && *input_line_pointer != 'E'))) 380233965Sjdp TC_PARSE_CONS_EXPRESSION (exp, nbytes); 380333965Sjdp else 380433965Sjdp { 380538889Sjdp unsigned int scan; 380633965Sjdp unsigned int result = 0; 380733965Sjdp 380833965Sjdp /* An MRI style string. Cut into as many bytes as will fit into 380933965Sjdp a nbyte chunk, left justify if necessary, and separate with 381033965Sjdp commas so we can try again later. */ 381133965Sjdp if (*input_line_pointer == 'A') 381233965Sjdp ++input_line_pointer; 381333965Sjdp else if (*input_line_pointer == 'E') 381433965Sjdp { 381560484Sobrien as_bad (_("EBCDIC constants are not supported")); 381633965Sjdp ++input_line_pointer; 381733965Sjdp } 381833965Sjdp 381933965Sjdp input_line_pointer++; 382033965Sjdp for (scan = 0; scan < nbytes; scan++) 382133965Sjdp { 382233965Sjdp if (*input_line_pointer == '\'') 382333965Sjdp { 382433965Sjdp if (input_line_pointer[1] == '\'') 382533965Sjdp { 382633965Sjdp input_line_pointer++; 382733965Sjdp } 382833965Sjdp else 382933965Sjdp break; 383033965Sjdp } 383133965Sjdp result = (result << 8) | (*input_line_pointer++); 383233965Sjdp } 383333965Sjdp 383477298Sobrien /* Left justify. */ 383533965Sjdp while (scan < nbytes) 383633965Sjdp { 383733965Sjdp result <<= 8; 383833965Sjdp scan++; 383933965Sjdp } 384077298Sobrien 384177298Sobrien /* Create correct expression. */ 384233965Sjdp exp->X_op = O_constant; 384333965Sjdp exp->X_add_number = result; 384477298Sobrien 384577298Sobrien /* Fake it so that we can read the next char too. */ 384633965Sjdp if (input_line_pointer[0] != '\'' || 384733965Sjdp (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\'')) 384833965Sjdp { 384933965Sjdp input_line_pointer -= 2; 385033965Sjdp input_line_pointer[0] = ','; 385133965Sjdp input_line_pointer[1] = '\''; 385233965Sjdp } 385333965Sjdp else 385433965Sjdp input_line_pointer++; 385533965Sjdp } 385633965Sjdp} 385760484Sobrien#endif /* TC_M68K */ 385833965Sjdp 385933965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 386033965Sjdp 386133965Sjdp/* Parse a repeat expression for cons. This is used by the MIPS 386233965Sjdp assembler. The format is NUMBER:COUNT; NUMBER appears in the 386333965Sjdp object file COUNT times. 386433965Sjdp 386533965Sjdp To use this for a target, define REPEAT_CONS_EXPRESSIONS. */ 386633965Sjdp 386733965Sjdpstatic void 386833965Sjdpparse_repeat_cons (exp, nbytes) 386933965Sjdp expressionS *exp; 387033965Sjdp unsigned int nbytes; 387133965Sjdp{ 387233965Sjdp expressionS count; 387333965Sjdp register int i; 387433965Sjdp 387533965Sjdp expression (exp); 387633965Sjdp 387733965Sjdp if (*input_line_pointer != ':') 387833965Sjdp { 387933965Sjdp /* No repeat count. */ 388033965Sjdp return; 388133965Sjdp } 388233965Sjdp 388333965Sjdp ++input_line_pointer; 388433965Sjdp expression (&count); 388533965Sjdp if (count.X_op != O_constant 388633965Sjdp || count.X_add_number <= 0) 388733965Sjdp { 388889857Sobrien as_warn (_("unresolvable or nonpositive repeat count; using 1")); 388933965Sjdp return; 389033965Sjdp } 389133965Sjdp 389233965Sjdp /* The cons function is going to output this expression once. So we 389333965Sjdp output it count - 1 times. */ 389433965Sjdp for (i = count.X_add_number - 1; i > 0; i--) 389533965Sjdp emit_expr (exp, nbytes); 389633965Sjdp} 389733965Sjdp 389833965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */ 389933965Sjdp 390033965Sjdp/* Parse a floating point number represented as a hex constant. This 390133965Sjdp permits users to specify the exact bits they want in the floating 390233965Sjdp point number. */ 390333965Sjdp 390433965Sjdpstatic int 3905130561Sobrienhex_float (int float_type, char *bytes) 390633965Sjdp{ 390733965Sjdp int length; 390833965Sjdp int i; 390933965Sjdp 391033965Sjdp switch (float_type) 391133965Sjdp { 391233965Sjdp case 'f': 391333965Sjdp case 'F': 391433965Sjdp case 's': 391533965Sjdp case 'S': 391633965Sjdp length = 4; 391733965Sjdp break; 391833965Sjdp 391933965Sjdp case 'd': 392033965Sjdp case 'D': 392133965Sjdp case 'r': 392233965Sjdp case 'R': 392333965Sjdp length = 8; 392433965Sjdp break; 392533965Sjdp 392633965Sjdp case 'x': 392733965Sjdp case 'X': 392833965Sjdp length = 12; 392933965Sjdp break; 393033965Sjdp 393133965Sjdp case 'p': 393233965Sjdp case 'P': 393333965Sjdp length = 12; 393433965Sjdp break; 393533965Sjdp 393633965Sjdp default: 393789857Sobrien as_bad (_("unknown floating type type '%c'"), float_type); 393833965Sjdp return -1; 393933965Sjdp } 394033965Sjdp 394133965Sjdp /* It would be nice if we could go through expression to parse the 394233965Sjdp hex constant, but if we get a bignum it's a pain to sort it into 394333965Sjdp the buffer correctly. */ 394433965Sjdp i = 0; 394533965Sjdp while (hex_p (*input_line_pointer) || *input_line_pointer == '_') 394633965Sjdp { 394733965Sjdp int d; 394833965Sjdp 394933965Sjdp /* The MRI assembler accepts arbitrary underscores strewn about 395077298Sobrien through the hex constant, so we ignore them as well. */ 395133965Sjdp if (*input_line_pointer == '_') 395233965Sjdp { 395333965Sjdp ++input_line_pointer; 395433965Sjdp continue; 395533965Sjdp } 395633965Sjdp 395733965Sjdp if (i >= length) 395833965Sjdp { 395989857Sobrien as_warn (_("floating point constant too large")); 396033965Sjdp return -1; 396133965Sjdp } 396233965Sjdp d = hex_value (*input_line_pointer) << 4; 396333965Sjdp ++input_line_pointer; 396433965Sjdp while (*input_line_pointer == '_') 396533965Sjdp ++input_line_pointer; 396633965Sjdp if (hex_p (*input_line_pointer)) 396733965Sjdp { 396833965Sjdp d += hex_value (*input_line_pointer); 396933965Sjdp ++input_line_pointer; 397033965Sjdp } 397133965Sjdp if (target_big_endian) 397233965Sjdp bytes[i] = d; 397333965Sjdp else 397433965Sjdp bytes[length - i - 1] = d; 397533965Sjdp ++i; 397633965Sjdp } 397733965Sjdp 397833965Sjdp if (i < length) 397933965Sjdp { 398033965Sjdp if (target_big_endian) 398133965Sjdp memset (bytes + i, 0, length - i); 398233965Sjdp else 398333965Sjdp memset (bytes, 0, length - i); 398433965Sjdp } 398533965Sjdp 398633965Sjdp return length; 398733965Sjdp} 398833965Sjdp 3989130561Sobrien/* float_cons() 399033965Sjdp 399177298Sobrien CONStruct some more frag chars of .floats .ffloats etc. 399277298Sobrien Makes 0 or more new frags. 399377298Sobrien If need_pass_2 == 1, no frags are emitted. 399477298Sobrien This understands only floating literals, not expressions. Sorry. 399577298Sobrien 399677298Sobrien A floating constant is defined by atof_generic(), except it is preceded 399777298Sobrien by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its 399877298Sobrien reading, I decided to be incompatible. This always tries to give you 399977298Sobrien rounded bits to the precision of the pseudo-op. Former AS did premature 4000130561Sobrien truncation, restored noisy bits instead of trailing 0s AND gave you 400177298Sobrien a choice of 2 flavours of noise according to which of 2 floating-point 400277298Sobrien scanners you directed AS to use. 400377298Sobrien 400477298Sobrien In: input_line_pointer->whitespace before, or '0' of flonum. */ 400577298Sobrien 400633965Sjdpvoid 4007130561Sobrienfloat_cons (/* Clobbers input_line-pointer, checks end-of-line. */ 4008130561Sobrien register int float_type /* 'f':.ffloat ... 'F':.float ... */) 400933965Sjdp{ 401033965Sjdp register char *p; 401177298Sobrien int length; /* Number of chars in an object. */ 401277298Sobrien register char *err; /* Error from scanning floating literal. */ 401333965Sjdp char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 401433965Sjdp 401533965Sjdp if (is_it_end_of_statement ()) 401633965Sjdp { 401733965Sjdp demand_empty_rest_of_line (); 401833965Sjdp return; 401933965Sjdp } 402033965Sjdp 402133965Sjdp#ifdef md_flush_pending_output 402233965Sjdp md_flush_pending_output (); 402333965Sjdp#endif 402433965Sjdp 402533965Sjdp do 402633965Sjdp { 402777298Sobrien /* input_line_pointer->1st char of a flonum (we hope!). */ 402833965Sjdp SKIP_WHITESPACE (); 402933965Sjdp 403033965Sjdp /* Skip any 0{letter} that may be present. Don't even check if the 4031130561Sobrien letter is legal. Someone may invent a "z" format and this routine 4032130561Sobrien has no use for such information. Lusers beware: you get 4033130561Sobrien diagnostics if your input is ill-conditioned. */ 403438889Sjdp if (input_line_pointer[0] == '0' 403589857Sobrien && ISALPHA (input_line_pointer[1])) 403633965Sjdp input_line_pointer += 2; 403733965Sjdp 403833965Sjdp /* Accept :xxxx, where the x's are hex digits, for a floating 4039130561Sobrien point with the exact digits specified. */ 404033965Sjdp if (input_line_pointer[0] == ':') 404133965Sjdp { 404233965Sjdp ++input_line_pointer; 404333965Sjdp length = hex_float (float_type, temp); 404433965Sjdp if (length < 0) 404533965Sjdp { 404633965Sjdp ignore_rest_of_line (); 404733965Sjdp return; 404833965Sjdp } 404933965Sjdp } 405033965Sjdp else 405133965Sjdp { 405233965Sjdp err = md_atof (float_type, temp, &length); 405333965Sjdp know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 405433965Sjdp know (length > 0); 405533965Sjdp if (err) 405633965Sjdp { 405789857Sobrien as_bad (_("bad floating literal: %s"), err); 405833965Sjdp ignore_rest_of_line (); 405933965Sjdp return; 406033965Sjdp } 406133965Sjdp } 406233965Sjdp 406333965Sjdp if (!need_pass_2) 406433965Sjdp { 406533965Sjdp int count; 406633965Sjdp 406733965Sjdp count = 1; 406833965Sjdp 406933965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 407033965Sjdp if (*input_line_pointer == ':') 407133965Sjdp { 407233965Sjdp expressionS count_exp; 407333965Sjdp 407433965Sjdp ++input_line_pointer; 407533965Sjdp expression (&count_exp); 407677298Sobrien 407733965Sjdp if (count_exp.X_op != O_constant 407833965Sjdp || count_exp.X_add_number <= 0) 407977298Sobrien as_warn (_("unresolvable or nonpositive repeat count; using 1")); 408033965Sjdp else 408133965Sjdp count = count_exp.X_add_number; 408233965Sjdp } 408333965Sjdp#endif 408433965Sjdp 408533965Sjdp while (--count >= 0) 408633965Sjdp { 408733965Sjdp p = frag_more (length); 408833965Sjdp memcpy (p, temp, (unsigned int) length); 408933965Sjdp } 409033965Sjdp } 409133965Sjdp SKIP_WHITESPACE (); 409233965Sjdp } 409333965Sjdp while (*input_line_pointer++ == ','); 409433965Sjdp 409577298Sobrien /* Put terminator back into stream. */ 409677298Sobrien --input_line_pointer; 409733965Sjdp demand_empty_rest_of_line (); 409877298Sobrien} 409933965Sjdp 410077298Sobrien/* Return the size of a LEB128 value. */ 410138889Sjdp 410238889Sjdpstatic inline int 4103130561Sobriensizeof_sleb128 (offsetT value) 410438889Sjdp{ 410538889Sjdp register int size = 0; 410638889Sjdp register unsigned byte; 410738889Sjdp 410838889Sjdp do 410938889Sjdp { 411038889Sjdp byte = (value & 0x7f); 411138889Sjdp /* Sadly, we cannot rely on typical arithmetic right shift behaviour. 411238889Sjdp Fortunately, we can structure things so that the extra work reduces 411338889Sjdp to a noop on systems that do things "properly". */ 411438889Sjdp value = (value >> 7) | ~(-(offsetT)1 >> 7); 411538889Sjdp size += 1; 411638889Sjdp } 411738889Sjdp while (!(((value == 0) && ((byte & 0x40) == 0)) 411838889Sjdp || ((value == -1) && ((byte & 0x40) != 0)))); 411938889Sjdp 412038889Sjdp return size; 412138889Sjdp} 412238889Sjdp 412338889Sjdpstatic inline int 4124130561Sobriensizeof_uleb128 (valueT value) 412538889Sjdp{ 412638889Sjdp register int size = 0; 412738889Sjdp register unsigned byte; 412838889Sjdp 412938889Sjdp do 413038889Sjdp { 413138889Sjdp byte = (value & 0x7f); 413238889Sjdp value >>= 7; 413338889Sjdp size += 1; 413438889Sjdp } 413538889Sjdp while (value != 0); 413638889Sjdp 413738889Sjdp return size; 413838889Sjdp} 413938889Sjdp 414060484Sobrienint 4141130561Sobriensizeof_leb128 (valueT value, int sign) 414238889Sjdp{ 414338889Sjdp if (sign) 414438889Sjdp return sizeof_sleb128 ((offsetT) value); 414538889Sjdp else 414638889Sjdp return sizeof_uleb128 (value); 414738889Sjdp} 414838889Sjdp 414938889Sjdp/* Output a LEB128 value. */ 415038889Sjdp 415138889Sjdpstatic inline int 4152130561Sobrienoutput_sleb128 (char *p, offsetT value) 415338889Sjdp{ 415438889Sjdp register char *orig = p; 415538889Sjdp register int more; 415638889Sjdp 415738889Sjdp do 415838889Sjdp { 415938889Sjdp unsigned byte = (value & 0x7f); 416038889Sjdp 416138889Sjdp /* Sadly, we cannot rely on typical arithmetic right shift behaviour. 416238889Sjdp Fortunately, we can structure things so that the extra work reduces 416338889Sjdp to a noop on systems that do things "properly". */ 416438889Sjdp value = (value >> 7) | ~(-(offsetT)1 >> 7); 416538889Sjdp 416638889Sjdp more = !((((value == 0) && ((byte & 0x40) == 0)) 416738889Sjdp || ((value == -1) && ((byte & 0x40) != 0)))); 416838889Sjdp if (more) 416938889Sjdp byte |= 0x80; 417038889Sjdp 417138889Sjdp *p++ = byte; 417238889Sjdp } 417338889Sjdp while (more); 417438889Sjdp 417538889Sjdp return p - orig; 417638889Sjdp} 417738889Sjdp 417838889Sjdpstatic inline int 4179130561Sobrienoutput_uleb128 (char *p, valueT value) 418038889Sjdp{ 418138889Sjdp char *orig = p; 418238889Sjdp 418338889Sjdp do 418438889Sjdp { 418538889Sjdp unsigned byte = (value & 0x7f); 418638889Sjdp value >>= 7; 418738889Sjdp if (value != 0) 418838889Sjdp /* More bytes to follow. */ 418938889Sjdp byte |= 0x80; 419038889Sjdp 419138889Sjdp *p++ = byte; 419238889Sjdp } 419338889Sjdp while (value != 0); 419438889Sjdp 419538889Sjdp return p - orig; 419638889Sjdp} 419738889Sjdp 419860484Sobrienint 4199130561Sobrienoutput_leb128 (char *p, valueT value, int sign) 420038889Sjdp{ 420138889Sjdp if (sign) 420238889Sjdp return output_sleb128 (p, (offsetT) value); 420338889Sjdp else 420438889Sjdp return output_uleb128 (p, value); 420538889Sjdp} 420638889Sjdp 420738889Sjdp/* Do the same for bignums. We combine sizeof with output here in that 420838889Sjdp we don't output for NULL values of P. It isn't really as critical as 420938889Sjdp for "normal" values that this be streamlined. */ 421038889Sjdp 421160484Sobrienstatic inline int 4212130561Sobrienoutput_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size) 421338889Sjdp{ 421438889Sjdp char *orig = p; 421538889Sjdp valueT val = 0; 421638889Sjdp int loaded = 0; 421738889Sjdp unsigned byte; 421838889Sjdp 421938889Sjdp /* Strip leading sign extensions off the bignum. */ 422077298Sobrien while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1) 422138889Sjdp size--; 422238889Sjdp 422338889Sjdp do 422438889Sjdp { 422538889Sjdp if (loaded < 7 && size > 0) 422638889Sjdp { 422738889Sjdp val |= (*bignum << loaded); 422838889Sjdp loaded += 8 * CHARS_PER_LITTLENUM; 422938889Sjdp size--; 423038889Sjdp bignum++; 423138889Sjdp } 423238889Sjdp 423338889Sjdp byte = val & 0x7f; 423438889Sjdp loaded -= 7; 423538889Sjdp val >>= 7; 423638889Sjdp 423738889Sjdp if (size == 0) 423838889Sjdp { 423938889Sjdp if ((val == 0 && (byte & 0x40) == 0) 424077298Sobrien || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0 424138889Sjdp && (byte & 0x40) != 0)) 424238889Sjdp byte |= 0x80; 424338889Sjdp } 424438889Sjdp 424538889Sjdp if (orig) 424638889Sjdp *p = byte; 424738889Sjdp p++; 424838889Sjdp } 424938889Sjdp while (byte & 0x80); 425038889Sjdp 425138889Sjdp return p - orig; 425238889Sjdp} 425338889Sjdp 425460484Sobrienstatic inline int 4255130561Sobrienoutput_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size) 425638889Sjdp{ 425738889Sjdp char *orig = p; 425838889Sjdp valueT val = 0; 425938889Sjdp int loaded = 0; 426038889Sjdp unsigned byte; 426138889Sjdp 426238889Sjdp /* Strip leading zeros off the bignum. */ 426338889Sjdp /* XXX: Is this needed? */ 426477298Sobrien while (size > 0 && bignum[size - 1] == 0) 426538889Sjdp size--; 426638889Sjdp 426738889Sjdp do 426838889Sjdp { 426938889Sjdp if (loaded < 7 && size > 0) 427038889Sjdp { 427138889Sjdp val |= (*bignum << loaded); 427238889Sjdp loaded += 8 * CHARS_PER_LITTLENUM; 427338889Sjdp size--; 427438889Sjdp bignum++; 427538889Sjdp } 427638889Sjdp 427738889Sjdp byte = val & 0x7f; 427838889Sjdp loaded -= 7; 427938889Sjdp val >>= 7; 428038889Sjdp 428138889Sjdp if (size > 0 || val) 428238889Sjdp byte |= 0x80; 428338889Sjdp 428438889Sjdp if (orig) 428538889Sjdp *p = byte; 428638889Sjdp p++; 428738889Sjdp } 428838889Sjdp while (byte & 0x80); 428938889Sjdp 429038889Sjdp return p - orig; 429138889Sjdp} 429238889Sjdp 429360484Sobrienstatic int 4294130561Sobrienoutput_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign) 429538889Sjdp{ 429638889Sjdp if (sign) 429738889Sjdp return output_big_sleb128 (p, bignum, size); 429838889Sjdp else 429938889Sjdp return output_big_uleb128 (p, bignum, size); 430038889Sjdp} 430138889Sjdp 430238889Sjdp/* Generate the appropriate fragments for a given expression to emit a 430338889Sjdp leb128 value. */ 430438889Sjdp 430538889Sjdpvoid 4306130561Sobrienemit_leb128_expr (expressionS *exp, int sign) 430738889Sjdp{ 430838889Sjdp operatorT op = exp->X_op; 430978828Sobrien int nbytes; 431038889Sjdp 431138889Sjdp if (op == O_absent || op == O_illegal) 431238889Sjdp { 431360484Sobrien as_warn (_("zero assumed for missing expression")); 431438889Sjdp exp->X_add_number = 0; 431538889Sjdp op = O_constant; 431638889Sjdp } 431738889Sjdp else if (op == O_big && exp->X_add_number <= 0) 431838889Sjdp { 431989857Sobrien as_bad (_("floating point number invalid")); 432038889Sjdp exp->X_add_number = 0; 432138889Sjdp op = O_constant; 432238889Sjdp } 432338889Sjdp else if (op == O_register) 432438889Sjdp { 432560484Sobrien as_warn (_("register value used as expression")); 432638889Sjdp op = O_constant; 432738889Sjdp } 432838889Sjdp 432978828Sobrien /* Let check_eh_frame know that data is being emitted. nbytes == -1 is 433078828Sobrien a signal that this is leb128 data. It shouldn't optimize this away. */ 433178828Sobrien nbytes = -1; 433278828Sobrien if (check_eh_frame (exp, &nbytes)) 433378828Sobrien abort (); 433478828Sobrien 433578828Sobrien /* Let the backend know that subsequent data may be byte aligned. */ 433678828Sobrien#ifdef md_cons_align 433778828Sobrien md_cons_align (1); 433878828Sobrien#endif 433978828Sobrien 434038889Sjdp if (op == O_constant) 434138889Sjdp { 434238889Sjdp /* If we've got a constant, emit the thing directly right now. */ 434338889Sjdp 434438889Sjdp valueT value = exp->X_add_number; 434538889Sjdp int size; 434638889Sjdp char *p; 434738889Sjdp 434838889Sjdp size = sizeof_leb128 (value, sign); 434938889Sjdp p = frag_more (size); 435038889Sjdp output_leb128 (p, value, sign); 435138889Sjdp } 435238889Sjdp else if (op == O_big) 435338889Sjdp { 435438889Sjdp /* O_big is a different sort of constant. */ 435538889Sjdp 435638889Sjdp int size; 435738889Sjdp char *p; 435838889Sjdp 435938889Sjdp size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign); 436038889Sjdp p = frag_more (size); 436138889Sjdp output_big_leb128 (p, generic_bignum, exp->X_add_number, sign); 436238889Sjdp } 436338889Sjdp else 436438889Sjdp { 436577298Sobrien /* Otherwise, we have to create a variable sized fragment and 436638889Sjdp resolve things later. */ 436738889Sjdp 436877298Sobrien frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign, 436938889Sjdp make_expr_symbol (exp), 0, (char *) NULL); 437038889Sjdp } 437138889Sjdp} 437238889Sjdp 437338889Sjdp/* Parse the .sleb128 and .uleb128 pseudos. */ 437438889Sjdp 437538889Sjdpvoid 4376130561Sobriens_leb128 (int sign) 437738889Sjdp{ 437838889Sjdp expressionS exp; 437938889Sjdp 4380130561Sobrien#ifdef md_flush_pending_output 4381130561Sobrien md_flush_pending_output (); 4382130561Sobrien#endif 4383130561Sobrien 4384130561Sobrien#ifdef md_flush_pending_output 4385130561Sobrien md_flush_pending_output (); 4386130561Sobrien#endif 4387130561Sobrien 438877298Sobrien do 438977298Sobrien { 439077298Sobrien expression (&exp); 439177298Sobrien emit_leb128_expr (&exp, sign); 439277298Sobrien } 439377298Sobrien while (*input_line_pointer++ == ','); 439438889Sjdp 439538889Sjdp input_line_pointer--; 439638889Sjdp demand_empty_rest_of_line (); 439738889Sjdp} 439838889Sjdp 439977298Sobrien/* We read 0 or more ',' separated, double-quoted strings. 440077298Sobrien Caller should have checked need_pass_2 is FALSE because we don't 440177298Sobrien check it. */ 440233965Sjdp 440377298Sobrienvoid 4404130561Sobrienstringer (/* Worker to do .ascii etc statements. */ 4405130561Sobrien /* Checks end-of-line. */ 4406130561Sobrien register int append_zero /* 0: don't append '\0', else 1. */) 440733965Sjdp{ 440833965Sjdp register unsigned int c; 440938889Sjdp char *start; 441033965Sjdp 441133965Sjdp#ifdef md_flush_pending_output 441233965Sjdp md_flush_pending_output (); 441333965Sjdp#endif 441433965Sjdp 441577298Sobrien /* The following awkward logic is to parse ZERO or more strings, 441677298Sobrien comma separated. Recall a string expression includes spaces 441777298Sobrien before the opening '\"' and spaces after the closing '\"'. 441877298Sobrien We fake a leading ',' if there is (supposed to be) 441977298Sobrien a 1st, expression. We keep demanding expressions for each ','. */ 442033965Sjdp if (is_it_end_of_statement ()) 442133965Sjdp { 442277298Sobrien c = 0; /* Skip loop. */ 442377298Sobrien ++input_line_pointer; /* Compensate for end of loop. */ 442433965Sjdp } 442533965Sjdp else 442633965Sjdp { 442777298Sobrien c = ','; /* Do loop. */ 442833965Sjdp } 4429104834Sobrien /* If we have been switched into the abs_section then we 4430104834Sobrien will not have an obstack onto which we can hang strings. */ 4431104834Sobrien if (now_seg == absolute_section) 4432104834Sobrien { 4433104834Sobrien as_bad (_("strings must be placed into a section")); 4434104834Sobrien c = 0; 4435104834Sobrien ignore_rest_of_line (); 4436104834Sobrien } 4437130561Sobrien 443833965Sjdp while (c == ',' || c == '<' || c == '"') 443933965Sjdp { 444033965Sjdp SKIP_WHITESPACE (); 444133965Sjdp switch (*input_line_pointer) 444233965Sjdp { 444333965Sjdp case '\"': 444477298Sobrien ++input_line_pointer; /*->1st char of string. */ 444538889Sjdp start = input_line_pointer; 444633965Sjdp while (is_a_char (c = next_char_of_string ())) 444733965Sjdp { 444833965Sjdp FRAG_APPEND_1_CHAR (c); 444933965Sjdp } 445033965Sjdp if (append_zero) 445133965Sjdp { 445233965Sjdp FRAG_APPEND_1_CHAR (0); 445333965Sjdp } 445433965Sjdp know (input_line_pointer[-1] == '\"'); 445538889Sjdp 445638889Sjdp#ifndef NO_LISTING 445738889Sjdp#ifdef OBJ_ELF 445838889Sjdp /* In ELF, when gcc is emitting DWARF 1 debugging output, it 4459130561Sobrien will emit .string with a filename in the .debug section 4460130561Sobrien after a sequence of constants. See the comment in 4461130561Sobrien emit_expr for the sequence. emit_expr will set 4462130561Sobrien dwarf_file_string to non-zero if this string might be a 4463130561Sobrien source file name. */ 446438889Sjdp if (strcmp (segment_name (now_seg), ".debug") != 0) 446538889Sjdp dwarf_file_string = 0; 446638889Sjdp else if (dwarf_file_string) 446738889Sjdp { 446838889Sjdp c = input_line_pointer[-1]; 446938889Sjdp input_line_pointer[-1] = '\0'; 447038889Sjdp listing_source_file (start); 447138889Sjdp input_line_pointer[-1] = c; 447238889Sjdp } 447338889Sjdp#endif 447438889Sjdp#endif 447538889Sjdp 447633965Sjdp break; 447733965Sjdp case '<': 447833965Sjdp input_line_pointer++; 447933965Sjdp c = get_single_number (); 448033965Sjdp FRAG_APPEND_1_CHAR (c); 448133965Sjdp if (*input_line_pointer != '>') 448233965Sjdp { 448389857Sobrien as_bad (_("expected <nn>")); 448433965Sjdp } 448533965Sjdp input_line_pointer++; 448633965Sjdp break; 448733965Sjdp case ',': 448833965Sjdp input_line_pointer++; 448933965Sjdp break; 449033965Sjdp } 449133965Sjdp SKIP_WHITESPACE (); 449233965Sjdp c = *input_line_pointer; 449333965Sjdp } 449433965Sjdp 449533965Sjdp demand_empty_rest_of_line (); 449633965Sjdp} /* stringer() */ 449733965Sjdp 449833965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the 449933965Sjdp high bits set. We'll probably also have trouble with 450033965Sjdp multibyte chars, wide chars, etc. Also be careful about 450177298Sobrien returning values bigger than 1 byte. xoxorich. */ 450233965Sjdp 450377298Sobrienunsigned int 4504130561Sobriennext_char_of_string (void) 450533965Sjdp{ 450633965Sjdp register unsigned int c; 450733965Sjdp 450833965Sjdp c = *input_line_pointer++ & CHAR_MASK; 450933965Sjdp switch (c) 451033965Sjdp { 451133965Sjdp case '\"': 451233965Sjdp c = NOT_A_CHAR; 451333965Sjdp break; 451433965Sjdp 451533965Sjdp case '\n': 451689857Sobrien as_warn (_("unterminated string; newline inserted")); 451733965Sjdp bump_line_counters (); 451833965Sjdp break; 451933965Sjdp 452033965Sjdp#ifndef NO_STRING_ESCAPES 452133965Sjdp case '\\': 452233965Sjdp switch (c = *input_line_pointer++) 452333965Sjdp { 452433965Sjdp case 'b': 452533965Sjdp c = '\b'; 452633965Sjdp break; 452733965Sjdp 452833965Sjdp case 'f': 452933965Sjdp c = '\f'; 453033965Sjdp break; 453133965Sjdp 453233965Sjdp case 'n': 453333965Sjdp c = '\n'; 453433965Sjdp break; 453533965Sjdp 453633965Sjdp case 'r': 453733965Sjdp c = '\r'; 453833965Sjdp break; 453933965Sjdp 454033965Sjdp case 't': 454133965Sjdp c = '\t'; 454233965Sjdp break; 454333965Sjdp 454433965Sjdp case 'v': 454533965Sjdp c = '\013'; 454633965Sjdp break; 454733965Sjdp 454833965Sjdp case '\\': 454933965Sjdp case '"': 455077298Sobrien break; /* As itself. */ 455133965Sjdp 455233965Sjdp case '0': 455333965Sjdp case '1': 455433965Sjdp case '2': 455533965Sjdp case '3': 455633965Sjdp case '4': 455733965Sjdp case '5': 455833965Sjdp case '6': 455933965Sjdp case '7': 456033965Sjdp case '8': 456133965Sjdp case '9': 456233965Sjdp { 456333965Sjdp long number; 456433965Sjdp int i; 456533965Sjdp 456677298Sobrien for (i = 0, number = 0; 456789857Sobrien ISDIGIT (c) && i < 3; 456877298Sobrien c = *input_line_pointer++, i++) 456933965Sjdp { 457033965Sjdp number = number * 8 + c - '0'; 457133965Sjdp } 457277298Sobrien 457333965Sjdp c = number & 0xff; 457433965Sjdp } 457533965Sjdp --input_line_pointer; 457633965Sjdp break; 457733965Sjdp 457833965Sjdp case 'x': 457933965Sjdp case 'X': 458033965Sjdp { 458133965Sjdp long number; 458233965Sjdp 458333965Sjdp number = 0; 458433965Sjdp c = *input_line_pointer++; 458589857Sobrien while (ISXDIGIT (c)) 458633965Sjdp { 458789857Sobrien if (ISDIGIT (c)) 458833965Sjdp number = number * 16 + c - '0'; 458989857Sobrien else if (ISUPPER (c)) 459033965Sjdp number = number * 16 + c - 'A' + 10; 459133965Sjdp else 459233965Sjdp number = number * 16 + c - 'a' + 10; 459333965Sjdp c = *input_line_pointer++; 459433965Sjdp } 459533965Sjdp c = number & 0xff; 459633965Sjdp --input_line_pointer; 459733965Sjdp } 459833965Sjdp break; 459933965Sjdp 460033965Sjdp case '\n': 460177298Sobrien /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ 460289857Sobrien as_warn (_("unterminated string; newline inserted")); 460333965Sjdp c = '\n'; 460433965Sjdp bump_line_counters (); 460533965Sjdp break; 460633965Sjdp 460733965Sjdp default: 460833965Sjdp 460933965Sjdp#ifdef ONLY_STANDARD_ESCAPES 461089857Sobrien as_bad (_("bad escaped character in string")); 461133965Sjdp c = '?'; 461233965Sjdp#endif /* ONLY_STANDARD_ESCAPES */ 461333965Sjdp 461433965Sjdp break; 461577298Sobrien } 461633965Sjdp break; 461733965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */ 461833965Sjdp 461933965Sjdp default: 462033965Sjdp break; 462177298Sobrien } 462233965Sjdp return (c); 462377298Sobrien} 462433965Sjdp 462533965Sjdpstatic segT 4626130561Sobrienget_segmented_expression (register expressionS *expP) 462733965Sjdp{ 462833965Sjdp register segT retval; 462933965Sjdp 463033965Sjdp retval = expression (expP); 463133965Sjdp if (expP->X_op == O_illegal 463233965Sjdp || expP->X_op == O_absent 463333965Sjdp || expP->X_op == O_big) 463433965Sjdp { 463589857Sobrien as_bad (_("expected address expression")); 463633965Sjdp expP->X_op = O_constant; 463733965Sjdp expP->X_add_number = 0; 463833965Sjdp retval = absolute_section; 463933965Sjdp } 464033965Sjdp return retval; 464133965Sjdp} 464233965Sjdp 464377298Sobrienstatic segT 4644130561Sobrienget_known_segmented_expression (register expressionS *expP) 464533965Sjdp{ 464633965Sjdp register segT retval; 464733965Sjdp 464833965Sjdp if ((retval = get_segmented_expression (expP)) == undefined_section) 464933965Sjdp { 465033965Sjdp /* There is no easy way to extract the undefined symbol from the 465133965Sjdp expression. */ 465233965Sjdp if (expP->X_add_symbol != NULL 465333965Sjdp && S_GET_SEGMENT (expP->X_add_symbol) != expr_section) 465460484Sobrien as_warn (_("symbol \"%s\" undefined; zero assumed"), 465533965Sjdp S_GET_NAME (expP->X_add_symbol)); 465633965Sjdp else 465760484Sobrien as_warn (_("some symbol undefined; zero assumed")); 465833965Sjdp retval = absolute_section; 465933965Sjdp expP->X_op = O_constant; 466033965Sjdp expP->X_add_number = 0; 466133965Sjdp } 466233965Sjdp know (retval == absolute_section || SEG_NORMAL (retval)); 466333965Sjdp return (retval); 466477298Sobrien} 466533965Sjdp 466633965SjdpoffsetT 4667130561Sobrienget_absolute_expr (expressionS *exp) 466833965Sjdp{ 4669130561Sobrien expression (exp); 4670130561Sobrien if (exp->X_op != O_constant) 467133965Sjdp { 4672130561Sobrien if (exp->X_op != O_absent) 467389857Sobrien as_bad (_("bad or irreducible absolute expression")); 4674130561Sobrien exp->X_add_number = 0; 467533965Sjdp } 4676130561Sobrien return exp->X_add_number; 467733965Sjdp} 467833965Sjdp 4679130561SobrienoffsetT 4680130561Sobrienget_absolute_expression (void) 4681130561Sobrien{ 4682130561Sobrien expressionS exp; 4683130561Sobrien 4684130561Sobrien return get_absolute_expr (&exp); 4685130561Sobrien} 4686130561Sobrien 468777298Sobrienchar /* Return terminator. */ 4688130561Sobrienget_absolute_expression_and_terminator (long *val_pointer /* Return value of expression. */) 468933965Sjdp{ 469033965Sjdp /* FIXME: val_pointer should probably be offsetT *. */ 469133965Sjdp *val_pointer = (long) get_absolute_expression (); 469233965Sjdp return (*input_line_pointer++); 469333965Sjdp} 469433965Sjdp 469577298Sobrien/* Like demand_copy_string, but return NULL if the string contains any '\0's. 469677298Sobrien Give a warning if that happens. */ 469777298Sobrien 469833965Sjdpchar * 4699130561Sobriendemand_copy_C_string (int *len_pointer) 470033965Sjdp{ 470133965Sjdp register char *s; 470233965Sjdp 470333965Sjdp if ((s = demand_copy_string (len_pointer)) != 0) 470433965Sjdp { 470533965Sjdp register int len; 470633965Sjdp 470733965Sjdp for (len = *len_pointer; len > 0; len--) 470833965Sjdp { 470933965Sjdp if (*s == 0) 471033965Sjdp { 471133965Sjdp s = 0; 471233965Sjdp len = 1; 471333965Sjdp *len_pointer = 0; 471489857Sobrien as_bad (_("this string may not contain \'\\0\'")); 471533965Sjdp } 471633965Sjdp } 471733965Sjdp } 471877298Sobrien 471933965Sjdp return s; 472033965Sjdp} 472133965Sjdp 472277298Sobrien/* Demand string, but return a safe (=private) copy of the string. 472377298Sobrien Return NULL if we can't read a string here. */ 472477298Sobrien 472533965Sjdpchar * 4726130561Sobriendemand_copy_string (int *lenP) 472733965Sjdp{ 472833965Sjdp register unsigned int c; 472933965Sjdp register int len; 473033965Sjdp char *retval; 473133965Sjdp 473233965Sjdp len = 0; 473333965Sjdp SKIP_WHITESPACE (); 473433965Sjdp if (*input_line_pointer == '\"') 473533965Sjdp { 473677298Sobrien input_line_pointer++; /* Skip opening quote. */ 473733965Sjdp 473833965Sjdp while (is_a_char (c = next_char_of_string ())) 473933965Sjdp { 474033965Sjdp obstack_1grow (¬es, c); 474133965Sjdp len++; 474233965Sjdp } 474333965Sjdp /* JF this next line is so demand_copy_C_string will return a 474477298Sobrien null terminated string. */ 474533965Sjdp obstack_1grow (¬es, '\0'); 474633965Sjdp retval = obstack_finish (¬es); 474733965Sjdp } 474833965Sjdp else 474933965Sjdp { 4750130561Sobrien as_bad (_("missing string")); 475133965Sjdp retval = NULL; 475233965Sjdp ignore_rest_of_line (); 475333965Sjdp } 475433965Sjdp *lenP = len; 475533965Sjdp return (retval); 475677298Sobrien} 475733965Sjdp 475877298Sobrien/* In: Input_line_pointer->next character. 475977298Sobrien 476077298Sobrien Do: Skip input_line_pointer over all whitespace. 476177298Sobrien 476277298Sobrien Out: 1 if input_line_pointer->end-of-line. */ 476377298Sobrien 476477298Sobrienint 4765130561Sobrienis_it_end_of_statement (void) 476633965Sjdp{ 476733965Sjdp SKIP_WHITESPACE (); 476833965Sjdp return (is_end_of_line[(unsigned char) *input_line_pointer]); 476977298Sobrien} 477033965Sjdp 477177298Sobrienvoid 4772130561Sobrienequals (char *sym_name, int reassign) 477333965Sjdp{ 477477298Sobrien register symbolS *symbolP; /* Symbol we are working with. */ 477538889Sjdp char *stop = NULL; 477633965Sjdp char stopc; 477733965Sjdp 477833965Sjdp input_line_pointer++; 477933965Sjdp if (*input_line_pointer == '=') 478033965Sjdp input_line_pointer++; 478133965Sjdp 478233965Sjdp while (*input_line_pointer == ' ' || *input_line_pointer == '\t') 478333965Sjdp input_line_pointer++; 478433965Sjdp 478533965Sjdp if (flag_mri) 478633965Sjdp stop = mri_comment_field (&stopc); 478733965Sjdp 478833965Sjdp if (sym_name[0] == '.' && sym_name[1] == '\0') 478933965Sjdp { 479077298Sobrien /* Turn '. = mumble' into a .org mumble. */ 479133965Sjdp register segT segment; 479233965Sjdp expressionS exp; 479333965Sjdp 479433965Sjdp segment = get_known_segmented_expression (&exp); 479533965Sjdp if (!need_pass_2) 479633965Sjdp do_org (segment, &exp, 0); 479733965Sjdp } 479833965Sjdp else 479933965Sjdp { 480078828Sobrien#ifdef OBJ_COFF 480178828Sobrien int local; 480278828Sobrien 480378828Sobrien symbolP = symbol_find (sym_name); 480478828Sobrien local = symbolP == NULL; 480578828Sobrien if (local) 480678828Sobrien#endif /* OBJ_COFF */ 480733965Sjdp symbolP = symbol_find_or_make (sym_name); 480833965Sjdp /* Permit register names to be redefined. */ 480977298Sobrien if (!reassign 481033965Sjdp && S_IS_DEFINED (symbolP) 481133965Sjdp && S_GET_SEGMENT (symbolP) != reg_section) 481289857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 481378828Sobrien 481478828Sobrien#ifdef OBJ_COFF 481578828Sobrien /* "set" symbols are local unless otherwise specified. */ 481678828Sobrien if (local) 481778828Sobrien SF_SET_LOCAL (symbolP); 481878828Sobrien#endif /* OBJ_COFF */ 481978828Sobrien 482033965Sjdp pseudo_set (symbolP); 482133965Sjdp } 482233965Sjdp 482333965Sjdp if (flag_mri) 482477298Sobrien { 482577298Sobrien /* Check garbage after the expression. */ 4826130561Sobrien demand_empty_rest_of_line (); 482777298Sobrien mri_comment_end (stop, stopc); 482877298Sobrien } 482977298Sobrien} 483033965Sjdp 483189857Sobrien/* .incbin -- include a file verbatim at the current location. */ 483289857Sobrien 483389857Sobrienvoid 4834130561Sobriens_incbin (int x ATTRIBUTE_UNUSED) 483589857Sobrien{ 483689857Sobrien FILE * binfile; 483789857Sobrien char * path; 483889857Sobrien char * filename; 483989857Sobrien char * binfrag; 484089857Sobrien long skip = 0; 484189857Sobrien long count = 0; 484289857Sobrien long bytes; 484389857Sobrien int len; 484489857Sobrien 484589857Sobrien#ifdef md_flush_pending_output 484689857Sobrien md_flush_pending_output (); 484789857Sobrien#endif 484889857Sobrien 484989857Sobrien SKIP_WHITESPACE (); 485089857Sobrien filename = demand_copy_string (& len); 485189857Sobrien if (filename == NULL) 485289857Sobrien return; 485389857Sobrien 485489857Sobrien SKIP_WHITESPACE (); 485589857Sobrien 485689857Sobrien /* Look for optional skip and count. */ 485789857Sobrien if (* input_line_pointer == ',') 485889857Sobrien { 485989857Sobrien ++ input_line_pointer; 486089857Sobrien skip = get_absolute_expression (); 486189857Sobrien 486289857Sobrien SKIP_WHITESPACE (); 486389857Sobrien 486489857Sobrien if (* input_line_pointer == ',') 486589857Sobrien { 486689857Sobrien ++ input_line_pointer; 486789857Sobrien 486889857Sobrien count = get_absolute_expression (); 486989857Sobrien if (count == 0) 487089857Sobrien as_warn (_(".incbin count zero, ignoring `%s'"), filename); 487189857Sobrien 487289857Sobrien SKIP_WHITESPACE (); 487389857Sobrien } 487489857Sobrien } 487589857Sobrien 487689857Sobrien demand_empty_rest_of_line (); 487789857Sobrien 487889857Sobrien /* Try opening absolute path first, then try include dirs. */ 487989857Sobrien binfile = fopen (filename, FOPEN_RB); 488089857Sobrien if (binfile == NULL) 488189857Sobrien { 488289857Sobrien int i; 488389857Sobrien 488489857Sobrien path = xmalloc ((unsigned long) len + include_dir_maxlen + 5); 488589857Sobrien 488689857Sobrien for (i = 0; i < include_dir_count; i++) 488789857Sobrien { 488889857Sobrien sprintf (path, "%s/%s", include_dirs[i], filename); 488989857Sobrien 489089857Sobrien binfile = fopen (path, FOPEN_RB); 489189857Sobrien if (binfile != NULL) 489289857Sobrien break; 489389857Sobrien } 489489857Sobrien 489589857Sobrien if (binfile == NULL) 489689857Sobrien as_bad (_("file not found: %s"), filename); 489789857Sobrien } 489889857Sobrien else 489989857Sobrien path = xstrdup (filename); 490089857Sobrien 490189857Sobrien if (binfile) 490289857Sobrien { 490389857Sobrien long file_len; 490489857Sobrien 490589857Sobrien register_dependency (path); 490689857Sobrien 490789857Sobrien /* Compute the length of the file. */ 490889857Sobrien if (fseek (binfile, 0, SEEK_END) != 0) 490989857Sobrien { 491089857Sobrien as_bad (_("seek to end of .incbin file failed `%s'"), path); 491189857Sobrien goto done; 491289857Sobrien } 491389857Sobrien file_len = ftell (binfile); 491489857Sobrien 491589857Sobrien /* If a count was not specified use the size of the file. */ 491689857Sobrien if (count == 0) 491789857Sobrien count = file_len; 491889857Sobrien 491989857Sobrien if (skip + count > file_len) 492089857Sobrien { 492189857Sobrien as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"), 492289857Sobrien skip, count, file_len); 492389857Sobrien goto done; 492489857Sobrien } 492589857Sobrien 492689857Sobrien if (fseek (binfile, skip, SEEK_SET) != 0) 492789857Sobrien { 492889857Sobrien as_bad (_("could not skip to %ld in file `%s'"), skip, path); 492989857Sobrien goto done; 493089857Sobrien } 493189857Sobrien 493289857Sobrien /* Allocate frag space and store file contents in it. */ 493389857Sobrien binfrag = frag_more (count); 493489857Sobrien 493589857Sobrien bytes = fread (binfrag, 1, count, binfile); 493689857Sobrien if (bytes < count) 493789857Sobrien as_warn (_("truncated file `%s', %ld of %ld bytes read"), 493889857Sobrien path, bytes, count); 493989857Sobrien } 494089857Sobriendone: 494189857Sobrien if (binfile != NULL) 494289857Sobrien fclose (binfile); 494389857Sobrien if (path) 494489857Sobrien free (path); 494589857Sobrien} 494689857Sobrien 494777298Sobrien/* .include -- include a file at this point. */ 494833965Sjdp 494977298Sobrienvoid 4950130561Sobriens_include (int arg ATTRIBUTE_UNUSED) 495133965Sjdp{ 495233965Sjdp char *filename; 495333965Sjdp int i; 495433965Sjdp FILE *try; 495533965Sjdp char *path; 495633965Sjdp 495777298Sobrien if (!flag_m68k_mri) 495838889Sjdp { 495938889Sjdp filename = demand_copy_string (&i); 496038889Sjdp if (filename == NULL) 496138889Sjdp { 496238889Sjdp /* demand_copy_string has already printed an error and 4963130561Sobrien called ignore_rest_of_line. */ 496438889Sjdp return; 496538889Sjdp } 496638889Sjdp } 496733965Sjdp else 496833965Sjdp { 496933965Sjdp SKIP_WHITESPACE (); 497033965Sjdp i = 0; 497177298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer] 497233965Sjdp && *input_line_pointer != ' ' 497333965Sjdp && *input_line_pointer != '\t') 497433965Sjdp { 497533965Sjdp obstack_1grow (¬es, *input_line_pointer); 497633965Sjdp ++input_line_pointer; 497733965Sjdp ++i; 497833965Sjdp } 497977298Sobrien 498033965Sjdp obstack_1grow (¬es, '\0'); 498133965Sjdp filename = obstack_finish (¬es); 498277298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 498333965Sjdp ++input_line_pointer; 498433965Sjdp } 498577298Sobrien 498633965Sjdp demand_empty_rest_of_line (); 498733965Sjdp path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ ); 498877298Sobrien 498933965Sjdp for (i = 0; i < include_dir_count; i++) 499033965Sjdp { 499133965Sjdp strcpy (path, include_dirs[i]); 499233965Sjdp strcat (path, "/"); 499333965Sjdp strcat (path, filename); 499489857Sobrien if (0 != (try = fopen (path, FOPEN_RT))) 499533965Sjdp { 499633965Sjdp fclose (try); 499733965Sjdp goto gotit; 499833965Sjdp } 499933965Sjdp } 500077298Sobrien 500133965Sjdp free (path); 500233965Sjdp path = filename; 500333965Sjdpgotit: 500477298Sobrien /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ 500538889Sjdp register_dependency (path); 500660484Sobrien input_scrub_insert_file (path); 500777298Sobrien} 500833965Sjdp 500977298Sobrienvoid 5010130561Sobrienadd_include_dir (char *path) 501133965Sjdp{ 501233965Sjdp int i; 501333965Sjdp 501433965Sjdp if (include_dir_count == 0) 501533965Sjdp { 501633965Sjdp include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs)); 501777298Sobrien include_dirs[0] = "."; /* Current dir. */ 501833965Sjdp include_dir_count = 2; 501933965Sjdp } 502033965Sjdp else 502133965Sjdp { 502233965Sjdp include_dir_count++; 502377298Sobrien include_dirs = 502477298Sobrien (char **) realloc (include_dirs, 502577298Sobrien include_dir_count * sizeof (*include_dirs)); 502633965Sjdp } 502733965Sjdp 502877298Sobrien include_dirs[include_dir_count - 1] = path; /* New one. */ 502933965Sjdp 503033965Sjdp i = strlen (path); 503133965Sjdp if (i > include_dir_maxlen) 503233965Sjdp include_dir_maxlen = i; 503377298Sobrien} 503460484Sobrien 503560484Sobrien/* Output debugging information to denote the source file. */ 503633965Sjdp 503760484Sobrienstatic void 5038130561Sobriengenerate_file_debug (void) 503960484Sobrien{ 504060484Sobrien if (debug_type == DEBUG_STABS) 504160484Sobrien stabs_generate_asm_file (); 504260484Sobrien} 504360484Sobrien 504460484Sobrien/* Output line number debugging information for the current source line. */ 504560484Sobrien 504660484Sobrienvoid 5047130561Sobriengenerate_lineno_debug (void) 504860484Sobrien{ 504960484Sobrien switch (debug_type) 505060484Sobrien { 505160484Sobrien case DEBUG_UNSPECIFIED: 505260484Sobrien case DEBUG_NONE: 505377298Sobrien case DEBUG_DWARF: 505460484Sobrien break; 505560484Sobrien case DEBUG_STABS: 505660484Sobrien stabs_generate_asm_lineno (); 505760484Sobrien break; 505860484Sobrien case DEBUG_ECOFF: 505960484Sobrien ecoff_generate_asm_lineno (); 506060484Sobrien break; 506160484Sobrien case DEBUG_DWARF2: 506277298Sobrien /* ??? We could here indicate to dwarf2dbg.c that something 506377298Sobrien has changed. However, since there is additional backend 506477298Sobrien support that is required (calling dwarf2_emit_insn), we 506577298Sobrien let dwarf2dbg.c call as_where on its own. */ 506660484Sobrien break; 506760484Sobrien } 506860484Sobrien} 506960484Sobrien 507060484Sobrien/* Output debugging information to mark a function entry point or end point. 507160484Sobrien END_P is zero for .func, and non-zero for .endfunc. */ 507260484Sobrien 507360484Sobrienvoid 5074130561Sobriens_func (int end_p) 507560484Sobrien{ 507660484Sobrien do_s_func (end_p, NULL); 507760484Sobrien} 507860484Sobrien 507960484Sobrien/* Subroutine of s_func so targets can choose a different default prefix. 508060484Sobrien If DEFAULT_PREFIX is NULL, use the target's "leading char". */ 508160484Sobrien 508260484Sobrienvoid 5083130561Sobriendo_s_func (int end_p, const char *default_prefix) 508460484Sobrien{ 508560484Sobrien /* Record the current function so that we can issue an error message for 508660484Sobrien misplaced .func,.endfunc, and also so that .endfunc needs no 508760484Sobrien arguments. */ 508860484Sobrien static char *current_name; 508960484Sobrien static char *current_label; 509060484Sobrien 509160484Sobrien if (end_p) 509260484Sobrien { 509360484Sobrien if (current_name == NULL) 509460484Sobrien { 509560484Sobrien as_bad (_("missing .func")); 509660484Sobrien ignore_rest_of_line (); 509760484Sobrien return; 509860484Sobrien } 509960484Sobrien 510060484Sobrien if (debug_type == DEBUG_STABS) 510160484Sobrien stabs_generate_asm_endfunc (current_name, current_label); 510260484Sobrien 510360484Sobrien current_name = current_label = NULL; 510460484Sobrien } 510560484Sobrien else /* ! end_p */ 510660484Sobrien { 510777298Sobrien char *name, *label; 510877298Sobrien char delim1, delim2; 510960484Sobrien 511060484Sobrien if (current_name != NULL) 511160484Sobrien { 511260484Sobrien as_bad (_(".endfunc missing for previous .func")); 511360484Sobrien ignore_rest_of_line (); 511460484Sobrien return; 511560484Sobrien } 511660484Sobrien 511760484Sobrien name = input_line_pointer; 511860484Sobrien delim1 = get_symbol_end (); 511960484Sobrien name = xstrdup (name); 512060484Sobrien *input_line_pointer = delim1; 512160484Sobrien SKIP_WHITESPACE (); 512260484Sobrien if (*input_line_pointer != ',') 512360484Sobrien { 512460484Sobrien if (default_prefix) 512560484Sobrien asprintf (&label, "%s%s", default_prefix, name); 512660484Sobrien else 512760484Sobrien { 512860484Sobrien char leading_char = 0; 512960484Sobrien#ifdef BFD_ASSEMBLER 513060484Sobrien leading_char = bfd_get_symbol_leading_char (stdoutput); 513160484Sobrien#endif 513260484Sobrien /* Missing entry point, use function's name with the leading 513360484Sobrien char prepended. */ 513460484Sobrien if (leading_char) 513560484Sobrien asprintf (&label, "%c%s", leading_char, name); 513660484Sobrien else 513760484Sobrien label = name; 513860484Sobrien } 513960484Sobrien } 514060484Sobrien else 514160484Sobrien { 514260484Sobrien ++input_line_pointer; 514360484Sobrien SKIP_WHITESPACE (); 514460484Sobrien label = input_line_pointer; 514560484Sobrien delim2 = get_symbol_end (); 514660484Sobrien label = xstrdup (label); 514760484Sobrien *input_line_pointer = delim2; 514860484Sobrien } 514960484Sobrien 515060484Sobrien if (debug_type == DEBUG_STABS) 515160484Sobrien stabs_generate_asm_func (name, label); 515260484Sobrien 515360484Sobrien current_name = name; 515460484Sobrien current_label = label; 515560484Sobrien } 515660484Sobrien 515760484Sobrien demand_empty_rest_of_line (); 515860484Sobrien} 515960484Sobrien 516077298Sobrienvoid 5161130561Sobriens_ignore (int arg ATTRIBUTE_UNUSED) 516233965Sjdp{ 516333965Sjdp while (!is_end_of_line[(unsigned char) *input_line_pointer]) 516433965Sjdp { 516533965Sjdp ++input_line_pointer; 516633965Sjdp } 516733965Sjdp ++input_line_pointer; 516833965Sjdp} 516933965Sjdp 517033965Sjdpvoid 5171130561Sobrienread_print_statistics (FILE *file) 517233965Sjdp{ 517333965Sjdp hash_print_statistics (file, "pseudo-op table", po_hash); 517433965Sjdp} 517533965Sjdp 517677298Sobrien/* Inserts the given line into the input stream. 517777298Sobrien 517860484Sobrien This call avoids macro/conditionals nesting checking, since the contents of 517960484Sobrien the line are assumed to replace the contents of a line already scanned. 518060484Sobrien 5181130561Sobrien An appropriate use of this function would be substitution of input lines when 518260484Sobrien called by md_start_line_hook(). The given line is assumed to already be 518360484Sobrien properly scrubbed. */ 518460484Sobrien 518560484Sobrienvoid 5186130561Sobrieninput_scrub_insert_line (const char *line) 518760484Sobrien{ 518860484Sobrien sb newline; 518960484Sobrien sb_new (&newline); 519060484Sobrien sb_add_string (&newline, line); 519160484Sobrien input_scrub_include_sb (&newline, input_line_pointer, 0); 519260484Sobrien sb_kill (&newline); 519360484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 519460484Sobrien} 519560484Sobrien 519660484Sobrien/* Insert a file into the input stream; the path must resolve to an actual 519777298Sobrien file; no include path searching or dependency registering is performed. */ 519860484Sobrien 519960484Sobrienvoid 5200130561Sobrieninput_scrub_insert_file (char *path) 520160484Sobrien{ 520260484Sobrien input_scrub_include_file (path, input_line_pointer); 520360484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 520460484Sobrien} 5205