read.c revision 89857
133965Sjdp/* read.c - read a source file - 278828Sobrien Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 389857Sobrien 1998, 1999, 2000, 2001 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 3533965Sjdp/* Routines that read assembler source text to build spagetti 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" 4633965Sjdp 4733965Sjdp#ifndef TC_START_LABEL 4833965Sjdp#define TC_START_LABEL(x,y) (x==':') 4933965Sjdp#endif 5033965Sjdp 5160484Sobrien/* Set by the object-format or the target. */ 5260484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT 5377298Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ 5477298Sobrien do \ 5577298Sobrien { \ 5677298Sobrien if ((SIZE) >= 8) \ 5777298Sobrien (P2VAR) = 3; \ 5877298Sobrien else if ((SIZE) >= 4) \ 5977298Sobrien (P2VAR) = 2; \ 6077298Sobrien else if ((SIZE) >= 2) \ 6177298Sobrien (P2VAR) = 1; \ 6277298Sobrien else \ 6377298Sobrien (P2VAR) = 0; \ 6477298Sobrien } \ 6577298Sobrien while (0) 6660484Sobrien#endif 6760484Sobrien 6877298Sobrienchar *input_line_pointer; /*->next char of source file to parse. */ 6933965Sjdp 7033965Sjdp#if BITS_PER_CHAR != 8 7133965Sjdp/* The following table is indexed by[(char)] and will break if 7233965Sjdp a char does not have exactly 256 states (hopefully 0:255!)! */ 7333965Sjdpdie horribly; 7433965Sjdp#endif 7533965Sjdp 7633965Sjdp#ifndef LEX_AT 7733965Sjdp/* The m88k unfortunately uses @ as a label beginner. */ 7833965Sjdp#define LEX_AT 0 7933965Sjdp#endif 8033965Sjdp 8133965Sjdp#ifndef LEX_BR 8233965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */ 8333965Sjdp#define LEX_BR 0 8433965Sjdp#endif 8533965Sjdp 8633965Sjdp#ifndef LEX_PCT 8733965Sjdp/* The Delta 68k assembler permits % inside label names. */ 8833965Sjdp#define LEX_PCT 0 8933965Sjdp#endif 9033965Sjdp 9133965Sjdp#ifndef LEX_QM 9233965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names. */ 9333965Sjdp#define LEX_QM 0 9433965Sjdp#endif 9533965Sjdp 9660484Sobrien#ifndef LEX_HASH 9777298Sobrien/* The IA-64 assembler uses # as a suffix designating a symbol. We include 9877298Sobrien it in the symbol and strip it out in tc_canonicalize_symbol_name. */ 9960484Sobrien#define LEX_HASH 0 10060484Sobrien#endif 10160484Sobrien 10233965Sjdp#ifndef LEX_DOLLAR 10333965Sjdp/* The a29k assembler does not permits labels to start with $. */ 10433965Sjdp#define LEX_DOLLAR 3 10533965Sjdp#endif 10633965Sjdp 10733965Sjdp#ifndef LEX_TILDE 10833965Sjdp/* The Delta 68k assembler permits ~ at start of label names. */ 10933965Sjdp#define LEX_TILDE 0 11033965Sjdp#endif 11133965Sjdp 11277298Sobrien/* Used by is_... macros. our ctype[]. */ 11377298Sobrienchar lex_type[256] = { 11433965Sjdp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ 11533965Sjdp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ 11660484Sobrien 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ 11733965Sjdp 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */ 11833965Sjdp LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ 11933965Sjdp 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */ 12033965Sjdp 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ 12177298Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */ 12260484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12360484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12460484Sobrien 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 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 13033965Sjdp}; 13133965Sjdp 13277298Sobrien/* In: a character. 13377298Sobrien Out: 1 if this character ends a line. */ 13477298Sobrienchar is_end_of_line[256] = { 13533965Sjdp#ifdef CR_EOL 13677298Sobrien 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, /* @abcdefghijklmno */ 13733965Sjdp#else 13877298Sobrien 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* @abcdefghijklmno */ 13933965Sjdp#endif 14077298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14177298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* _!"#$%&'()*+,-./ */ 14277298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ 14377298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14477298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14577298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14677298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14777298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14877298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 14977298Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 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 /* */ 15533965Sjdp}; 15633965Sjdp 15777298Sobrien#ifdef IGNORE_OPCODE_CASE 15877298Sobrienchar original_case_string[128]; 15977298Sobrien#endif 16033965Sjdp 16177298Sobrien/* Functions private to this file. */ 16233965Sjdp 16377298Sobrienstatic char *buffer; /* 1st char of each buffer of lines is here. */ 16477298Sobrienstatic char *buffer_limit; /*->1 + last char in buffer. */ 16577298Sobrien 16677298Sobrien/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 16777298Sobrien in the tc-<CPU>.h file. See the "Porting GAS" section of the 16877298Sobrien internals manual. */ 16933965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN; 17033965Sjdp 17177298Sobrienstatic char *old_buffer; /* JF a hack. */ 17233965Sjdpstatic char *old_input; 17333965Sjdpstatic char *old_limit; 17433965Sjdp 17577298Sobrien/* Variables for handling include file directory table. */ 17633965Sjdp 17777298Sobrien/* Table of pointers to directories to search for .include's. */ 17877298Sobrienchar **include_dirs; 17933965Sjdp 18077298Sobrien/* How many are in the table. */ 18177298Sobrienint include_dir_count; 18277298Sobrien 18377298Sobrien/* Length of longest in table. */ 18477298Sobrienint include_dir_maxlen = 1; 18577298Sobrien 18633965Sjdp#ifndef WORKING_DOT_WORD 18733965Sjdpstruct broken_word *broken_words; 18833965Sjdpint new_broken_words; 18933965Sjdp#endif 19033965Sjdp 19133965Sjdp/* The current offset into the absolute section. We don't try to 19233965Sjdp build frags in the absolute section, since no data can be stored 19333965Sjdp there. We just keep track of the current offset. */ 19433965SjdpaddressT abs_section_offset; 19533965Sjdp 19633965Sjdp/* If this line had an MRI style label, it is stored in this variable. 19733965Sjdp This is used by some of the MRI pseudo-ops. */ 19833965SjdpsymbolS *line_label; 19933965Sjdp 20033965Sjdp/* This global variable is used to support MRI common sections. We 20133965Sjdp translate such sections into a common symbol. This variable is 20233965Sjdp non-NULL when we are in an MRI common section. */ 20333965SjdpsymbolS *mri_common_symbol; 20433965Sjdp 20533965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we 20633965Sjdp need to align to an even byte boundary unless the next pseudo-op is 20733965Sjdp dc.b, ds.b, or dcb.b. This variable is set to 1 if an alignment 20833965Sjdp may be needed. */ 20933965Sjdpstatic int mri_pending_align; 21033965Sjdp 21138889Sjdp#ifndef NO_LISTING 21238889Sjdp#ifdef OBJ_ELF 21338889Sjdp/* This variable is set to be non-zero if the next string we see might 21438889Sjdp be the name of the source file in DWARF debugging information. See 21538889Sjdp the comment in emit_expr for the format we look for. */ 21638889Sjdpstatic int dwarf_file_string; 21738889Sjdp#endif 21838889Sjdp#endif 21938889Sjdp 22033965Sjdpstatic void cons_worker PARAMS ((int, int)); 22160484Sobrienstatic int scrub_from_string PARAMS ((char *, int)); 22233965Sjdpstatic void do_align PARAMS ((int, char *, int, int)); 22333965Sjdpstatic void s_align PARAMS ((int, int)); 22460484Sobrienstatic void s_lcomm_internal PARAMS ((int, int)); 22533965Sjdpstatic int hex_float PARAMS ((int, char *)); 22660484Sobrienstatic inline int sizeof_sleb128 PARAMS ((offsetT)); 22760484Sobrienstatic inline int sizeof_uleb128 PARAMS ((valueT)); 22860484Sobrienstatic inline int output_sleb128 PARAMS ((char *, offsetT)); 22960484Sobrienstatic inline int output_uleb128 PARAMS ((char *, valueT)); 23060484Sobrienstatic inline int output_big_sleb128 PARAMS ((char *, LITTLENUM_TYPE *, int)); 23160484Sobrienstatic inline int output_big_uleb128 PARAMS ((char *, LITTLENUM_TYPE *, int)); 23260484Sobrienstatic int output_big_leb128 PARAMS ((char *, LITTLENUM_TYPE *, int, int)); 23333965Sjdpstatic void do_org PARAMS ((segT, expressionS *, int)); 23433965Sjdpchar *demand_copy_string PARAMS ((int *lenP)); 23533965Sjdpstatic segT get_segmented_expression PARAMS ((expressionS *expP)); 23633965Sjdpstatic segT get_known_segmented_expression PARAMS ((expressionS * expP)); 23733965Sjdpstatic void pobegin PARAMS ((void)); 23833965Sjdpstatic int get_line_sb PARAMS ((sb *)); 23960484Sobrienstatic void generate_file_debug PARAMS ((void)); 24033965Sjdp 24133965Sjdpvoid 24233965Sjdpread_begin () 24333965Sjdp{ 24433965Sjdp const char *p; 24533965Sjdp 24633965Sjdp pobegin (); 24733965Sjdp obj_read_begin_hook (); 24833965Sjdp 24933965Sjdp /* Something close -- but not too close -- to a multiple of 1024. 25033965Sjdp The debugging malloc I'm using has 24 bytes of overhead. */ 25133965Sjdp obstack_begin (¬es, chunksize); 25233965Sjdp obstack_begin (&cond_obstack, chunksize); 25333965Sjdp 25477298Sobrien /* Use machine dependent syntax. */ 25533965Sjdp for (p = line_separator_chars; *p; p++) 25633965Sjdp is_end_of_line[(unsigned char) *p] = 1; 25777298Sobrien /* Use more. FIXME-SOMEDAY. */ 25833965Sjdp 25933965Sjdp if (flag_mri) 26033965Sjdp lex_type['?'] = 3; 26133965Sjdp} 26233965Sjdp 26377298Sobrien/* Set up pseudo-op tables. */ 26433965Sjdp 26533965Sjdpstatic struct hash_control *po_hash; 26633965Sjdp 26777298Sobrienstatic const pseudo_typeS potable[] = { 26833965Sjdp {"abort", s_abort, 0}, 26933965Sjdp {"align", s_align_ptwo, 0}, 27033965Sjdp {"ascii", stringer, 0}, 27133965Sjdp {"asciz", stringer, 1}, 27233965Sjdp {"balign", s_align_bytes, 0}, 27333965Sjdp {"balignw", s_align_bytes, -2}, 27433965Sjdp {"balignl", s_align_bytes, -4}, 27577298Sobrien/* block */ 27633965Sjdp {"byte", cons, 1}, 27733965Sjdp {"comm", s_comm, 0}, 27833965Sjdp {"common", s_mri_common, 0}, 27933965Sjdp {"common.s", s_mri_common, 1}, 28033965Sjdp {"data", s_data, 0}, 28133965Sjdp {"dc", cons, 2}, 28233965Sjdp {"dc.b", cons, 1}, 28333965Sjdp {"dc.d", float_cons, 'd'}, 28433965Sjdp {"dc.l", cons, 4}, 28533965Sjdp {"dc.s", float_cons, 'f'}, 28633965Sjdp {"dc.w", cons, 2}, 28733965Sjdp {"dc.x", float_cons, 'x'}, 28833965Sjdp {"dcb", s_space, 2}, 28933965Sjdp {"dcb.b", s_space, 1}, 29033965Sjdp {"dcb.d", s_float_space, 'd'}, 29133965Sjdp {"dcb.l", s_space, 4}, 29233965Sjdp {"dcb.s", s_float_space, 'f'}, 29333965Sjdp {"dcb.w", s_space, 2}, 29433965Sjdp {"dcb.x", s_float_space, 'x'}, 29533965Sjdp {"ds", s_space, 2}, 29633965Sjdp {"ds.b", s_space, 1}, 29733965Sjdp {"ds.d", s_space, 8}, 29833965Sjdp {"ds.l", s_space, 4}, 29933965Sjdp {"ds.p", s_space, 12}, 30033965Sjdp {"ds.s", s_space, 4}, 30133965Sjdp {"ds.w", s_space, 2}, 30233965Sjdp {"ds.x", s_space, 12}, 30333965Sjdp {"debug", s_ignore, 0}, 30433965Sjdp#ifdef S_SET_DESC 30533965Sjdp {"desc", s_desc, 0}, 30633965Sjdp#endif 30777298Sobrien/* dim */ 30833965Sjdp {"double", float_cons, 'd'}, 30977298Sobrien/* dsect */ 31077298Sobrien {"eject", listing_eject, 0}, /* Formfeed listing. */ 31133965Sjdp {"else", s_else, 0}, 31233965Sjdp {"elsec", s_else, 0}, 31360484Sobrien {"elseif", s_elseif, (int) O_ne}, 31433965Sjdp {"end", s_end, 0}, 31533965Sjdp {"endc", s_endif, 0}, 31660484Sobrien {"endfunc", s_func, 1}, 31733965Sjdp {"endif", s_endif, 0}, 31889857Sobrien {"endr", s_bad_endr, 0}, 31977298Sobrien/* endef */ 32033965Sjdp {"equ", s_set, 0}, 32133965Sjdp {"equiv", s_set, 1}, 32233965Sjdp {"err", s_err, 0}, 32333965Sjdp {"exitm", s_mexit, 0}, 32477298Sobrien/* extend */ 32577298Sobrien {"extern", s_ignore, 0}, /* We treat all undef as ext. */ 32633965Sjdp {"appfile", s_app_file, 1}, 32733965Sjdp {"appline", s_app_line, 0}, 32833965Sjdp {"fail", s_fail, 0}, 32933965Sjdp {"file", s_app_file, 0}, 33033965Sjdp {"fill", s_fill, 0}, 33133965Sjdp {"float", float_cons, 'f'}, 33233965Sjdp {"format", s_ignore, 0}, 33360484Sobrien {"func", s_func, 0}, 33433965Sjdp {"global", s_globl, 0}, 33533965Sjdp {"globl", s_globl, 0}, 33633965Sjdp {"hword", cons, 2}, 33733965Sjdp {"if", s_if, (int) O_ne}, 33833965Sjdp {"ifc", s_ifc, 0}, 33933965Sjdp {"ifdef", s_ifdef, 0}, 34033965Sjdp {"ifeq", s_if, (int) O_eq}, 34133965Sjdp {"ifeqs", s_ifeqs, 0}, 34233965Sjdp {"ifge", s_if, (int) O_ge}, 34333965Sjdp {"ifgt", s_if, (int) O_gt}, 34433965Sjdp {"ifle", s_if, (int) O_le}, 34533965Sjdp {"iflt", s_if, (int) O_lt}, 34633965Sjdp {"ifnc", s_ifc, 1}, 34733965Sjdp {"ifndef", s_ifdef, 1}, 34833965Sjdp {"ifne", s_if, (int) O_ne}, 34933965Sjdp {"ifnes", s_ifeqs, 1}, 35033965Sjdp {"ifnotdef", s_ifdef, 1}, 35189857Sobrien {"incbin", s_incbin, 0}, 35233965Sjdp {"include", s_include, 0}, 35333965Sjdp {"int", cons, 4}, 35433965Sjdp {"irp", s_irp, 0}, 35533965Sjdp {"irep", s_irp, 0}, 35633965Sjdp {"irpc", s_irp, 1}, 35733965Sjdp {"irepc", s_irp, 1}, 35833965Sjdp {"lcomm", s_lcomm, 0}, 35977298Sobrien {"lflags", listing_flags, 0}, /* Listing flags. */ 36033965Sjdp {"linkonce", s_linkonce, 0}, 36177298Sobrien {"list", listing_list, 1}, /* Turn listing on. */ 36233965Sjdp {"llen", listing_psize, 1}, 36333965Sjdp {"long", cons, 4}, 36433965Sjdp {"lsym", s_lsym, 0}, 36533965Sjdp {"macro", s_macro, 0}, 36633965Sjdp {"mexit", s_mexit, 0}, 36733965Sjdp {"mri", s_mri, 0}, 36833965Sjdp {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */ 36933965Sjdp {"name", s_ignore, 0}, 37033965Sjdp {"noformat", s_ignore, 0}, 37177298Sobrien {"nolist", listing_list, 0}, /* Turn listing off. */ 37233965Sjdp {"nopage", listing_nopage, 0}, 37333965Sjdp {"octa", cons, 16}, 37433965Sjdp {"offset", s_struct, 0}, 37533965Sjdp {"org", s_org, 0}, 37633965Sjdp {"p2align", s_align_ptwo, 0}, 37733965Sjdp {"p2alignw", s_align_ptwo, -2}, 37833965Sjdp {"p2alignl", s_align_ptwo, -4}, 37933965Sjdp {"page", listing_eject, 0}, 38033965Sjdp {"plen", listing_psize, 0}, 38133965Sjdp {"print", s_print, 0}, 38277298Sobrien {"psize", listing_psize, 0}, /* Set paper size. */ 38333965Sjdp {"purgem", s_purgem, 0}, 38433965Sjdp {"quad", cons, 8}, 38533965Sjdp {"rep", s_rept, 0}, 38633965Sjdp {"rept", s_rept, 0}, 38733965Sjdp {"rva", s_rva, 4}, 38877298Sobrien {"sbttl", listing_title, 1}, /* Subtitle of listing. */ 38977298Sobrien/* scl */ 39077298Sobrien/* sect */ 39133965Sjdp {"set", s_set, 0}, 39233965Sjdp {"short", cons, 2}, 39333965Sjdp {"single", float_cons, 'f'}, 39477298Sobrien/* size */ 39533965Sjdp {"space", s_space, 0}, 39633965Sjdp {"skip", s_space, 0}, 39738889Sjdp {"sleb128", s_leb128, 1}, 39833965Sjdp {"spc", s_ignore, 0}, 39933965Sjdp {"stabd", s_stab, 'd'}, 40033965Sjdp {"stabn", s_stab, 'n'}, 40133965Sjdp {"stabs", s_stab, 's'}, 40233965Sjdp {"string", stringer, 1}, 40333965Sjdp {"struct", s_struct, 0}, 40477298Sobrien/* tag */ 40533965Sjdp {"text", s_text, 0}, 40633965Sjdp 40733965Sjdp /* This is for gcc to use. It's only just been added (2/94), so gcc 40833965Sjdp won't be able to use it for a while -- probably a year or more. 40933965Sjdp But once this has been released, check with gcc maintainers 41033965Sjdp before deleting it or even changing the spelling. */ 41133965Sjdp {"this_GCC_requires_the_GNU_assembler", s_ignore, 0}, 41233965Sjdp /* If we're folding case -- done for some targets, not necessarily 41333965Sjdp all -- the above string in an input file will be converted to 41433965Sjdp this one. Match it either way... */ 41533965Sjdp {"this_gcc_requires_the_gnu_assembler", s_ignore, 0}, 41633965Sjdp 41777298Sobrien {"title", listing_title, 0}, /* Listing title. */ 41833965Sjdp {"ttl", listing_title, 0}, 41977298Sobrien/* type */ 42038889Sjdp {"uleb128", s_leb128, 0}, 42177298Sobrien/* use */ 42277298Sobrien/* val */ 42333965Sjdp {"xcom", s_comm, 0}, 42433965Sjdp {"xdef", s_globl, 0}, 42533965Sjdp {"xref", s_ignore, 0}, 42633965Sjdp {"xstabs", s_xstab, 's'}, 42733965Sjdp {"word", cons, 2}, 42833965Sjdp {"zero", s_space, 0}, 42977298Sobrien {NULL, NULL, 0} /* End sentinel. */ 43033965Sjdp}; 43133965Sjdp 43233965Sjdpstatic int pop_override_ok = 0; 43333965Sjdpstatic const char *pop_table_name; 43433965Sjdp 43533965Sjdpvoid 43633965Sjdppop_insert (table) 43733965Sjdp const pseudo_typeS *table; 43833965Sjdp{ 43933965Sjdp const char *errtxt; 44033965Sjdp const pseudo_typeS *pop; 44133965Sjdp for (pop = table; pop->poc_name; pop++) 44233965Sjdp { 44333965Sjdp errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); 44433965Sjdp if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists"))) 44560484Sobrien as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name, 44633965Sjdp errtxt); 44733965Sjdp } 44833965Sjdp} 44933965Sjdp 45033965Sjdp#ifndef md_pop_insert 45133965Sjdp#define md_pop_insert() pop_insert(md_pseudo_table) 45233965Sjdp#endif 45333965Sjdp 45433965Sjdp#ifndef obj_pop_insert 45533965Sjdp#define obj_pop_insert() pop_insert(obj_pseudo_table) 45633965Sjdp#endif 45733965Sjdp 45877298Sobrienstatic void 45933965Sjdppobegin () 46033965Sjdp{ 46133965Sjdp po_hash = hash_new (); 46233965Sjdp 46377298Sobrien /* Do the target-specific pseudo ops. */ 46433965Sjdp pop_table_name = "md"; 46533965Sjdp md_pop_insert (); 46633965Sjdp 46777298Sobrien /* Now object specific. Skip any that were in the target table. */ 46833965Sjdp pop_table_name = "obj"; 46933965Sjdp pop_override_ok = 1; 47033965Sjdp obj_pop_insert (); 47133965Sjdp 47277298Sobrien /* Now portable ones. Skip any that we've seen already. */ 47333965Sjdp pop_table_name = "standard"; 47433965Sjdp pop_insert (potable); 47533965Sjdp} 47633965Sjdp 47733965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY() \ 47833965Sjdp if (ignore_input ()) \ 47933965Sjdp { \ 48077298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer++]) \ 48133965Sjdp if (input_line_pointer == buffer_limit) \ 48233965Sjdp break; \ 48333965Sjdp continue; \ 48433965Sjdp } 48533965Sjdp 48633965Sjdp/* This function is used when scrubbing the characters between #APP 48733965Sjdp and #NO_APP. */ 48833965Sjdp 48933965Sjdpstatic char *scrub_string; 49033965Sjdpstatic char *scrub_string_end; 49133965Sjdp 49233965Sjdpstatic int 49360484Sobrienscrub_from_string (buf, buflen) 49460484Sobrien char *buf; 49560484Sobrien int buflen; 49633965Sjdp{ 49760484Sobrien int copy; 49833965Sjdp 49960484Sobrien copy = scrub_string_end - scrub_string; 50060484Sobrien if (copy > buflen) 50160484Sobrien copy = buflen; 50260484Sobrien memcpy (buf, scrub_string, copy); 50360484Sobrien scrub_string += copy; 50460484Sobrien return copy; 50533965Sjdp} 50633965Sjdp 50777298Sobrien/* We read the file, putting things into a web that represents what we 50877298Sobrien have been reading. */ 50977298Sobrienvoid 51033965Sjdpread_a_source_file (name) 51133965Sjdp char *name; 51233965Sjdp{ 51333965Sjdp register char c; 51477298Sobrien register char *s; /* String of symbol, '\0' appended. */ 51533965Sjdp register int temp; 51633965Sjdp pseudo_typeS *pop; 51733965Sjdp 51877298Sobrien#ifdef WARN_COMMENTS 51977298Sobrien found_comment = 0; 52077298Sobrien#endif 52177298Sobrien 52233965Sjdp buffer = input_scrub_new_file (name); 52333965Sjdp 52433965Sjdp listing_file (name); 52538889Sjdp listing_newline (NULL); 52638889Sjdp register_dependency (name); 52733965Sjdp 52860484Sobrien /* Generate debugging information before we've read anything in to denote 52960484Sobrien this file as the "main" source file and not a subordinate one 53060484Sobrien (e.g. N_SO vs N_SOL in stabs). */ 53160484Sobrien generate_file_debug (); 53260484Sobrien 53333965Sjdp while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0) 53477298Sobrien { /* We have another line to parse. */ 53577298Sobrien know (buffer_limit[-1] == '\n'); /* Must have a sentinel. */ 53633965Sjdp contin: /* JF this goto is my fault I admit it. 53733965Sjdp Someone brave please re-write the whole 53833965Sjdp input section here? Pleeze??? */ 53933965Sjdp while (input_line_pointer < buffer_limit) 54033965Sjdp { 54177298Sobrien /* We have more of this buffer to parse. */ 54233965Sjdp 54377298Sobrien /* We now have input_line_pointer->1st char of next line. 54477298Sobrien If input_line_pointer [-1] == '\n' then we just 54577298Sobrien scanned another line: so bump line counters. */ 54633965Sjdp if (is_end_of_line[(unsigned char) input_line_pointer[-1]]) 54733965Sjdp { 54833965Sjdp#ifdef md_start_line_hook 54933965Sjdp md_start_line_hook (); 55033965Sjdp#endif 55133965Sjdp if (input_line_pointer[-1] == '\n') 55233965Sjdp bump_line_counters (); 55333965Sjdp 55433965Sjdp line_label = NULL; 55533965Sjdp 55660484Sobrien if (LABELS_WITHOUT_COLONS || flag_m68k_mri) 55733965Sjdp { 55833965Sjdp /* Text at the start of a line must be a label, we 55933965Sjdp run down and stick a colon in. */ 56033965Sjdp if (is_name_beginner (*input_line_pointer)) 56133965Sjdp { 56233965Sjdp char *line_start = input_line_pointer; 56333965Sjdp char c; 56433965Sjdp int mri_line_macro; 56533965Sjdp 56633965Sjdp LISTING_NEWLINE (); 56733965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 56833965Sjdp 56933965Sjdp c = get_symbol_end (); 57033965Sjdp 57133965Sjdp /* In MRI mode, the EQU and MACRO pseudoops must 57233965Sjdp be handled specially. */ 57333965Sjdp mri_line_macro = 0; 57433965Sjdp if (flag_m68k_mri) 57533965Sjdp { 57633965Sjdp char *rest = input_line_pointer + 1; 57733965Sjdp 57833965Sjdp if (*rest == ':') 57933965Sjdp ++rest; 58033965Sjdp if (*rest == ' ' || *rest == '\t') 58133965Sjdp ++rest; 58233965Sjdp if ((strncasecmp (rest, "EQU", 3) == 0 58333965Sjdp || strncasecmp (rest, "SET", 3) == 0) 58433965Sjdp && (rest[3] == ' ' || rest[3] == '\t')) 58533965Sjdp { 58633965Sjdp input_line_pointer = rest + 3; 58733965Sjdp equals (line_start, 58833965Sjdp strncasecmp (rest, "SET", 3) == 0); 58933965Sjdp continue; 59033965Sjdp } 59133965Sjdp if (strncasecmp (rest, "MACRO", 5) == 0 59233965Sjdp && (rest[5] == ' ' 59333965Sjdp || rest[5] == '\t' 59433965Sjdp || is_end_of_line[(unsigned char) rest[5]])) 59533965Sjdp mri_line_macro = 1; 59633965Sjdp } 59733965Sjdp 59833965Sjdp /* In MRI mode, we need to handle the MACRO 59933965Sjdp pseudo-op specially: we don't want to put the 60033965Sjdp symbol in the symbol table. */ 60177298Sobrien if (!mri_line_macro 60260484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON 60377298Sobrien && TC_START_LABEL_WITHOUT_COLON(c, 60477298Sobrien input_line_pointer) 60560484Sobrien#endif 60677298Sobrien ) 60733965Sjdp line_label = colon (line_start); 60833965Sjdp else 60933965Sjdp line_label = symbol_create (line_start, 61033965Sjdp absolute_section, 61133965Sjdp (valueT) 0, 61233965Sjdp &zero_address_frag); 61333965Sjdp 61433965Sjdp *input_line_pointer = c; 61533965Sjdp if (c == ':') 61633965Sjdp input_line_pointer++; 61733965Sjdp } 61833965Sjdp } 61933965Sjdp } 62033965Sjdp 62177298Sobrien /* We are at the begining of a line, or similar place. 62277298Sobrien We expect a well-formed assembler statement. 62377298Sobrien A "symbol-name:" is a statement. 62477298Sobrien 62577298Sobrien Depending on what compiler is used, the order of these tests 62677298Sobrien may vary to catch most common case 1st. 62777298Sobrien Each test is independent of all other tests at the (top) level. 62877298Sobrien PLEASE make a compiler that doesn't use this assembler. 62977298Sobrien It is crufty to waste a compiler's time encoding things for this 63077298Sobrien assembler, which then wastes more time decoding it. 63177298Sobrien (And communicating via (linear) files is silly! 63277298Sobrien If you must pass stuff, please pass a tree!) */ 63333965Sjdp if ((c = *input_line_pointer++) == '\t' 63433965Sjdp || c == ' ' 63533965Sjdp || c == '\f' 63633965Sjdp || c == 0) 63777298Sobrien c = *input_line_pointer++; 63838889Sjdp 63977298Sobrien know (c != ' '); /* No further leading whitespace. */ 64077298Sobrien 64138889Sjdp#ifndef NO_LISTING 64238889Sjdp /* If listing is on, and we are expanding a macro, then give 64338889Sjdp the listing code the contents of the expanded line. */ 64438889Sjdp if (listing) 64538889Sjdp { 64638889Sjdp if ((listing & LISTING_MACEXP) && macro_nest > 0) 64738889Sjdp { 64838889Sjdp char *copy; 64938889Sjdp int len; 65038889Sjdp 65138889Sjdp /* Find the end of the current expanded macro line. */ 65277298Sobrien for (s = input_line_pointer - 1; *s; ++s) 65338889Sjdp if (is_end_of_line[(unsigned char) *s]) 65438889Sjdp break; 65538889Sjdp 65638889Sjdp /* Copy it for safe keeping. Also give an indication of 65738889Sjdp how much macro nesting is involved at this point. */ 65877298Sobrien len = s - (input_line_pointer - 1); 65938889Sjdp copy = (char *) xmalloc (len + macro_nest + 2); 66038889Sjdp memset (copy, '>', macro_nest); 66138889Sjdp copy[macro_nest] = ' '; 66277298Sobrien memcpy (copy + macro_nest + 1, input_line_pointer - 1, len); 66377298Sobrien copy[macro_nest + 1 + len] = '\0'; 66438889Sjdp 66538889Sjdp /* Install the line with the listing facility. */ 66638889Sjdp listing_newline (copy); 66738889Sjdp } 66838889Sjdp else 66938889Sjdp listing_newline (NULL); 67038889Sjdp } 67138889Sjdp#endif 67277298Sobrien /* C is the 1st significant character. 67377298Sobrien Input_line_pointer points after that character. */ 67433965Sjdp if (is_name_beginner (c)) 67533965Sjdp { 67677298Sobrien /* Want user-defined label or pseudo/opcode. */ 67733965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 67833965Sjdp 67933965Sjdp s = --input_line_pointer; 68077298Sobrien c = get_symbol_end (); /* name's delimiter. */ 68177298Sobrien 68277298Sobrien /* C is character after symbol. 68377298Sobrien That character's place in the input line is now '\0'. 68477298Sobrien S points to the beginning of the symbol. 68577298Sobrien [In case of pseudo-op, s->'.'.] 68677298Sobrien Input_line_pointer->'\0' where c was. */ 68777298Sobrien if (TC_START_LABEL (c, input_line_pointer)) 68833965Sjdp { 68933965Sjdp if (flag_m68k_mri) 69033965Sjdp { 69133965Sjdp char *rest = input_line_pointer + 1; 69233965Sjdp 69333965Sjdp /* In MRI mode, \tsym: set 0 is permitted. */ 69433965Sjdp if (*rest == ':') 69533965Sjdp ++rest; 69677298Sobrien 69733965Sjdp if (*rest == ' ' || *rest == '\t') 69833965Sjdp ++rest; 69977298Sobrien 70033965Sjdp if ((strncasecmp (rest, "EQU", 3) == 0 70133965Sjdp || strncasecmp (rest, "SET", 3) == 0) 70233965Sjdp && (rest[3] == ' ' || rest[3] == '\t')) 70333965Sjdp { 70433965Sjdp input_line_pointer = rest + 3; 70533965Sjdp equals (s, 1); 70633965Sjdp continue; 70733965Sjdp } 70833965Sjdp } 70933965Sjdp 71077298Sobrien line_label = colon (s); /* User-defined label. */ 71177298Sobrien /* Put ':' back for error messages' sake. */ 71277298Sobrien *input_line_pointer++ = ':'; 71377298Sobrien /* Input_line_pointer->after ':'. */ 71433965Sjdp SKIP_WHITESPACE (); 71533965Sjdp } 71633965Sjdp else if (c == '=' 71733965Sjdp || ((c == ' ' || c == '\t') 71833965Sjdp && input_line_pointer[1] == '=' 71933965Sjdp#ifdef TC_EQUAL_IN_INSN 72077298Sobrien && !TC_EQUAL_IN_INSN (c, input_line_pointer) 72133965Sjdp#endif 72233965Sjdp )) 72333965Sjdp { 72433965Sjdp equals (s, 1); 72533965Sjdp demand_empty_rest_of_line (); 72633965Sjdp } 72733965Sjdp else 72877298Sobrien { 72977298Sobrien /* Expect pseudo-op or machine instruction. */ 73033965Sjdp pop = NULL; 73133965Sjdp 73233965Sjdp#ifdef IGNORE_OPCODE_CASE 73333965Sjdp { 73433965Sjdp char *s2 = s; 73577298Sobrien 73677298Sobrien strncpy (original_case_string, s2, sizeof (original_case_string)); 73777298Sobrien original_case_string[sizeof (original_case_string) - 1] = 0; 73877298Sobrien 73933965Sjdp while (*s2) 74033965Sjdp { 74189857Sobrien *s2 = TOLOWER (*s2); 74233965Sjdp s2++; 74333965Sjdp } 74433965Sjdp } 74533965Sjdp#endif 74660484Sobrien if (NO_PSEUDO_DOT || flag_m68k_mri) 74733965Sjdp { 74833965Sjdp /* The MRI assembler and the m88k use pseudo-ops 74933965Sjdp without a period. */ 75033965Sjdp pop = (pseudo_typeS *) hash_find (po_hash, s); 75133965Sjdp if (pop != NULL && pop->poc_handler == NULL) 75233965Sjdp pop = NULL; 75333965Sjdp } 75433965Sjdp 75533965Sjdp if (pop != NULL 75677298Sobrien || (!flag_m68k_mri && *s == '.')) 75733965Sjdp { 75877298Sobrien /* PSEUDO - OP. 75933965Sjdp 76077298Sobrien WARNING: c has next char, which may be end-of-line. 76177298Sobrien We lookup the pseudo-op table with s+1 because we 76277298Sobrien already know that the pseudo-op begins with a '.'. */ 76377298Sobrien 76433965Sjdp if (pop == NULL) 76533965Sjdp pop = (pseudo_typeS *) hash_find (po_hash, s + 1); 76633965Sjdp 76733965Sjdp /* In MRI mode, we may need to insert an 76833965Sjdp automatic alignment directive. What a hack 76933965Sjdp this is. */ 77033965Sjdp if (mri_pending_align 77133965Sjdp && (pop == NULL 77277298Sobrien || !((pop->poc_handler == cons 77377298Sobrien && pop->poc_val == 1) 77477298Sobrien || (pop->poc_handler == s_space 77577298Sobrien && pop->poc_val == 1) 77633965Sjdp#ifdef tc_conditional_pseudoop 77777298Sobrien || tc_conditional_pseudoop (pop) 77833965Sjdp#endif 77977298Sobrien || pop->poc_handler == s_if 78077298Sobrien || pop->poc_handler == s_ifdef 78177298Sobrien || pop->poc_handler == s_ifc 78277298Sobrien || pop->poc_handler == s_ifeqs 78377298Sobrien || pop->poc_handler == s_else 78477298Sobrien || pop->poc_handler == s_endif 78577298Sobrien || pop->poc_handler == s_globl 78677298Sobrien || pop->poc_handler == s_ignore))) 78733965Sjdp { 78833965Sjdp do_align (1, (char *) NULL, 0, 0); 78933965Sjdp mri_pending_align = 0; 79077298Sobrien 79133965Sjdp if (line_label != NULL) 79233965Sjdp { 79360484Sobrien symbol_set_frag (line_label, frag_now); 79433965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 79533965Sjdp } 79633965Sjdp } 79733965Sjdp 79877298Sobrien /* Print the error msg now, while we still can. */ 79933965Sjdp if (pop == NULL) 80033965Sjdp { 80189857Sobrien as_bad (_("unknown pseudo-op: `%s'"), s); 80233965Sjdp *input_line_pointer = c; 80333965Sjdp s_ignore (0); 80433965Sjdp continue; 80533965Sjdp } 80633965Sjdp 80777298Sobrien /* Put it back for error messages etc. */ 80833965Sjdp *input_line_pointer = c; 80933965Sjdp /* The following skip of whitespace is compulsory. 81033965Sjdp A well shaped space is sometimes all that separates 81177298Sobrien keyword from operands. */ 81233965Sjdp if (c == ' ' || c == '\t') 81333965Sjdp input_line_pointer++; 81477298Sobrien 81577298Sobrien /* Input_line is restored. 81677298Sobrien Input_line_pointer->1st non-blank char 81777298Sobrien after pseudo-operation. */ 81833965Sjdp (*pop->poc_handler) (pop->poc_val); 81933965Sjdp 82033965Sjdp /* If that was .end, just get out now. */ 82133965Sjdp if (pop->poc_handler == s_end) 82233965Sjdp goto quit; 82333965Sjdp } 82433965Sjdp else 82533965Sjdp { 82633965Sjdp int inquote = 0; 82760484Sobrien#ifdef QUOTES_IN_INSN 82860484Sobrien int inescape = 0; 82960484Sobrien#endif 83033965Sjdp 83177298Sobrien /* WARNING: c has char, which may be end-of-line. */ 83277298Sobrien /* Also: input_line_pointer->`\0` where c was. */ 83333965Sjdp *input_line_pointer = c; 83433965Sjdp while (!is_end_of_line[(unsigned char) *input_line_pointer] 83533965Sjdp || inquote 83633965Sjdp#ifdef TC_EOL_IN_INSN 83733965Sjdp || TC_EOL_IN_INSN (input_line_pointer) 83833965Sjdp#endif 83933965Sjdp ) 84033965Sjdp { 84133965Sjdp if (flag_m68k_mri && *input_line_pointer == '\'') 84277298Sobrien inquote = !inquote; 84360484Sobrien#ifdef QUOTES_IN_INSN 84460484Sobrien if (inescape) 84560484Sobrien inescape = 0; 84660484Sobrien else if (*input_line_pointer == '"') 84777298Sobrien inquote = !inquote; 84860484Sobrien else if (*input_line_pointer == '\\') 84960484Sobrien inescape = 1; 85060484Sobrien#endif 85133965Sjdp input_line_pointer++; 85233965Sjdp } 85333965Sjdp 85433965Sjdp c = *input_line_pointer; 85533965Sjdp *input_line_pointer = '\0'; 85633965Sjdp 85760484Sobrien generate_lineno_debug (); 85838889Sjdp 85933965Sjdp if (macro_defined) 86033965Sjdp { 86133965Sjdp sb out; 86233965Sjdp const char *err; 86377298Sobrien macro_entry *macro; 86433965Sjdp 86560484Sobrien if (check_macro (s, &out, '\0', &err, ¯o)) 86633965Sjdp { 86733965Sjdp if (err != NULL) 86860484Sobrien as_bad ("%s", err); 86933965Sjdp *input_line_pointer++ = c; 87033965Sjdp input_scrub_include_sb (&out, 87160484Sobrien input_line_pointer, 1); 87233965Sjdp sb_kill (&out); 87333965Sjdp buffer_limit = 87433965Sjdp input_scrub_next_buffer (&input_line_pointer); 87560484Sobrien#ifdef md_macro_info 87677298Sobrien md_macro_info (macro); 87760484Sobrien#endif 87833965Sjdp continue; 87933965Sjdp } 88033965Sjdp } 88133965Sjdp 88233965Sjdp if (mri_pending_align) 88333965Sjdp { 88433965Sjdp do_align (1, (char *) NULL, 0, 0); 88533965Sjdp mri_pending_align = 0; 88633965Sjdp if (line_label != NULL) 88733965Sjdp { 88860484Sobrien symbol_set_frag (line_label, frag_now); 88933965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 89033965Sjdp } 89133965Sjdp } 89233965Sjdp 89377298Sobrien md_assemble (s); /* Assemble 1 instruction. */ 89433965Sjdp 89533965Sjdp *input_line_pointer++ = c; 89633965Sjdp 89733965Sjdp /* We resume loop AFTER the end-of-line from 89877298Sobrien this instruction. */ 89977298Sobrien } 90077298Sobrien } 90133965Sjdp continue; 90277298Sobrien } 90333965Sjdp 90433965Sjdp /* Empty statement? */ 90533965Sjdp if (is_end_of_line[(unsigned char) c]) 90633965Sjdp continue; 90733965Sjdp 90889857Sobrien if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c)) 90933965Sjdp { 91077298Sobrien /* local label ("4:") */ 91133965Sjdp char *backup = input_line_pointer; 91233965Sjdp 91333965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 91433965Sjdp 91533965Sjdp temp = c - '0'; 91633965Sjdp 91777298Sobrien /* Read the whole number. */ 91889857Sobrien while (ISDIGIT (*input_line_pointer)) 91933965Sjdp { 92033965Sjdp temp = (temp * 10) + *input_line_pointer - '0'; 92133965Sjdp ++input_line_pointer; 92277298Sobrien } 92333965Sjdp 92433965Sjdp if (LOCAL_LABELS_DOLLAR 92533965Sjdp && *input_line_pointer == '$' 92633965Sjdp && *(input_line_pointer + 1) == ':') 92733965Sjdp { 92833965Sjdp input_line_pointer += 2; 92933965Sjdp 93033965Sjdp if (dollar_label_defined (temp)) 93133965Sjdp { 93260484Sobrien as_fatal (_("label \"%d$\" redefined"), temp); 93333965Sjdp } 93433965Sjdp 93533965Sjdp define_dollar_label (temp); 93633965Sjdp colon (dollar_label_name (temp, 0)); 93733965Sjdp continue; 93833965Sjdp } 93933965Sjdp 94033965Sjdp if (LOCAL_LABELS_FB 94133965Sjdp && *input_line_pointer++ == ':') 94233965Sjdp { 94333965Sjdp fb_label_instance_inc (temp); 94433965Sjdp colon (fb_label_name (temp, 0)); 94533965Sjdp continue; 94633965Sjdp } 94733965Sjdp 94833965Sjdp input_line_pointer = backup; 94933965Sjdp } /* local label ("4:") */ 95033965Sjdp 95133965Sjdp if (c && strchr (line_comment_chars, c)) 95277298Sobrien { /* Its a comment. Better say APP or NO_APP. */ 95333965Sjdp char *ends; 95433965Sjdp char *new_buf; 95533965Sjdp char *new_tmp; 95633965Sjdp unsigned int new_length; 95733965Sjdp char *tmp_buf = 0; 95833965Sjdp 95933965Sjdp bump_line_counters (); 96033965Sjdp s = input_line_pointer; 96133965Sjdp if (strncmp (s, "APP\n", 4)) 96233965Sjdp continue; /* We ignore it */ 96333965Sjdp s += 4; 96433965Sjdp 96533965Sjdp ends = strstr (s, "#NO_APP\n"); 96633965Sjdp 96733965Sjdp if (!ends) 96833965Sjdp { 96933965Sjdp unsigned int tmp_len; 97033965Sjdp unsigned int num; 97133965Sjdp 97233965Sjdp /* The end of the #APP wasn't in this buffer. We 97333965Sjdp keep reading in buffers until we find the #NO_APP 97433965Sjdp that goes with this #APP There is one. The specs 97577298Sobrien guarentee it... */ 97633965Sjdp tmp_len = buffer_limit - s; 97733965Sjdp tmp_buf = xmalloc (tmp_len + 1); 97833965Sjdp memcpy (tmp_buf, s, tmp_len); 97933965Sjdp do 98033965Sjdp { 98133965Sjdp new_tmp = input_scrub_next_buffer (&buffer); 98233965Sjdp if (!new_tmp) 98333965Sjdp break; 98433965Sjdp else 98533965Sjdp buffer_limit = new_tmp; 98633965Sjdp input_line_pointer = buffer; 98733965Sjdp ends = strstr (buffer, "#NO_APP\n"); 98833965Sjdp if (ends) 98933965Sjdp num = ends - buffer; 99033965Sjdp else 99133965Sjdp num = buffer_limit - buffer; 99233965Sjdp 99333965Sjdp tmp_buf = xrealloc (tmp_buf, tmp_len + num); 99433965Sjdp memcpy (tmp_buf + tmp_len, buffer, num); 99533965Sjdp tmp_len += num; 99633965Sjdp } 99733965Sjdp while (!ends); 99833965Sjdp 99933965Sjdp input_line_pointer = ends ? ends + 8 : NULL; 100033965Sjdp 100133965Sjdp s = tmp_buf; 100233965Sjdp ends = s + tmp_len; 100333965Sjdp 100433965Sjdp } 100533965Sjdp else 100633965Sjdp { 100733965Sjdp input_line_pointer = ends + 8; 100833965Sjdp } 100933965Sjdp 101033965Sjdp scrub_string = s; 101133965Sjdp scrub_string_end = ends; 101233965Sjdp 101333965Sjdp new_length = ends - s; 101433965Sjdp new_buf = (char *) xmalloc (new_length); 101533965Sjdp new_tmp = new_buf; 101633965Sjdp for (;;) 101733965Sjdp { 101833965Sjdp int space; 101933965Sjdp int size; 102033965Sjdp 102133965Sjdp space = (new_buf + new_length) - new_tmp; 102233965Sjdp size = do_scrub_chars (scrub_from_string, new_tmp, space); 102333965Sjdp 102433965Sjdp if (size < space) 102533965Sjdp { 102633965Sjdp new_tmp += size; 102733965Sjdp break; 102833965Sjdp } 102933965Sjdp 103033965Sjdp new_buf = xrealloc (new_buf, new_length + 100); 103133965Sjdp new_tmp = new_buf + new_length; 103233965Sjdp new_length += 100; 103333965Sjdp } 103433965Sjdp 103533965Sjdp if (tmp_buf) 103633965Sjdp free (tmp_buf); 103733965Sjdp old_buffer = buffer; 103833965Sjdp old_input = input_line_pointer; 103933965Sjdp old_limit = buffer_limit; 104033965Sjdp buffer = new_buf; 104133965Sjdp input_line_pointer = new_buf; 104233965Sjdp buffer_limit = new_tmp; 104377298Sobrien 104433965Sjdp continue; 104533965Sjdp } 104633965Sjdp 104733965Sjdp HANDLE_CONDITIONAL_ASSEMBLY (); 104833965Sjdp 104933965Sjdp#ifdef tc_unrecognized_line 105033965Sjdp if (tc_unrecognized_line (c)) 105133965Sjdp continue; 105233965Sjdp#endif 105389857Sobrien input_line_pointer--; 105489857Sobrien /* Report unknown char as ignored. */ 105533965Sjdp ignore_rest_of_line (); 105677298Sobrien } 105733965Sjdp 105833965Sjdp#ifdef md_after_pass_hook 105933965Sjdp md_after_pass_hook (); 106033965Sjdp#endif 106133965Sjdp 106233965Sjdp if (old_buffer) 106333965Sjdp { 106433965Sjdp free (buffer); 106533965Sjdp bump_line_counters (); 106633965Sjdp if (old_input != 0) 106733965Sjdp { 106833965Sjdp buffer = old_buffer; 106933965Sjdp input_line_pointer = old_input; 107033965Sjdp buffer_limit = old_limit; 107133965Sjdp old_buffer = 0; 107233965Sjdp goto contin; 107333965Sjdp } 107433965Sjdp } 107577298Sobrien } 107633965Sjdp 107733965Sjdp quit: 107833965Sjdp 107933965Sjdp#ifdef md_cleanup 108077298Sobrien md_cleanup (); 108133965Sjdp#endif 108277298Sobrien /* Close the input file. */ 108377298Sobrien input_scrub_close (); 108477298Sobrien#ifdef WARN_COMMENTS 108577298Sobrien { 108677298Sobrien if (warn_comment && found_comment) 108777298Sobrien as_warn_where (found_comment_file, found_comment, 108877298Sobrien "first comment found here"); 108977298Sobrien } 109077298Sobrien#endif 109133965Sjdp} 109233965Sjdp 109333965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first 109433965Sjdp nonquoted space. This function looks for that point, stuffs a null 109533965Sjdp in, and sets *STOPCP to the character that used to be there, and 109633965Sjdp returns the location. 109733965Sjdp 109833965Sjdp Until I hear otherwise, I am going to assume that this is only true 109933965Sjdp for the m68k MRI assembler. */ 110033965Sjdp 110133965Sjdpchar * 110233965Sjdpmri_comment_field (stopcp) 110333965Sjdp char *stopcp; 110433965Sjdp{ 110577298Sobrien char *s; 110633965Sjdp#ifdef TC_M68K 110733965Sjdp int inquote = 0; 110833965Sjdp 110933965Sjdp know (flag_m68k_mri); 111033965Sjdp 111133965Sjdp for (s = input_line_pointer; 111277298Sobrien ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t') 111333965Sjdp || inquote); 111433965Sjdp s++) 111533965Sjdp { 111633965Sjdp if (*s == '\'') 111777298Sobrien inquote = !inquote; 111833965Sjdp } 111933965Sjdp#else 112077298Sobrien for (s = input_line_pointer; 112177298Sobrien !is_end_of_line[(unsigned char) *s]; 112277298Sobrien s++) 112333965Sjdp ; 112477298Sobrien#endif 112533965Sjdp *stopcp = *s; 112633965Sjdp *s = '\0'; 112777298Sobrien 112833965Sjdp return s; 112933965Sjdp} 113033965Sjdp 113133965Sjdp/* Skip to the end of an MRI comment field. */ 113233965Sjdp 113333965Sjdpvoid 113433965Sjdpmri_comment_end (stop, stopc) 113533965Sjdp char *stop; 113633965Sjdp int stopc; 113733965Sjdp{ 113833965Sjdp know (flag_mri); 113933965Sjdp 114033965Sjdp input_line_pointer = stop; 114133965Sjdp *stop = stopc; 114277298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 114333965Sjdp ++input_line_pointer; 114433965Sjdp} 114533965Sjdp 114677298Sobrienvoid 114733965Sjdps_abort (ignore) 114860484Sobrien int ignore ATTRIBUTE_UNUSED; 114933965Sjdp{ 115060484Sobrien as_fatal (_(".abort detected. Abandoning ship.")); 115133965Sjdp} 115233965Sjdp 115333965Sjdp/* Guts of .align directive. N is the power of two to which to align. 115433965Sjdp FILL may be NULL, or it may point to the bytes of the fill pattern. 115533965Sjdp LEN is the length of whatever FILL points to, if anything. MAX is 115633965Sjdp the maximum number of characters to skip when doing the alignment, 115733965Sjdp or 0 if there is no maximum. */ 115833965Sjdp 115977298Sobrienstatic void 116033965Sjdpdo_align (n, fill, len, max) 116133965Sjdp int n; 116233965Sjdp char *fill; 116333965Sjdp int len; 116433965Sjdp int max; 116533965Sjdp{ 116689857Sobrien if (now_seg == absolute_section) 116789857Sobrien { 116889857Sobrien if (fill != NULL) 116989857Sobrien while (len-- > 0) 117089857Sobrien if (*fill++ != '\0') 117189857Sobrien { 117289857Sobrien as_warn (_("ignoring fill value in absolute section")); 117389857Sobrien break; 117489857Sobrien } 117589857Sobrien fill = NULL; 117689857Sobrien len = 0; 117789857Sobrien } 117889857Sobrien 117933965Sjdp#ifdef md_do_align 118033965Sjdp md_do_align (n, fill, len, max, just_record_alignment); 118133965Sjdp#endif 118233965Sjdp 118377298Sobrien /* Only make a frag if we HAVE to... */ 118433965Sjdp if (n != 0 && !need_pass_2) 118533965Sjdp { 118677298Sobrien if (fill == NULL) 118777298Sobrien { 118877298Sobrien if (subseg_text_p (now_seg)) 118977298Sobrien frag_align_code (n, max); 119077298Sobrien else 119177298Sobrien frag_align (n, 0, max); 119277298Sobrien } 119377298Sobrien else if (len <= 1) 119433965Sjdp frag_align (n, *fill, max); 119533965Sjdp else 119633965Sjdp frag_align_pattern (n, fill, len, max); 119733965Sjdp } 119833965Sjdp 119933965Sjdp#ifdef md_do_align 120033965Sjdp just_record_alignment: 120133965Sjdp#endif 120233965Sjdp 120360484Sobrien record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER); 120433965Sjdp} 120533965Sjdp 120633965Sjdp/* Handle the .align pseudo-op. A positive ARG is a default alignment 120733965Sjdp (in bytes). A negative ARG is the negative of the length of the 120833965Sjdp fill pattern. BYTES_P is non-zero if the alignment value should be 120933965Sjdp interpreted as the byte boundary, rather than the power of 2. */ 121033965Sjdp 121133965Sjdpstatic void 121233965Sjdps_align (arg, bytes_p) 121333965Sjdp int arg; 121433965Sjdp int bytes_p; 121533965Sjdp{ 121633965Sjdp register unsigned int align; 121733965Sjdp char *stop = NULL; 121833965Sjdp char stopc; 121933965Sjdp offsetT fill = 0; 122033965Sjdp int max; 122133965Sjdp int fill_p; 122233965Sjdp 122333965Sjdp if (flag_mri) 122433965Sjdp stop = mri_comment_field (&stopc); 122533965Sjdp 122633965Sjdp if (is_end_of_line[(unsigned char) *input_line_pointer]) 122733965Sjdp { 122833965Sjdp if (arg < 0) 122933965Sjdp align = 0; 123033965Sjdp else 123177298Sobrien align = arg; /* Default value from pseudo-op table. */ 123233965Sjdp } 123333965Sjdp else 123433965Sjdp { 123533965Sjdp align = get_absolute_expression (); 123633965Sjdp SKIP_WHITESPACE (); 123733965Sjdp } 123833965Sjdp 123933965Sjdp if (bytes_p) 124033965Sjdp { 124133965Sjdp /* Convert to a power of 2. */ 124233965Sjdp if (align != 0) 124333965Sjdp { 124433965Sjdp unsigned int i; 124533965Sjdp 124633965Sjdp for (i = 0; (align & 1) == 0; align >>= 1, ++i) 124733965Sjdp ; 124833965Sjdp if (align != 1) 124989857Sobrien as_bad (_("alignment not a power of 2")); 125077298Sobrien 125133965Sjdp align = i; 125233965Sjdp } 125333965Sjdp } 125433965Sjdp 125533965Sjdp if (align > 15) 125633965Sjdp { 125733965Sjdp align = 15; 125889857Sobrien as_warn (_("alignment too large: %u assumed"), align); 125933965Sjdp } 126033965Sjdp 126133965Sjdp if (*input_line_pointer != ',') 126233965Sjdp { 126333965Sjdp fill_p = 0; 126433965Sjdp max = 0; 126533965Sjdp } 126633965Sjdp else 126733965Sjdp { 126833965Sjdp ++input_line_pointer; 126933965Sjdp if (*input_line_pointer == ',') 127033965Sjdp fill_p = 0; 127133965Sjdp else 127233965Sjdp { 127333965Sjdp fill = get_absolute_expression (); 127433965Sjdp SKIP_WHITESPACE (); 127533965Sjdp fill_p = 1; 127633965Sjdp } 127733965Sjdp 127833965Sjdp if (*input_line_pointer != ',') 127933965Sjdp max = 0; 128033965Sjdp else 128133965Sjdp { 128233965Sjdp ++input_line_pointer; 128333965Sjdp max = get_absolute_expression (); 128433965Sjdp } 128533965Sjdp } 128633965Sjdp 128777298Sobrien if (!fill_p) 128833965Sjdp { 128933965Sjdp if (arg < 0) 129060484Sobrien as_warn (_("expected fill pattern missing")); 129133965Sjdp do_align (align, (char *) NULL, 0, max); 129233965Sjdp } 129333965Sjdp else 129433965Sjdp { 129533965Sjdp int fill_len; 129633965Sjdp 129733965Sjdp if (arg >= 0) 129833965Sjdp fill_len = 1; 129933965Sjdp else 130077298Sobrien fill_len = -arg; 130133965Sjdp if (fill_len <= 1) 130233965Sjdp { 130333965Sjdp char fill_char; 130433965Sjdp 130533965Sjdp fill_char = fill; 130633965Sjdp do_align (align, &fill_char, fill_len, max); 130733965Sjdp } 130833965Sjdp else 130933965Sjdp { 131033965Sjdp char ab[16]; 131133965Sjdp 131238889Sjdp if ((size_t) fill_len > sizeof ab) 131333965Sjdp abort (); 131433965Sjdp md_number_to_chars (ab, fill, fill_len); 131533965Sjdp do_align (align, ab, fill_len, max); 131633965Sjdp } 131733965Sjdp } 131833965Sjdp 131960484Sobrien demand_empty_rest_of_line (); 132060484Sobrien 132133965Sjdp if (flag_mri) 132233965Sjdp mri_comment_end (stop, stopc); 132333965Sjdp} 132433965Sjdp 132533965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means 132633965Sjdp align to a 4 byte boundary. */ 132733965Sjdp 132877298Sobrienvoid 132933965Sjdps_align_bytes (arg) 133033965Sjdp int arg; 133133965Sjdp{ 133233965Sjdp s_align (arg, 1); 133333965Sjdp} 133433965Sjdp 133538889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align 133633965Sjdp to a 2**4 boundary. */ 133733965Sjdp 133877298Sobrienvoid 133933965Sjdps_align_ptwo (arg) 134033965Sjdp int arg; 134133965Sjdp{ 134233965Sjdp s_align (arg, 0); 134333965Sjdp} 134433965Sjdp 134577298Sobrienvoid 134633965Sjdps_comm (ignore) 134760484Sobrien int ignore ATTRIBUTE_UNUSED; 134833965Sjdp{ 134933965Sjdp register char *name; 135033965Sjdp register char c; 135133965Sjdp register char *p; 135233965Sjdp offsetT temp; 135333965Sjdp register symbolS *symbolP; 135433965Sjdp char *stop = NULL; 135533965Sjdp char stopc; 135633965Sjdp 135733965Sjdp if (flag_mri) 135833965Sjdp stop = mri_comment_field (&stopc); 135933965Sjdp 136033965Sjdp name = input_line_pointer; 136133965Sjdp c = get_symbol_end (); 136277298Sobrien /* Just after name is now '\0'. */ 136333965Sjdp p = input_line_pointer; 136433965Sjdp *p = c; 136589857Sobrien 136689857Sobrien if (name == p) 136789857Sobrien { 136889857Sobrien as_bad (_("expected symbol name")); 136989857Sobrien discard_rest_of_line (); 137089857Sobrien return; 137189857Sobrien } 137289857Sobrien 137333965Sjdp SKIP_WHITESPACE (); 137477298Sobrien 137533965Sjdp if (*input_line_pointer != ',') 137633965Sjdp { 137789857Sobrien *p = 0; 137889857Sobrien as_bad (_("expected comma after \"%s\""), name); 137989857Sobrien *p = c; 138060484Sobrien ignore_rest_of_line (); 138133965Sjdp if (flag_mri) 138233965Sjdp mri_comment_end (stop, stopc); 138333965Sjdp return; 138433965Sjdp } 138577298Sobrien 138633965Sjdp input_line_pointer++; /* skip ',' */ 138777298Sobrien 138833965Sjdp if ((temp = get_absolute_expression ()) < 0) 138933965Sjdp { 139089857Sobrien as_warn (_(".COMMon length (%ld) < 0 ignored"), (long) temp); 139160484Sobrien ignore_rest_of_line (); 139233965Sjdp if (flag_mri) 139333965Sjdp mri_comment_end (stop, stopc); 139433965Sjdp return; 139533965Sjdp } 139677298Sobrien 139733965Sjdp *p = 0; 139833965Sjdp symbolP = symbol_find_or_make (name); 139933965Sjdp *p = c; 140077298Sobrien 140177298Sobrien if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP)) 140233965Sjdp { 140389857Sobrien as_bad (_("symbol `%s' is already defined"), 140433965Sjdp S_GET_NAME (symbolP)); 140560484Sobrien ignore_rest_of_line (); 140633965Sjdp if (flag_mri) 140733965Sjdp mri_comment_end (stop, stopc); 140833965Sjdp return; 140933965Sjdp } 141077298Sobrien 141133965Sjdp if (S_GET_VALUE (symbolP)) 141233965Sjdp { 141333965Sjdp if (S_GET_VALUE (symbolP) != (valueT) temp) 141489857Sobrien as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"), 141533965Sjdp S_GET_NAME (symbolP), 141633965Sjdp (long) S_GET_VALUE (symbolP), 141733965Sjdp (long) temp); 141833965Sjdp } 141933965Sjdp else 142033965Sjdp { 142133965Sjdp S_SET_VALUE (symbolP, (valueT) temp); 142233965Sjdp S_SET_EXTERNAL (symbolP); 142333965Sjdp } 142433965Sjdp#ifdef OBJ_VMS 142533965Sjdp { 142633965Sjdp extern int flag_one; 142777298Sobrien if (!temp || !flag_one) 142833965Sjdp S_GET_OTHER(symbolP) = const_flag; 142933965Sjdp } 143033965Sjdp#endif /* not OBJ_VMS */ 143133965Sjdp know (symbolP->sy_frag == &zero_address_frag); 143233965Sjdp 143360484Sobrien demand_empty_rest_of_line (); 143460484Sobrien 143533965Sjdp if (flag_mri) 143633965Sjdp mri_comment_end (stop, stopc); 143733965Sjdp} /* s_comm() */ 143833965Sjdp 143933965Sjdp/* The MRI COMMON pseudo-op. We handle this by creating a common 144033965Sjdp symbol with the appropriate name. We make s_space do the right 144133965Sjdp thing by increasing the size. */ 144233965Sjdp 144333965Sjdpvoid 144433965Sjdps_mri_common (small) 144560484Sobrien int small ATTRIBUTE_UNUSED; 144633965Sjdp{ 144733965Sjdp char *name; 144833965Sjdp char c; 144933965Sjdp char *alc = NULL; 145033965Sjdp symbolS *sym; 145133965Sjdp offsetT align; 145233965Sjdp char *stop = NULL; 145333965Sjdp char stopc; 145433965Sjdp 145577298Sobrien if (!flag_mri) 145633965Sjdp { 145733965Sjdp s_comm (0); 145833965Sjdp return; 145933965Sjdp } 146033965Sjdp 146133965Sjdp stop = mri_comment_field (&stopc); 146233965Sjdp 146333965Sjdp SKIP_WHITESPACE (); 146433965Sjdp 146533965Sjdp name = input_line_pointer; 146689857Sobrien if (!ISDIGIT (*name)) 146733965Sjdp c = get_symbol_end (); 146833965Sjdp else 146933965Sjdp { 147033965Sjdp do 147133965Sjdp { 147233965Sjdp ++input_line_pointer; 147333965Sjdp } 147489857Sobrien while (ISDIGIT (*input_line_pointer)); 147577298Sobrien 147633965Sjdp c = *input_line_pointer; 147733965Sjdp *input_line_pointer = '\0'; 147833965Sjdp 147933965Sjdp if (line_label != NULL) 148033965Sjdp { 148133965Sjdp alc = (char *) xmalloc (strlen (S_GET_NAME (line_label)) 148233965Sjdp + (input_line_pointer - name) 148333965Sjdp + 1); 148433965Sjdp sprintf (alc, "%s%s", name, S_GET_NAME (line_label)); 148533965Sjdp name = alc; 148633965Sjdp } 148733965Sjdp } 148833965Sjdp 148933965Sjdp sym = symbol_find_or_make (name); 149033965Sjdp *input_line_pointer = c; 149133965Sjdp if (alc != NULL) 149233965Sjdp free (alc); 149333965Sjdp 149433965Sjdp if (*input_line_pointer != ',') 149533965Sjdp align = 0; 149633965Sjdp else 149733965Sjdp { 149833965Sjdp ++input_line_pointer; 149933965Sjdp align = get_absolute_expression (); 150033965Sjdp } 150133965Sjdp 150277298Sobrien if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym)) 150333965Sjdp { 150489857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym)); 150560484Sobrien ignore_rest_of_line (); 150633965Sjdp mri_comment_end (stop, stopc); 150733965Sjdp return; 150833965Sjdp } 150933965Sjdp 151033965Sjdp S_SET_EXTERNAL (sym); 151133965Sjdp mri_common_symbol = sym; 151233965Sjdp 151333965Sjdp#ifdef S_SET_ALIGN 151433965Sjdp if (align != 0) 151533965Sjdp S_SET_ALIGN (sym, align); 151633965Sjdp#endif 151733965Sjdp 151833965Sjdp if (line_label != NULL) 151933965Sjdp { 152060484Sobrien expressionS exp; 152160484Sobrien exp.X_op = O_symbol; 152260484Sobrien exp.X_add_symbol = sym; 152360484Sobrien exp.X_add_number = 0; 152460484Sobrien symbol_set_value_expression (line_label, &exp); 152560484Sobrien symbol_set_frag (line_label, &zero_address_frag); 152633965Sjdp S_SET_SEGMENT (line_label, expr_section); 152733965Sjdp } 152833965Sjdp 152933965Sjdp /* FIXME: We just ignore the small argument, which distinguishes 153033965Sjdp COMMON and COMMON.S. I don't know what we can do about it. */ 153133965Sjdp 153233965Sjdp /* Ignore the type and hptype. */ 153333965Sjdp if (*input_line_pointer == ',') 153433965Sjdp input_line_pointer += 2; 153533965Sjdp if (*input_line_pointer == ',') 153633965Sjdp input_line_pointer += 2; 153733965Sjdp 153860484Sobrien demand_empty_rest_of_line (); 153960484Sobrien 154033965Sjdp mri_comment_end (stop, stopc); 154133965Sjdp} 154233965Sjdp 154333965Sjdpvoid 154433965Sjdps_data (ignore) 154560484Sobrien int ignore ATTRIBUTE_UNUSED; 154633965Sjdp{ 154733965Sjdp segT section; 154833965Sjdp register int temp; 154933965Sjdp 155033965Sjdp temp = get_absolute_expression (); 155133965Sjdp if (flag_readonly_data_in_text) 155233965Sjdp { 155333965Sjdp section = text_section; 155433965Sjdp temp += 1000; 155533965Sjdp } 155633965Sjdp else 155733965Sjdp section = data_section; 155833965Sjdp 155933965Sjdp subseg_set (section, (subsegT) temp); 156033965Sjdp 156133965Sjdp#ifdef OBJ_VMS 156233965Sjdp const_flag = 0; 156333965Sjdp#endif 156433965Sjdp demand_empty_rest_of_line (); 156533965Sjdp} 156633965Sjdp 156733965Sjdp/* Handle the .appfile pseudo-op. This is automatically generated by 156833965Sjdp do_scrub_chars when a preprocessor # line comment is seen with a 156933965Sjdp file name. This default definition may be overridden by the object 157033965Sjdp or CPU specific pseudo-ops. This function is also the default 157133965Sjdp definition for .file; the APPFILE argument is 1 for .appfile, 0 for 157233965Sjdp .file. */ 157333965Sjdp 157477298Sobrienvoid 157533965Sjdps_app_file (appfile) 157633965Sjdp int appfile; 157733965Sjdp{ 157833965Sjdp register char *s; 157933965Sjdp int length; 158033965Sjdp 158177298Sobrien /* Some assemblers tolerate immediately following '"'. */ 158233965Sjdp if ((s = demand_copy_string (&length)) != 0) 158333965Sjdp { 158433965Sjdp /* If this is a fake .appfile, a fake newline was inserted into 158533965Sjdp the buffer. Passing -2 to new_logical_line tells it to 158633965Sjdp account for it. */ 158738889Sjdp int may_omit 158877298Sobrien = (!new_logical_line (s, appfile ? -2 : -1) && appfile); 158933965Sjdp 159033965Sjdp /* In MRI mode, the preprocessor may have inserted an extraneous 159133965Sjdp backquote. */ 159233965Sjdp if (flag_m68k_mri 159333965Sjdp && *input_line_pointer == '\'' 159433965Sjdp && is_end_of_line[(unsigned char) input_line_pointer[1]]) 159533965Sjdp ++input_line_pointer; 159633965Sjdp 159733965Sjdp demand_empty_rest_of_line (); 159877298Sobrien if (!may_omit) 159938889Sjdp { 160033965Sjdp#ifdef LISTING 160138889Sjdp if (listing) 160238889Sjdp listing_source_file (s); 160333965Sjdp#endif 160438889Sjdp register_dependency (s); 160533965Sjdp#ifdef obj_app_file 160638889Sjdp obj_app_file (s); 160733965Sjdp#endif 160838889Sjdp } 160938889Sjdp } 161033965Sjdp} 161133965Sjdp 161233965Sjdp/* Handle the .appline pseudo-op. This is automatically generated by 161333965Sjdp do_scrub_chars when a preprocessor # line comment is seen. This 161433965Sjdp default definition may be overridden by the object or CPU specific 161533965Sjdp pseudo-ops. */ 161633965Sjdp 161733965Sjdpvoid 161833965Sjdps_app_line (ignore) 161960484Sobrien int ignore ATTRIBUTE_UNUSED; 162033965Sjdp{ 162133965Sjdp int l; 162233965Sjdp 162333965Sjdp /* The given number is that of the next line. */ 162433965Sjdp l = get_absolute_expression () - 1; 162533965Sjdp if (l < 0) 162633965Sjdp /* Some of the back ends can't deal with non-positive line numbers. 162733965Sjdp Besides, it's silly. */ 162889857Sobrien as_warn (_("line numbers must be positive; line number %d rejected"), 162977298Sobrien l + 1); 163033965Sjdp else 163133965Sjdp { 163233965Sjdp new_logical_line ((char *) NULL, l); 163333965Sjdp#ifdef LISTING 163433965Sjdp if (listing) 163533965Sjdp listing_source_line (l); 163633965Sjdp#endif 163733965Sjdp } 163833965Sjdp demand_empty_rest_of_line (); 163933965Sjdp} 164033965Sjdp 164133965Sjdp/* Handle the .end pseudo-op. Actually, the real work is done in 164233965Sjdp read_a_source_file. */ 164333965Sjdp 164433965Sjdpvoid 164533965Sjdps_end (ignore) 164660484Sobrien int ignore ATTRIBUTE_UNUSED; 164733965Sjdp{ 164833965Sjdp if (flag_mri) 164933965Sjdp { 165033965Sjdp /* The MRI assembler permits the start symbol to follow .end, 165133965Sjdp but we don't support that. */ 165233965Sjdp SKIP_WHITESPACE (); 165377298Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer] 165433965Sjdp && *input_line_pointer != '*' 165533965Sjdp && *input_line_pointer != '!') 165660484Sobrien as_warn (_("start address not supported")); 165733965Sjdp } 165833965Sjdp} 165933965Sjdp 166033965Sjdp/* Handle the .err pseudo-op. */ 166133965Sjdp 166233965Sjdpvoid 166333965Sjdps_err (ignore) 166460484Sobrien int ignore ATTRIBUTE_UNUSED; 166533965Sjdp{ 166660484Sobrien as_bad (_(".err encountered")); 166733965Sjdp demand_empty_rest_of_line (); 166833965Sjdp} 166933965Sjdp 167033965Sjdp/* Handle the MRI fail pseudo-op. */ 167133965Sjdp 167233965Sjdpvoid 167333965Sjdps_fail (ignore) 167460484Sobrien int ignore ATTRIBUTE_UNUSED; 167533965Sjdp{ 167633965Sjdp offsetT temp; 167733965Sjdp char *stop = NULL; 167833965Sjdp char stopc; 167933965Sjdp 168033965Sjdp if (flag_mri) 168133965Sjdp stop = mri_comment_field (&stopc); 168233965Sjdp 168333965Sjdp temp = get_absolute_expression (); 168433965Sjdp if (temp >= 500) 168560484Sobrien as_warn (_(".fail %ld encountered"), (long) temp); 168633965Sjdp else 168760484Sobrien as_bad (_(".fail %ld encountered"), (long) temp); 168833965Sjdp 168960484Sobrien demand_empty_rest_of_line (); 169060484Sobrien 169133965Sjdp if (flag_mri) 169233965Sjdp mri_comment_end (stop, stopc); 169333965Sjdp} 169433965Sjdp 169577298Sobrienvoid 169633965Sjdps_fill (ignore) 169760484Sobrien int ignore ATTRIBUTE_UNUSED; 169833965Sjdp{ 169938889Sjdp expressionS rep_exp; 170038889Sjdp long size = 1; 170138889Sjdp register long fill = 0; 170233965Sjdp char *p; 170333965Sjdp 170433965Sjdp#ifdef md_flush_pending_output 170533965Sjdp md_flush_pending_output (); 170633965Sjdp#endif 170733965Sjdp 170838889Sjdp get_known_segmented_expression (&rep_exp); 170933965Sjdp if (*input_line_pointer == ',') 171033965Sjdp { 171133965Sjdp input_line_pointer++; 171238889Sjdp size = get_absolute_expression (); 171333965Sjdp if (*input_line_pointer == ',') 171433965Sjdp { 171533965Sjdp input_line_pointer++; 171638889Sjdp fill = get_absolute_expression (); 171733965Sjdp } 171833965Sjdp } 171938889Sjdp 172033965Sjdp /* This is to be compatible with BSD 4.2 AS, not for any rational reason. */ 172133965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8) 172238889Sjdp if (size > BSD_FILL_SIZE_CROCK_8) 172333965Sjdp { 172489857Sobrien as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8); 172538889Sjdp size = BSD_FILL_SIZE_CROCK_8; 172633965Sjdp } 172738889Sjdp if (size < 0) 172833965Sjdp { 172989857Sobrien as_warn (_("size negative; .fill ignored")); 173038889Sjdp size = 0; 173133965Sjdp } 173238889Sjdp else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0) 173333965Sjdp { 173438889Sjdp if (rep_exp.X_add_number < 0) 173589857Sobrien as_warn (_("repeat < 0; .fill ignored")); 173638889Sjdp size = 0; 173733965Sjdp } 173833965Sjdp 173938889Sjdp if (size && !need_pass_2) 174033965Sjdp { 174138889Sjdp if (rep_exp.X_op == O_constant) 174238889Sjdp { 174338889Sjdp p = frag_var (rs_fill, (int) size, (int) size, 174438889Sjdp (relax_substateT) 0, (symbolS *) 0, 174538889Sjdp (offsetT) rep_exp.X_add_number, 174638889Sjdp (char *) 0); 174738889Sjdp } 174838889Sjdp else 174938889Sjdp { 175038889Sjdp /* We don't have a constant repeat count, so we can't use 175138889Sjdp rs_fill. We can get the same results out of rs_space, 175238889Sjdp but its argument is in bytes, so we must multiply the 175338889Sjdp repeat count by size. */ 175438889Sjdp 175538889Sjdp symbolS *rep_sym; 175638889Sjdp rep_sym = make_expr_symbol (&rep_exp); 175738889Sjdp if (size != 1) 175838889Sjdp { 175938889Sjdp expressionS size_exp; 176038889Sjdp size_exp.X_op = O_constant; 176138889Sjdp size_exp.X_add_number = size; 176238889Sjdp 176338889Sjdp rep_exp.X_op = O_multiply; 176438889Sjdp rep_exp.X_add_symbol = rep_sym; 176538889Sjdp rep_exp.X_op_symbol = make_expr_symbol (&size_exp); 176638889Sjdp rep_exp.X_add_number = 0; 176738889Sjdp rep_sym = make_expr_symbol (&rep_exp); 176838889Sjdp } 176938889Sjdp 177038889Sjdp p = frag_var (rs_space, (int) size, (int) size, 177138889Sjdp (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0); 177238889Sjdp } 177377298Sobrien 177438889Sjdp memset (p, 0, (unsigned int) size); 177577298Sobrien 177633965Sjdp /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX 177789857Sobrien flavoured AS. The following bizarre behaviour is to be 177877298Sobrien compatible with above. I guess they tried to take up to 8 177977298Sobrien bytes from a 4-byte expression and they forgot to sign 178089857Sobrien extend. */ 178133965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4) 178238889Sjdp md_number_to_chars (p, (valueT) fill, 178338889Sjdp (size > BSD_FILL_SIZE_CROCK_4 178433965Sjdp ? BSD_FILL_SIZE_CROCK_4 178538889Sjdp : (int) size)); 178633965Sjdp /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) 178777298Sobrien but emits no error message because it seems a legal thing to do. 178877298Sobrien It is a degenerate case of .fill but could be emitted by a 178977298Sobrien compiler. */ 179033965Sjdp } 179133965Sjdp demand_empty_rest_of_line (); 179233965Sjdp} 179333965Sjdp 179477298Sobrienvoid 179533965Sjdps_globl (ignore) 179660484Sobrien int ignore ATTRIBUTE_UNUSED; 179733965Sjdp{ 179833965Sjdp char *name; 179933965Sjdp int c; 180033965Sjdp symbolS *symbolP; 180133965Sjdp char *stop = NULL; 180233965Sjdp char stopc; 180333965Sjdp 180433965Sjdp if (flag_mri) 180533965Sjdp stop = mri_comment_field (&stopc); 180633965Sjdp 180733965Sjdp do 180833965Sjdp { 180933965Sjdp name = input_line_pointer; 181033965Sjdp c = get_symbol_end (); 181133965Sjdp symbolP = symbol_find_or_make (name); 181260484Sobrien S_SET_EXTERNAL (symbolP); 181360484Sobrien 181433965Sjdp *input_line_pointer = c; 181533965Sjdp SKIP_WHITESPACE (); 181660484Sobrien c = *input_line_pointer; 181733965Sjdp if (c == ',') 181833965Sjdp { 181933965Sjdp input_line_pointer++; 182033965Sjdp SKIP_WHITESPACE (); 182189857Sobrien if (is_end_of_line[(unsigned char) *input_line_pointer]) 182233965Sjdp c = '\n'; 182333965Sjdp } 182433965Sjdp } 182533965Sjdp while (c == ','); 182633965Sjdp 182760484Sobrien demand_empty_rest_of_line (); 182860484Sobrien 182933965Sjdp if (flag_mri) 183033965Sjdp mri_comment_end (stop, stopc); 183133965Sjdp} 183233965Sjdp 183333965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops. */ 183433965Sjdp 183533965Sjdpvoid 183633965Sjdps_irp (irpc) 183733965Sjdp int irpc; 183833965Sjdp{ 183933965Sjdp char *file; 184033965Sjdp unsigned int line; 184133965Sjdp sb s; 184233965Sjdp const char *err; 184333965Sjdp sb out; 184433965Sjdp 184533965Sjdp as_where (&file, &line); 184633965Sjdp 184733965Sjdp sb_new (&s); 184877298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 184933965Sjdp sb_add_char (&s, *input_line_pointer++); 185033965Sjdp 185133965Sjdp sb_new (&out); 185233965Sjdp 185333965Sjdp err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0'); 185433965Sjdp if (err != NULL) 185533965Sjdp as_bad_where (file, line, "%s", err); 185633965Sjdp 185733965Sjdp sb_kill (&s); 185833965Sjdp 185960484Sobrien input_scrub_include_sb (&out, input_line_pointer, 1); 186033965Sjdp sb_kill (&out); 186133965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 186233965Sjdp} 186333965Sjdp 186433965Sjdp/* Handle the .linkonce pseudo-op. This tells the assembler to mark 186533965Sjdp the section to only be linked once. However, this is not supported 186633965Sjdp by most object file formats. This takes an optional argument, 186733965Sjdp which is what to do about duplicates. */ 186833965Sjdp 186933965Sjdpvoid 187033965Sjdps_linkonce (ignore) 187160484Sobrien int ignore ATTRIBUTE_UNUSED; 187233965Sjdp{ 187333965Sjdp enum linkonce_type type; 187433965Sjdp 187533965Sjdp SKIP_WHITESPACE (); 187633965Sjdp 187733965Sjdp type = LINKONCE_DISCARD; 187833965Sjdp 187977298Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer]) 188033965Sjdp { 188133965Sjdp char *s; 188233965Sjdp char c; 188333965Sjdp 188433965Sjdp s = input_line_pointer; 188533965Sjdp c = get_symbol_end (); 188633965Sjdp if (strcasecmp (s, "discard") == 0) 188733965Sjdp type = LINKONCE_DISCARD; 188833965Sjdp else if (strcasecmp (s, "one_only") == 0) 188933965Sjdp type = LINKONCE_ONE_ONLY; 189033965Sjdp else if (strcasecmp (s, "same_size") == 0) 189133965Sjdp type = LINKONCE_SAME_SIZE; 189233965Sjdp else if (strcasecmp (s, "same_contents") == 0) 189333965Sjdp type = LINKONCE_SAME_CONTENTS; 189433965Sjdp else 189560484Sobrien as_warn (_("unrecognized .linkonce type `%s'"), s); 189633965Sjdp 189733965Sjdp *input_line_pointer = c; 189833965Sjdp } 189933965Sjdp 190033965Sjdp#ifdef obj_handle_link_once 190133965Sjdp obj_handle_link_once (type); 190233965Sjdp#else /* ! defined (obj_handle_link_once) */ 190333965Sjdp#ifdef BFD_ASSEMBLER 190433965Sjdp { 190533965Sjdp flagword flags; 190633965Sjdp 190733965Sjdp if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0) 190860484Sobrien as_warn (_(".linkonce is not supported for this object file format")); 190933965Sjdp 191033965Sjdp flags = bfd_get_section_flags (stdoutput, now_seg); 191133965Sjdp flags |= SEC_LINK_ONCE; 191233965Sjdp switch (type) 191333965Sjdp { 191433965Sjdp default: 191533965Sjdp abort (); 191633965Sjdp case LINKONCE_DISCARD: 191733965Sjdp flags |= SEC_LINK_DUPLICATES_DISCARD; 191833965Sjdp break; 191933965Sjdp case LINKONCE_ONE_ONLY: 192033965Sjdp flags |= SEC_LINK_DUPLICATES_ONE_ONLY; 192133965Sjdp break; 192233965Sjdp case LINKONCE_SAME_SIZE: 192333965Sjdp flags |= SEC_LINK_DUPLICATES_SAME_SIZE; 192433965Sjdp break; 192533965Sjdp case LINKONCE_SAME_CONTENTS: 192633965Sjdp flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS; 192733965Sjdp break; 192833965Sjdp } 192977298Sobrien if (!bfd_set_section_flags (stdoutput, now_seg, flags)) 193060484Sobrien as_bad (_("bfd_set_section_flags: %s"), 193133965Sjdp bfd_errmsg (bfd_get_error ())); 193233965Sjdp } 193333965Sjdp#else /* ! defined (BFD_ASSEMBLER) */ 193460484Sobrien as_warn (_(".linkonce is not supported for this object file format")); 193533965Sjdp#endif /* ! defined (BFD_ASSEMBLER) */ 193633965Sjdp#endif /* ! defined (obj_handle_link_once) */ 193733965Sjdp 193833965Sjdp demand_empty_rest_of_line (); 193933965Sjdp} 194033965Sjdp 194177298Sobrienstatic void 194238889Sjdps_lcomm_internal (needs_align, bytes_p) 194333965Sjdp /* 1 if this was a ".bss" directive, which may require a 3rd argument 194477298Sobrien (alignment); 0 if it was an ".lcomm" (2 args only). */ 194533965Sjdp int needs_align; 194638889Sjdp /* 1 if the alignment value should be interpreted as the byte boundary, 194777298Sobrien rather than the power of 2. */ 194838889Sjdp int bytes_p; 194933965Sjdp{ 195033965Sjdp register char *name; 195133965Sjdp register char c; 195233965Sjdp register char *p; 195333965Sjdp register int temp; 195433965Sjdp register symbolS *symbolP; 195533965Sjdp segT current_seg = now_seg; 195633965Sjdp subsegT current_subseg = now_subseg; 195733965Sjdp const int max_alignment = 15; 195833965Sjdp int align = 0; 195933965Sjdp segT bss_seg = bss_section; 196033965Sjdp 196133965Sjdp name = input_line_pointer; 196233965Sjdp c = get_symbol_end (); 196333965Sjdp p = input_line_pointer; 196433965Sjdp *p = c; 196589857Sobrien 196689857Sobrien if (name == p) 196789857Sobrien { 196889857Sobrien as_bad (_("expected symbol name")); 196989857Sobrien discard_rest_of_line (); 197089857Sobrien return; 197189857Sobrien } 197289857Sobrien 197333965Sjdp SKIP_WHITESPACE (); 197433965Sjdp 197533965Sjdp /* Accept an optional comma after the name. The comma used to be 197633965Sjdp required, but Irix 5 cc does not generate it. */ 197733965Sjdp if (*input_line_pointer == ',') 197833965Sjdp { 197933965Sjdp ++input_line_pointer; 198033965Sjdp SKIP_WHITESPACE (); 198133965Sjdp } 198233965Sjdp 198389857Sobrien if (is_end_of_line[(unsigned char) *input_line_pointer]) 198433965Sjdp { 198589857Sobrien as_bad (_("missing size expression")); 198633965Sjdp return; 198733965Sjdp } 198833965Sjdp 198933965Sjdp if ((temp = get_absolute_expression ()) < 0) 199033965Sjdp { 199189857Sobrien as_warn (_("BSS length (%d) < 0 ignored"), temp); 199233965Sjdp ignore_rest_of_line (); 199333965Sjdp return; 199433965Sjdp } 199533965Sjdp 199633965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA) 199733965Sjdp if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour 199833965Sjdp || OUTPUT_FLAVOR == bfd_target_elf_flavour) 199933965Sjdp { 200033965Sjdp /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */ 200189857Sobrien if ((unsigned) temp <= bfd_get_gp_size (stdoutput)) 200233965Sjdp { 200333965Sjdp bss_seg = subseg_new (".sbss", 1); 200433965Sjdp seg_info (bss_seg)->bss = 1; 200533965Sjdp#ifdef BFD_ASSEMBLER 200677298Sobrien if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) 200760484Sobrien as_warn (_("error setting flags for \".sbss\": %s"), 200833965Sjdp bfd_errmsg (bfd_get_error ())); 200933965Sjdp#endif 201033965Sjdp } 201133965Sjdp } 201233965Sjdp#endif 201360484Sobrien 201477298Sobrien if (!needs_align) 201577298Sobrien { 201677298Sobrien TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); 201733965Sjdp 201877298Sobrien /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ 201977298Sobrien if (align) 202077298Sobrien record_alignment (bss_seg, align); 202177298Sobrien } 202233965Sjdp 202333965Sjdp if (needs_align) 202433965Sjdp { 202533965Sjdp align = 0; 202633965Sjdp SKIP_WHITESPACE (); 202777298Sobrien 202833965Sjdp if (*input_line_pointer != ',') 202933965Sjdp { 203089857Sobrien as_bad (_("expected comma after size")); 203133965Sjdp ignore_rest_of_line (); 203233965Sjdp return; 203333965Sjdp } 203477298Sobrien 203533965Sjdp input_line_pointer++; 203633965Sjdp SKIP_WHITESPACE (); 203777298Sobrien 203889857Sobrien if (is_end_of_line[(unsigned char) *input_line_pointer]) 203933965Sjdp { 204089857Sobrien as_bad (_("missing alignment")); 204133965Sjdp return; 204233965Sjdp } 204377298Sobrien 204433965Sjdp align = get_absolute_expression (); 204577298Sobrien 204638889Sjdp if (bytes_p) 204738889Sjdp { 204838889Sjdp /* Convert to a power of 2. */ 204938889Sjdp if (align != 0) 205038889Sjdp { 205138889Sjdp unsigned int i; 205238889Sjdp 205338889Sjdp for (i = 0; (align & 1) == 0; align >>= 1, ++i) 205438889Sjdp ; 205538889Sjdp if (align != 1) 205689857Sobrien as_bad (_("alignment not a power of 2")); 205738889Sjdp align = i; 205838889Sjdp } 205938889Sjdp } 206077298Sobrien 206133965Sjdp if (align > max_alignment) 206233965Sjdp { 206333965Sjdp align = max_alignment; 206489857Sobrien as_warn (_("alignment too large; %d assumed"), align); 206533965Sjdp } 206633965Sjdp else if (align < 0) 206733965Sjdp { 206833965Sjdp align = 0; 206989857Sobrien as_warn (_("alignment negative; 0 assumed")); 207033965Sjdp } 207177298Sobrien 207233965Sjdp record_alignment (bss_seg, align); 207377298Sobrien } 207433965Sjdp else 207533965Sjdp { 207633965Sjdp /* Assume some objects may require alignment on some systems. */ 207733965Sjdp#if defined (TC_ALPHA) && ! defined (VMS) 207833965Sjdp if (temp > 1) 207933965Sjdp { 208033965Sjdp align = ffs (temp) - 1; 208133965Sjdp if (temp % (1 << align)) 208233965Sjdp abort (); 208333965Sjdp } 208433965Sjdp#endif 208533965Sjdp } 208633965Sjdp 208733965Sjdp *p = 0; 208833965Sjdp symbolP = symbol_find_or_make (name); 208933965Sjdp *p = c; 209033965Sjdp 209133965Sjdp if ( 209260484Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \ 209360484Sobrien || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT)) 209460484Sobrien#ifdef BFD_ASSEMBLER 209560484Sobrien (OUTPUT_FLAVOR != bfd_target_aout_flavour 209660484Sobrien || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && 209760484Sobrien#else 209860484Sobrien (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && 209960484Sobrien#endif 210060484Sobrien#endif 210160484Sobrien (S_GET_SEGMENT (symbolP) == bss_seg 210260484Sobrien || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) 210333965Sjdp { 210433965Sjdp char *pfrag; 210533965Sjdp 210633965Sjdp subseg_set (bss_seg, 1); 210733965Sjdp 210833965Sjdp if (align) 210933965Sjdp frag_align (align, 0, 0); 211077298Sobrien 211177298Sobrien /* Detach from old frag. */ 211233965Sjdp if (S_GET_SEGMENT (symbolP) == bss_seg) 211360484Sobrien symbol_get_frag (symbolP)->fr_symbol = NULL; 211433965Sjdp 211560484Sobrien symbol_set_frag (symbolP, frag_now); 211677298Sobrien pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, 211733965Sjdp (offsetT) temp, (char *) 0); 211833965Sjdp *pfrag = 0; 211933965Sjdp 212033965Sjdp S_SET_SEGMENT (symbolP, bss_seg); 212133965Sjdp 212233965Sjdp#ifdef OBJ_COFF 212333965Sjdp /* The symbol may already have been created with a preceding 212433965Sjdp ".globl" directive -- be careful not to step on storage class 212577298Sobrien in that case. Otherwise, set it to static. */ 212633965Sjdp if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 212733965Sjdp { 212833965Sjdp S_SET_STORAGE_CLASS (symbolP, C_STAT); 212933965Sjdp } 213033965Sjdp#endif /* OBJ_COFF */ 213133965Sjdp 213233965Sjdp#ifdef S_SET_SIZE 213333965Sjdp S_SET_SIZE (symbolP, temp); 213433965Sjdp#endif 213533965Sjdp } 213633965Sjdp else 213789857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 213833965Sjdp 213933965Sjdp subseg_set (current_seg, current_subseg); 214033965Sjdp 214133965Sjdp demand_empty_rest_of_line (); 214277298Sobrien} 214333965Sjdp 214438889Sjdpvoid 214538889Sjdps_lcomm (needs_align) 214638889Sjdp int needs_align; 214738889Sjdp{ 214838889Sjdp s_lcomm_internal (needs_align, 0); 214938889Sjdp} 215038889Sjdp 215177298Sobrienvoid 215277298Sobriens_lcomm_bytes (needs_align) 215338889Sjdp int needs_align; 215438889Sjdp{ 215538889Sjdp s_lcomm_internal (needs_align, 1); 215638889Sjdp} 215738889Sjdp 215877298Sobrienvoid 215933965Sjdps_lsym (ignore) 216060484Sobrien int ignore ATTRIBUTE_UNUSED; 216133965Sjdp{ 216233965Sjdp register char *name; 216333965Sjdp register char c; 216433965Sjdp register char *p; 216533965Sjdp expressionS exp; 216633965Sjdp register symbolS *symbolP; 216733965Sjdp 216877298Sobrien /* We permit ANY defined expression: BSD4.2 demands constants. */ 216933965Sjdp name = input_line_pointer; 217033965Sjdp c = get_symbol_end (); 217133965Sjdp p = input_line_pointer; 217233965Sjdp *p = c; 217389857Sobrien 217489857Sobrien if (name == p) 217589857Sobrien { 217689857Sobrien as_bad (_("expected symbol name")); 217789857Sobrien discard_rest_of_line (); 217889857Sobrien return; 217989857Sobrien } 218089857Sobrien 218133965Sjdp SKIP_WHITESPACE (); 218277298Sobrien 218333965Sjdp if (*input_line_pointer != ',') 218433965Sjdp { 218533965Sjdp *p = 0; 218689857Sobrien as_bad (_("expected comma after \"%s\""), name); 218733965Sjdp *p = c; 218833965Sjdp ignore_rest_of_line (); 218933965Sjdp return; 219033965Sjdp } 219177298Sobrien 219233965Sjdp input_line_pointer++; 219333965Sjdp expression (&exp); 219477298Sobrien 219533965Sjdp if (exp.X_op != O_constant 219633965Sjdp && exp.X_op != O_register) 219733965Sjdp { 219860484Sobrien as_bad (_("bad expression")); 219933965Sjdp ignore_rest_of_line (); 220033965Sjdp return; 220133965Sjdp } 220277298Sobrien 220333965Sjdp *p = 0; 220433965Sjdp symbolP = symbol_find_or_make (name); 220533965Sjdp 220633965Sjdp /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 && 220733965Sjdp symbolP->sy_desc == 0) out of this test because coff doesn't have 220833965Sjdp those fields, and I can't see when they'd ever be tripped. I 220933965Sjdp don't think I understand why they were here so I may have 221033965Sjdp introduced a bug. As recently as 1.37 didn't have this test 221177298Sobrien anyway. xoxorich. */ 221233965Sjdp 221333965Sjdp if (S_GET_SEGMENT (symbolP) == undefined_section 221433965Sjdp && S_GET_VALUE (symbolP) == 0) 221533965Sjdp { 221633965Sjdp /* The name might be an undefined .global symbol; be sure to 221777298Sobrien keep the "external" bit. */ 221833965Sjdp S_SET_SEGMENT (symbolP, 221933965Sjdp (exp.X_op == O_constant 222033965Sjdp ? absolute_section 222133965Sjdp : reg_section)); 222233965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 222333965Sjdp } 222433965Sjdp else 222533965Sjdp { 222689857Sobrien as_bad (_("symbol `%s' is already defined"), name); 222733965Sjdp } 222877298Sobrien 222933965Sjdp *p = c; 223033965Sjdp demand_empty_rest_of_line (); 223177298Sobrien} 223233965Sjdp 223333965Sjdp/* Read a line into an sb. */ 223433965Sjdp 223533965Sjdpstatic int 223633965Sjdpget_line_sb (line) 223733965Sjdp sb *line; 223833965Sjdp{ 223933965Sjdp char quote1, quote2, inquote; 224033965Sjdp 224133965Sjdp if (input_line_pointer[-1] == '\n') 224233965Sjdp bump_line_counters (); 224333965Sjdp 224433965Sjdp if (input_line_pointer >= buffer_limit) 224533965Sjdp { 224633965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 224733965Sjdp if (buffer_limit == 0) 224833965Sjdp return 0; 224933965Sjdp } 225033965Sjdp 225133965Sjdp /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this 225233965Sjdp code needs to be changed. */ 225377298Sobrien if (!flag_m68k_mri) 225433965Sjdp quote1 = '"'; 225533965Sjdp else 225633965Sjdp quote1 = '\0'; 225733965Sjdp 225833965Sjdp quote2 = '\0'; 225933965Sjdp if (flag_m68k_mri) 226033965Sjdp quote2 = '\''; 226133965Sjdp#ifdef LEX_IS_STRINGQUOTE 226233965Sjdp quote2 = '\''; 226333965Sjdp#endif 226433965Sjdp 226533965Sjdp inquote = '\0'; 226677298Sobrien 226777298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer] 226833965Sjdp || (inquote != '\0' && *input_line_pointer != '\n')) 226933965Sjdp { 227033965Sjdp if (inquote == *input_line_pointer) 227133965Sjdp inquote = '\0'; 227233965Sjdp else if (inquote == '\0') 227333965Sjdp { 227433965Sjdp if (*input_line_pointer == quote1) 227533965Sjdp inquote = quote1; 227633965Sjdp else if (*input_line_pointer == quote2) 227733965Sjdp inquote = quote2; 227833965Sjdp } 227977298Sobrien 228033965Sjdp sb_add_char (line, *input_line_pointer++); 228133965Sjdp } 228277298Sobrien 228338889Sjdp while (input_line_pointer < buffer_limit 228438889Sjdp && is_end_of_line[(unsigned char) *input_line_pointer]) 228533965Sjdp { 228633965Sjdp if (input_line_pointer[-1] == '\n') 228733965Sjdp bump_line_counters (); 228833965Sjdp ++input_line_pointer; 228933965Sjdp } 229077298Sobrien 229133965Sjdp return 1; 229233965Sjdp} 229333965Sjdp 229433965Sjdp/* Define a macro. This is an interface to macro.c, which is shared 229533965Sjdp between gas and gasp. */ 229633965Sjdp 229733965Sjdpvoid 229833965Sjdps_macro (ignore) 229960484Sobrien int ignore ATTRIBUTE_UNUSED; 230033965Sjdp{ 230133965Sjdp char *file; 230233965Sjdp unsigned int line; 230333965Sjdp sb s; 230433965Sjdp sb label; 230533965Sjdp const char *err; 230633965Sjdp const char *name; 230733965Sjdp 230833965Sjdp as_where (&file, &line); 230933965Sjdp 231033965Sjdp sb_new (&s); 231177298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 231233965Sjdp sb_add_char (&s, *input_line_pointer++); 231333965Sjdp 231433965Sjdp sb_new (&label); 231533965Sjdp if (line_label != NULL) 231633965Sjdp sb_add_string (&label, S_GET_NAME (line_label)); 231733965Sjdp 231833965Sjdp err = define_macro (0, &s, &label, get_line_sb, &name); 231933965Sjdp if (err != NULL) 232033965Sjdp as_bad_where (file, line, "%s", err); 232133965Sjdp else 232233965Sjdp { 232333965Sjdp if (line_label != NULL) 232433965Sjdp { 232533965Sjdp S_SET_SEGMENT (line_label, undefined_section); 232633965Sjdp S_SET_VALUE (line_label, 0); 232760484Sobrien symbol_set_frag (line_label, &zero_address_frag); 232833965Sjdp } 232933965Sjdp 233060484Sobrien if (((NO_PSEUDO_DOT || flag_m68k_mri) 233133965Sjdp && hash_find (po_hash, name) != NULL) 233277298Sobrien || (!flag_m68k_mri 233333965Sjdp && *name == '.' 233433965Sjdp && hash_find (po_hash, name + 1) != NULL)) 233560484Sobrien as_warn (_("attempt to redefine pseudo-op `%s' ignored"), 233633965Sjdp name); 233733965Sjdp } 233833965Sjdp 233933965Sjdp sb_kill (&s); 234033965Sjdp} 234133965Sjdp 234233965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro 234333965Sjdp expansion. */ 234433965Sjdp 234533965Sjdpvoid 234633965Sjdps_mexit (ignore) 234760484Sobrien int ignore ATTRIBUTE_UNUSED; 234833965Sjdp{ 234933965Sjdp cond_exit_macro (macro_nest); 235033965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 235133965Sjdp} 235233965Sjdp 235333965Sjdp/* Switch in and out of MRI mode. */ 235433965Sjdp 235533965Sjdpvoid 235633965Sjdps_mri (ignore) 235760484Sobrien int ignore ATTRIBUTE_UNUSED; 235833965Sjdp{ 235933965Sjdp int on, old_flag; 236033965Sjdp 236133965Sjdp on = get_absolute_expression (); 236233965Sjdp old_flag = flag_mri; 236333965Sjdp if (on != 0) 236433965Sjdp { 236533965Sjdp flag_mri = 1; 236633965Sjdp#ifdef TC_M68K 236733965Sjdp flag_m68k_mri = 1; 236833965Sjdp#endif 236960484Sobrien macro_mri_mode (1); 237033965Sjdp } 237133965Sjdp else 237233965Sjdp { 237333965Sjdp flag_mri = 0; 237460484Sobrien#ifdef TC_M68K 237533965Sjdp flag_m68k_mri = 0; 237660484Sobrien#endif 237760484Sobrien macro_mri_mode (0); 237833965Sjdp } 237933965Sjdp 238060484Sobrien /* Operator precedence changes in m68k MRI mode, so we need to 238160484Sobrien update the operator rankings. */ 238260484Sobrien expr_set_precedence (); 238360484Sobrien 238433965Sjdp#ifdef MRI_MODE_CHANGE 238533965Sjdp if (on != old_flag) 238633965Sjdp MRI_MODE_CHANGE (on); 238733965Sjdp#endif 238833965Sjdp 238933965Sjdp demand_empty_rest_of_line (); 239033965Sjdp} 239133965Sjdp 239233965Sjdp/* Handle changing the location counter. */ 239333965Sjdp 239433965Sjdpstatic void 239533965Sjdpdo_org (segment, exp, fill) 239633965Sjdp segT segment; 239733965Sjdp expressionS *exp; 239833965Sjdp int fill; 239933965Sjdp{ 240033965Sjdp if (segment != now_seg && segment != absolute_section) 240189857Sobrien as_bad (_("invalid segment \"%s\""), segment_name (segment)); 240233965Sjdp 240333965Sjdp if (now_seg == absolute_section) 240433965Sjdp { 240533965Sjdp if (fill != 0) 240660484Sobrien as_warn (_("ignoring fill value in absolute section")); 240733965Sjdp if (exp->X_op != O_constant) 240833965Sjdp { 240960484Sobrien as_bad (_("only constant offsets supported in absolute section")); 241033965Sjdp exp->X_add_number = 0; 241133965Sjdp } 241233965Sjdp abs_section_offset = exp->X_add_number; 241333965Sjdp } 241433965Sjdp else 241533965Sjdp { 241633965Sjdp char *p; 241778828Sobrien symbolS *sym = exp->X_add_symbol; 241878828Sobrien offsetT off = exp->X_add_number * OCTETS_PER_BYTE; 241933965Sjdp 242078828Sobrien if (exp->X_op != O_constant && exp->X_op != O_symbol) 242178828Sobrien { 242278828Sobrien /* Handle complex expressions. */ 242378828Sobrien sym = make_expr_symbol (exp); 242478828Sobrien off = 0; 242578828Sobrien } 242678828Sobrien 242778828Sobrien p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0); 242833965Sjdp *p = fill; 242933965Sjdp } 243033965Sjdp} 243133965Sjdp 243277298Sobrienvoid 243333965Sjdps_org (ignore) 243460484Sobrien int ignore ATTRIBUTE_UNUSED; 243533965Sjdp{ 243633965Sjdp register segT segment; 243733965Sjdp expressionS exp; 243833965Sjdp register long temp_fill; 243933965Sjdp 244060484Sobrien#ifdef md_flush_pending_output 244160484Sobrien md_flush_pending_output (); 244260484Sobrien#endif 244360484Sobrien 244433965Sjdp /* The m68k MRI assembler has a different meaning for .org. It 244533965Sjdp means to create an absolute section at a given address. We can't 244633965Sjdp support that--use a linker script instead. */ 244733965Sjdp if (flag_m68k_mri) 244833965Sjdp { 244960484Sobrien as_bad (_("MRI style ORG pseudo-op not supported")); 245033965Sjdp ignore_rest_of_line (); 245133965Sjdp return; 245233965Sjdp } 245333965Sjdp 245433965Sjdp /* Don't believe the documentation of BSD 4.2 AS. There is no such 245533965Sjdp thing as a sub-segment-relative origin. Any absolute origin is 245633965Sjdp given a warning, then assumed to be segment-relative. Any 245733965Sjdp segmented origin expression ("foo+42") had better be in the right 245833965Sjdp segment or the .org is ignored. 245933965Sjdp 246033965Sjdp BSD 4.2 AS warns if you try to .org backwards. We cannot because 246133965Sjdp we never know sub-segment sizes when we are reading code. BSD 246233965Sjdp will crash trying to emit negative numbers of filler bytes in 246333965Sjdp certain .orgs. We don't crash, but see as-write for that code. 246433965Sjdp 246533965Sjdp Don't make frag if need_pass_2==1. */ 246633965Sjdp segment = get_known_segmented_expression (&exp); 246733965Sjdp if (*input_line_pointer == ',') 246833965Sjdp { 246933965Sjdp input_line_pointer++; 247033965Sjdp temp_fill = get_absolute_expression (); 247133965Sjdp } 247233965Sjdp else 247333965Sjdp temp_fill = 0; 247433965Sjdp 247533965Sjdp if (!need_pass_2) 247633965Sjdp do_org (segment, &exp, temp_fill); 247733965Sjdp 247833965Sjdp demand_empty_rest_of_line (); 247977298Sobrien} 248033965Sjdp 248133965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op. This should be 248233965Sjdp called by the obj-format routine which handles section changing 248333965Sjdp when in MRI mode. It will create a new section, and return it. It 248433965Sjdp will set *TYPE to the section type: one of 'C' (code), 'D' (data), 248533965Sjdp 'M' (mixed), or 'R' (romable). If BFD_ASSEMBLER is defined, the 248633965Sjdp flags will be set in the section. */ 248733965Sjdp 248833965Sjdpvoid 248933965Sjdps_mri_sect (type) 249060484Sobrien char *type ATTRIBUTE_UNUSED; 249133965Sjdp{ 249233965Sjdp#ifdef TC_M68K 249333965Sjdp 249433965Sjdp char *name; 249533965Sjdp char c; 249633965Sjdp segT seg; 249733965Sjdp 249833965Sjdp SKIP_WHITESPACE (); 249977298Sobrien 250033965Sjdp name = input_line_pointer; 250189857Sobrien if (!ISDIGIT (*name)) 250233965Sjdp c = get_symbol_end (); 250333965Sjdp else 250433965Sjdp { 250533965Sjdp do 250633965Sjdp { 250733965Sjdp ++input_line_pointer; 250833965Sjdp } 250989857Sobrien while (ISDIGIT (*input_line_pointer)); 251077298Sobrien 251133965Sjdp c = *input_line_pointer; 251233965Sjdp *input_line_pointer = '\0'; 251333965Sjdp } 251433965Sjdp 251533965Sjdp name = xstrdup (name); 251633965Sjdp 251733965Sjdp *input_line_pointer = c; 251833965Sjdp 251933965Sjdp seg = subseg_new (name, 0); 252033965Sjdp 252133965Sjdp if (*input_line_pointer == ',') 252233965Sjdp { 252333965Sjdp int align; 252433965Sjdp 252533965Sjdp ++input_line_pointer; 252633965Sjdp align = get_absolute_expression (); 252733965Sjdp record_alignment (seg, align); 252833965Sjdp } 252933965Sjdp 253033965Sjdp *type = 'C'; 253133965Sjdp if (*input_line_pointer == ',') 253233965Sjdp { 253333965Sjdp c = *++input_line_pointer; 253489857Sobrien c = TOUPPER (c); 253533965Sjdp if (c == 'C' || c == 'D' || c == 'M' || c == 'R') 253633965Sjdp *type = c; 253733965Sjdp else 253860484Sobrien as_bad (_("unrecognized section type")); 253933965Sjdp ++input_line_pointer; 254033965Sjdp 254133965Sjdp#ifdef BFD_ASSEMBLER 254233965Sjdp { 254333965Sjdp flagword flags; 254433965Sjdp 254533965Sjdp flags = SEC_NO_FLAGS; 254633965Sjdp if (*type == 'C') 254733965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE; 254833965Sjdp else if (*type == 'D' || *type == 'M') 254933965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_DATA; 255033965Sjdp else if (*type == 'R') 255133965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM; 255233965Sjdp if (flags != SEC_NO_FLAGS) 255333965Sjdp { 255477298Sobrien if (!bfd_set_section_flags (stdoutput, seg, flags)) 255560484Sobrien as_warn (_("error setting flags for \"%s\": %s"), 255633965Sjdp bfd_section_name (stdoutput, seg), 255733965Sjdp bfd_errmsg (bfd_get_error ())); 255833965Sjdp } 255933965Sjdp } 256033965Sjdp#endif 256133965Sjdp } 256233965Sjdp 256333965Sjdp /* Ignore the HP type. */ 256433965Sjdp if (*input_line_pointer == ',') 256533965Sjdp input_line_pointer += 2; 256633965Sjdp 256733965Sjdp demand_empty_rest_of_line (); 256833965Sjdp 256933965Sjdp#else /* ! TC_M68K */ 257033965Sjdp#ifdef TC_I960 257133965Sjdp 257233965Sjdp char *name; 257333965Sjdp char c; 257433965Sjdp segT seg; 257533965Sjdp 257633965Sjdp SKIP_WHITESPACE (); 257733965Sjdp 257833965Sjdp name = input_line_pointer; 257933965Sjdp c = get_symbol_end (); 258033965Sjdp 258133965Sjdp name = xstrdup (name); 258233965Sjdp 258333965Sjdp *input_line_pointer = c; 258433965Sjdp 258533965Sjdp seg = subseg_new (name, 0); 258633965Sjdp 258733965Sjdp if (*input_line_pointer != ',') 258833965Sjdp *type = 'C'; 258933965Sjdp else 259033965Sjdp { 259133965Sjdp char *sectype; 259233965Sjdp 259333965Sjdp ++input_line_pointer; 259433965Sjdp SKIP_WHITESPACE (); 259533965Sjdp sectype = input_line_pointer; 259633965Sjdp c = get_symbol_end (); 259733965Sjdp if (*sectype == '\0') 259833965Sjdp *type = 'C'; 259933965Sjdp else if (strcasecmp (sectype, "text") == 0) 260033965Sjdp *type = 'C'; 260133965Sjdp else if (strcasecmp (sectype, "data") == 0) 260233965Sjdp *type = 'D'; 260333965Sjdp else if (strcasecmp (sectype, "romdata") == 0) 260433965Sjdp *type = 'R'; 260533965Sjdp else 260660484Sobrien as_warn (_("unrecognized section type `%s'"), sectype); 260733965Sjdp *input_line_pointer = c; 260833965Sjdp } 260933965Sjdp 261033965Sjdp if (*input_line_pointer == ',') 261133965Sjdp { 261233965Sjdp char *seccmd; 261333965Sjdp 261433965Sjdp ++input_line_pointer; 261533965Sjdp SKIP_WHITESPACE (); 261633965Sjdp seccmd = input_line_pointer; 261733965Sjdp c = get_symbol_end (); 261833965Sjdp if (strcasecmp (seccmd, "absolute") == 0) 261933965Sjdp { 262060484Sobrien as_bad (_("absolute sections are not supported")); 262133965Sjdp *input_line_pointer = c; 262233965Sjdp ignore_rest_of_line (); 262333965Sjdp return; 262433965Sjdp } 262533965Sjdp else if (strcasecmp (seccmd, "align") == 0) 262633965Sjdp { 262733965Sjdp int align; 262833965Sjdp 262933965Sjdp *input_line_pointer = c; 263033965Sjdp align = get_absolute_expression (); 263133965Sjdp record_alignment (seg, align); 263233965Sjdp } 263333965Sjdp else 263433965Sjdp { 263560484Sobrien as_warn (_("unrecognized section command `%s'"), seccmd); 263633965Sjdp *input_line_pointer = c; 263733965Sjdp } 263833965Sjdp } 263933965Sjdp 264077298Sobrien demand_empty_rest_of_line (); 264133965Sjdp 264233965Sjdp#else /* ! TC_I960 */ 264333965Sjdp /* The MRI assembler seems to use different forms of .sect for 264433965Sjdp different targets. */ 264560484Sobrien as_bad ("MRI mode not supported for this target"); 264660484Sobrien ignore_rest_of_line (); 264733965Sjdp#endif /* ! TC_I960 */ 264833965Sjdp#endif /* ! TC_M68K */ 264933965Sjdp} 265033965Sjdp 265133965Sjdp/* Handle the .print pseudo-op. */ 265233965Sjdp 265333965Sjdpvoid 265433965Sjdps_print (ignore) 265560484Sobrien int ignore ATTRIBUTE_UNUSED; 265633965Sjdp{ 265733965Sjdp char *s; 265833965Sjdp int len; 265933965Sjdp 266033965Sjdp s = demand_copy_C_string (&len); 266133965Sjdp printf ("%s\n", s); 266233965Sjdp demand_empty_rest_of_line (); 266333965Sjdp} 266433965Sjdp 266533965Sjdp/* Handle the .purgem pseudo-op. */ 266633965Sjdp 266733965Sjdpvoid 266833965Sjdps_purgem (ignore) 266960484Sobrien int ignore ATTRIBUTE_UNUSED; 267033965Sjdp{ 267133965Sjdp if (is_it_end_of_statement ()) 267233965Sjdp { 267333965Sjdp demand_empty_rest_of_line (); 267433965Sjdp return; 267533965Sjdp } 267633965Sjdp 267733965Sjdp do 267833965Sjdp { 267933965Sjdp char *name; 268033965Sjdp char c; 268133965Sjdp 268233965Sjdp SKIP_WHITESPACE (); 268333965Sjdp name = input_line_pointer; 268433965Sjdp c = get_symbol_end (); 268533965Sjdp delete_macro (name); 268633965Sjdp *input_line_pointer = c; 268733965Sjdp SKIP_WHITESPACE (); 268833965Sjdp } 268933965Sjdp while (*input_line_pointer++ == ','); 269033965Sjdp 269133965Sjdp --input_line_pointer; 269233965Sjdp demand_empty_rest_of_line (); 269333965Sjdp} 269433965Sjdp 269533965Sjdp/* Handle the .rept pseudo-op. */ 269633965Sjdp 269733965Sjdpvoid 269889857Sobriens_bad_endr (ignore) 269989857Sobrien int ignore ATTRIBUTE_UNUSED; 270089857Sobrien{ 270189857Sobrien as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp")); 270289857Sobrien demand_empty_rest_of_line (); 270389857Sobrien} 270489857Sobrien 270589857Sobrien/* Handle the .rept pseudo-op. */ 270689857Sobrien 270789857Sobrienvoid 270833965Sjdps_rept (ignore) 270960484Sobrien int ignore ATTRIBUTE_UNUSED; 271033965Sjdp{ 271133965Sjdp int count; 271260484Sobrien 271360484Sobrien count = get_absolute_expression (); 271460484Sobrien 271577298Sobrien do_repeat (count, "REPT", "ENDR"); 271660484Sobrien} 271760484Sobrien 271860484Sobrien/* This function provides a generic repeat block implementation. It allows 271977298Sobrien different directives to be used as the start/end keys. */ 272060484Sobrien 272160484Sobrienvoid 272260484Sobriendo_repeat (count, start, end) 272377298Sobrien int count; 272477298Sobrien const char *start; 272577298Sobrien const char *end; 272660484Sobrien{ 272733965Sjdp sb one; 272833965Sjdp sb many; 272933965Sjdp 273033965Sjdp sb_new (&one); 273177298Sobrien if (!buffer_and_nest (start, end, &one, get_line_sb)) 273233965Sjdp { 273360484Sobrien as_bad (_("%s without %s"), start, end); 273433965Sjdp return; 273533965Sjdp } 273633965Sjdp 273733965Sjdp sb_new (&many); 273833965Sjdp while (count-- > 0) 273933965Sjdp sb_add_sb (&many, &one); 274033965Sjdp 274133965Sjdp sb_kill (&one); 274233965Sjdp 274360484Sobrien input_scrub_include_sb (&many, input_line_pointer, 1); 274433965Sjdp sb_kill (&many); 274533965Sjdp buffer_limit = input_scrub_next_buffer (&input_line_pointer); 274633965Sjdp} 274733965Sjdp 274860484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional 274960484Sobrien input buffers to skip. Assumes that conditionals preceding the loop end 275077298Sobrien are properly nested. 275160484Sobrien 275260484Sobrien This function makes it easier to implement a premature "break" out of the 275360484Sobrien loop. The EXTRA arg accounts for other buffers we might have inserted, 275477298Sobrien such as line substitutions. */ 275560484Sobrien 275660484Sobrienvoid 275760484Sobrienend_repeat (extra) 275877298Sobrien int extra; 275960484Sobrien{ 276060484Sobrien cond_exit_macro (macro_nest); 276160484Sobrien while (extra-- >= 0) 276260484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 276360484Sobrien} 276460484Sobrien 276533965Sjdp/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then 276633965Sjdp this is .equiv, and it is an error if the symbol is already 276733965Sjdp defined. */ 276833965Sjdp 276977298Sobrienvoid 277033965Sjdps_set (equiv) 277133965Sjdp int equiv; 277233965Sjdp{ 277333965Sjdp register char *name; 277433965Sjdp register char delim; 277533965Sjdp register char *end_name; 277633965Sjdp register symbolS *symbolP; 277733965Sjdp 277877298Sobrien /* Especial apologies for the random logic: 277977298Sobrien this just grew, and could be parsed much more simply! 278077298Sobrien Dean in haste. */ 278133965Sjdp name = input_line_pointer; 278233965Sjdp delim = get_symbol_end (); 278333965Sjdp end_name = input_line_pointer; 278433965Sjdp *end_name = delim; 278589857Sobrien 278689857Sobrien if (name == end_name) 278789857Sobrien { 278889857Sobrien as_bad (_("expected symbol name")); 278989857Sobrien discard_rest_of_line (); 279089857Sobrien return; 279189857Sobrien } 279289857Sobrien 279333965Sjdp SKIP_WHITESPACE (); 279433965Sjdp 279533965Sjdp if (*input_line_pointer != ',') 279633965Sjdp { 279733965Sjdp *end_name = 0; 279889857Sobrien as_bad (_("expected comma after \"%s\""), name); 279933965Sjdp *end_name = delim; 280033965Sjdp ignore_rest_of_line (); 280133965Sjdp return; 280233965Sjdp } 280333965Sjdp 280433965Sjdp input_line_pointer++; 280533965Sjdp *end_name = 0; 280633965Sjdp 280733965Sjdp if (name[0] == '.' && name[1] == '\0') 280833965Sjdp { 280977298Sobrien /* Turn '. = mumble' into a .org mumble. */ 281033965Sjdp register segT segment; 281133965Sjdp expressionS exp; 281233965Sjdp 281333965Sjdp segment = get_known_segmented_expression (&exp); 281433965Sjdp 281533965Sjdp if (!need_pass_2) 281633965Sjdp do_org (segment, &exp, 0); 281733965Sjdp 281833965Sjdp *end_name = delim; 281933965Sjdp return; 282033965Sjdp } 282133965Sjdp 282233965Sjdp if ((symbolP = symbol_find (name)) == NULL 282333965Sjdp && (symbolP = md_undefined_symbol (name)) == NULL) 282433965Sjdp { 282538889Sjdp#ifndef NO_LISTING 282638889Sjdp /* When doing symbol listings, play games with dummy fragments living 282738889Sjdp outside the normal fragment chain to record the file and line info 282838889Sjdp for this symbol. */ 282938889Sjdp if (listing & LISTING_SYMBOLS) 283038889Sjdp { 283138889Sjdp extern struct list_info_struct *listing_tail; 283277298Sobrien fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS)); 283377298Sobrien memset (dummy_frag, 0, sizeof (fragS)); 283438889Sjdp dummy_frag->fr_type = rs_fill; 283538889Sjdp dummy_frag->line = listing_tail; 283638889Sjdp symbolP = symbol_new (name, undefined_section, 0, dummy_frag); 283738889Sjdp dummy_frag->fr_symbol = symbolP; 283838889Sjdp } 283938889Sjdp else 284038889Sjdp#endif 284177298Sobrien symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); 284277298Sobrien 284333965Sjdp#ifdef OBJ_COFF 284477298Sobrien /* "set" symbols are local unless otherwise specified. */ 284533965Sjdp SF_SET_LOCAL (symbolP); 284633965Sjdp#endif /* OBJ_COFF */ 284777298Sobrien } 284833965Sjdp 284933965Sjdp symbol_table_insert (symbolP); 285033965Sjdp 285133965Sjdp *end_name = delim; 285233965Sjdp 285333965Sjdp if (equiv 285433965Sjdp && S_IS_DEFINED (symbolP) 285533965Sjdp && S_GET_SEGMENT (symbolP) != reg_section) 285689857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 285733965Sjdp 285833965Sjdp pseudo_set (symbolP); 285933965Sjdp demand_empty_rest_of_line (); 286077298Sobrien} 286133965Sjdp 286277298Sobrienvoid 286333965Sjdps_space (mult) 286433965Sjdp int mult; 286533965Sjdp{ 286633965Sjdp expressionS exp; 286733965Sjdp expressionS val; 286833965Sjdp char *p = 0; 286933965Sjdp char *stop = NULL; 287033965Sjdp char stopc; 287133965Sjdp int bytes; 287233965Sjdp 287333965Sjdp#ifdef md_flush_pending_output 287433965Sjdp md_flush_pending_output (); 287533965Sjdp#endif 287633965Sjdp 287733965Sjdp if (flag_mri) 287833965Sjdp stop = mri_comment_field (&stopc); 287933965Sjdp 288033965Sjdp /* In m68k MRI mode, we need to align to a word boundary, unless 288133965Sjdp this is ds.b. */ 288233965Sjdp if (flag_m68k_mri && mult > 1) 288333965Sjdp { 288433965Sjdp if (now_seg == absolute_section) 288533965Sjdp { 288633965Sjdp abs_section_offset += abs_section_offset & 1; 288733965Sjdp if (line_label != NULL) 288833965Sjdp S_SET_VALUE (line_label, abs_section_offset); 288933965Sjdp } 289033965Sjdp else if (mri_common_symbol != NULL) 289133965Sjdp { 289233965Sjdp valueT val; 289333965Sjdp 289433965Sjdp val = S_GET_VALUE (mri_common_symbol); 289533965Sjdp if ((val & 1) != 0) 289633965Sjdp { 289733965Sjdp S_SET_VALUE (mri_common_symbol, val + 1); 289833965Sjdp if (line_label != NULL) 289933965Sjdp { 290060484Sobrien expressionS *symexp; 290160484Sobrien 290260484Sobrien symexp = symbol_get_value_expression (line_label); 290360484Sobrien know (symexp->X_op == O_symbol); 290460484Sobrien know (symexp->X_add_symbol == mri_common_symbol); 290560484Sobrien symexp->X_add_number += 1; 290633965Sjdp } 290733965Sjdp } 290833965Sjdp } 290933965Sjdp else 291033965Sjdp { 291133965Sjdp do_align (1, (char *) NULL, 0, 0); 291233965Sjdp if (line_label != NULL) 291333965Sjdp { 291460484Sobrien symbol_set_frag (line_label, frag_now); 291533965Sjdp S_SET_VALUE (line_label, frag_now_fix ()); 291633965Sjdp } 291733965Sjdp } 291833965Sjdp } 291933965Sjdp 292033965Sjdp bytes = mult; 292133965Sjdp 292233965Sjdp expression (&exp); 292333965Sjdp 292433965Sjdp SKIP_WHITESPACE (); 292533965Sjdp if (*input_line_pointer == ',') 292633965Sjdp { 292733965Sjdp ++input_line_pointer; 292833965Sjdp expression (&val); 292933965Sjdp } 293033965Sjdp else 293133965Sjdp { 293233965Sjdp val.X_op = O_constant; 293333965Sjdp val.X_add_number = 0; 293433965Sjdp } 293533965Sjdp 293633965Sjdp if (val.X_op != O_constant 293733965Sjdp || val.X_add_number < - 0x80 293833965Sjdp || val.X_add_number > 0xff 293933965Sjdp || (mult != 0 && mult != 1 && val.X_add_number != 0)) 294033965Sjdp { 294133965Sjdp if (exp.X_op != O_constant) 294289857Sobrien as_bad (_("unsupported variable size or fill value")); 294333965Sjdp else 294433965Sjdp { 294533965Sjdp offsetT i; 294633965Sjdp 294733965Sjdp if (mult == 0) 294833965Sjdp mult = 1; 294933965Sjdp bytes = mult * exp.X_add_number; 295033965Sjdp for (i = 0; i < exp.X_add_number; i++) 295133965Sjdp emit_expr (&val, mult); 295233965Sjdp } 295333965Sjdp } 295433965Sjdp else 295533965Sjdp { 295633965Sjdp if (exp.X_op == O_constant) 295733965Sjdp { 295833965Sjdp long repeat; 295933965Sjdp 296033965Sjdp repeat = exp.X_add_number; 296133965Sjdp if (mult) 296233965Sjdp repeat *= mult; 296333965Sjdp bytes = repeat; 296433965Sjdp if (repeat <= 0) 296533965Sjdp { 296677298Sobrien if (!flag_mri) 296760484Sobrien as_warn (_(".space repeat count is zero, ignored")); 296860484Sobrien else if (repeat < 0) 296960484Sobrien as_warn (_(".space repeat count is negative, ignored")); 297033965Sjdp goto getout; 297133965Sjdp } 297233965Sjdp 297333965Sjdp /* If we are in the absolute section, just bump the offset. */ 297433965Sjdp if (now_seg == absolute_section) 297533965Sjdp { 297633965Sjdp abs_section_offset += repeat; 297733965Sjdp goto getout; 297833965Sjdp } 297933965Sjdp 298033965Sjdp /* If we are secretly in an MRI common section, then 298133965Sjdp creating space just increases the size of the common 298233965Sjdp symbol. */ 298333965Sjdp if (mri_common_symbol != NULL) 298433965Sjdp { 298533965Sjdp S_SET_VALUE (mri_common_symbol, 298633965Sjdp S_GET_VALUE (mri_common_symbol) + repeat); 298733965Sjdp goto getout; 298833965Sjdp } 298933965Sjdp 299033965Sjdp if (!need_pass_2) 299133965Sjdp p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, 299233965Sjdp (offsetT) repeat, (char *) 0); 299333965Sjdp } 299433965Sjdp else 299533965Sjdp { 299633965Sjdp if (now_seg == absolute_section) 299733965Sjdp { 299860484Sobrien as_bad (_("space allocation too complex in absolute section")); 299933965Sjdp subseg_set (text_section, 0); 300033965Sjdp } 300177298Sobrien 300233965Sjdp if (mri_common_symbol != NULL) 300333965Sjdp { 300460484Sobrien as_bad (_("space allocation too complex in common section")); 300533965Sjdp mri_common_symbol = NULL; 300633965Sjdp } 300777298Sobrien 300833965Sjdp if (!need_pass_2) 300933965Sjdp p = frag_var (rs_space, 1, 1, (relax_substateT) 0, 301033965Sjdp make_expr_symbol (&exp), (offsetT) 0, (char *) 0); 301133965Sjdp } 301233965Sjdp 301333965Sjdp if (p) 301433965Sjdp *p = val.X_add_number; 301533965Sjdp } 301633965Sjdp 301733965Sjdp getout: 301833965Sjdp 301933965Sjdp /* In MRI mode, after an odd number of bytes, we must align to an 302033965Sjdp even word boundary, unless the next instruction is a dc.b, ds.b 302133965Sjdp or dcb.b. */ 302233965Sjdp if (flag_mri && (bytes & 1) != 0) 302333965Sjdp mri_pending_align = 1; 302433965Sjdp 302560484Sobrien demand_empty_rest_of_line (); 302660484Sobrien 302733965Sjdp if (flag_mri) 302833965Sjdp mri_comment_end (stop, stopc); 302933965Sjdp} 303033965Sjdp 303133965Sjdp/* This is like s_space, but the value is a floating point number with 303233965Sjdp the given precision. This is for the MRI dcb.s pseudo-op and 303333965Sjdp friends. */ 303433965Sjdp 303533965Sjdpvoid 303633965Sjdps_float_space (float_type) 303733965Sjdp int float_type; 303833965Sjdp{ 303933965Sjdp offsetT count; 304033965Sjdp int flen; 304133965Sjdp char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 304233965Sjdp char *stop = NULL; 304333965Sjdp char stopc; 304433965Sjdp 304533965Sjdp if (flag_mri) 304633965Sjdp stop = mri_comment_field (&stopc); 304733965Sjdp 304833965Sjdp count = get_absolute_expression (); 304933965Sjdp 305033965Sjdp SKIP_WHITESPACE (); 305133965Sjdp if (*input_line_pointer != ',') 305233965Sjdp { 305360484Sobrien as_bad (_("missing value")); 305460484Sobrien ignore_rest_of_line (); 305533965Sjdp if (flag_mri) 305633965Sjdp mri_comment_end (stop, stopc); 305733965Sjdp return; 305833965Sjdp } 305933965Sjdp 306033965Sjdp ++input_line_pointer; 306133965Sjdp 306233965Sjdp SKIP_WHITESPACE (); 306333965Sjdp 306433965Sjdp /* Skip any 0{letter} that may be present. Don't even check if the 306533965Sjdp * letter is legal. */ 306638889Sjdp if (input_line_pointer[0] == '0' 306789857Sobrien && ISALPHA (input_line_pointer[1])) 306833965Sjdp input_line_pointer += 2; 306933965Sjdp 307033965Sjdp /* Accept :xxxx, where the x's are hex digits, for a floating point 307133965Sjdp with the exact digits specified. */ 307233965Sjdp if (input_line_pointer[0] == ':') 307333965Sjdp { 307433965Sjdp flen = hex_float (float_type, temp); 307533965Sjdp if (flen < 0) 307633965Sjdp { 307760484Sobrien ignore_rest_of_line (); 307833965Sjdp if (flag_mri) 307933965Sjdp mri_comment_end (stop, stopc); 308033965Sjdp return; 308133965Sjdp } 308233965Sjdp } 308333965Sjdp else 308433965Sjdp { 308533965Sjdp char *err; 308633965Sjdp 308733965Sjdp err = md_atof (float_type, temp, &flen); 308833965Sjdp know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 308933965Sjdp know (flen > 0); 309033965Sjdp if (err) 309133965Sjdp { 309289857Sobrien as_bad (_("bad floating literal: %s"), err); 309360484Sobrien ignore_rest_of_line (); 309433965Sjdp if (flag_mri) 309533965Sjdp mri_comment_end (stop, stopc); 309633965Sjdp return; 309733965Sjdp } 309833965Sjdp } 309933965Sjdp 310033965Sjdp while (--count >= 0) 310133965Sjdp { 310233965Sjdp char *p; 310333965Sjdp 310433965Sjdp p = frag_more (flen); 310533965Sjdp memcpy (p, temp, (unsigned int) flen); 310633965Sjdp } 310733965Sjdp 310860484Sobrien demand_empty_rest_of_line (); 310960484Sobrien 311033965Sjdp if (flag_mri) 311133965Sjdp mri_comment_end (stop, stopc); 311233965Sjdp} 311333965Sjdp 311433965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers. */ 311533965Sjdp 311633965Sjdpvoid 311733965Sjdps_struct (ignore) 311860484Sobrien int ignore ATTRIBUTE_UNUSED; 311933965Sjdp{ 312033965Sjdp char *stop = NULL; 312133965Sjdp char stopc; 312233965Sjdp 312333965Sjdp if (flag_mri) 312433965Sjdp stop = mri_comment_field (&stopc); 312533965Sjdp abs_section_offset = get_absolute_expression (); 312633965Sjdp subseg_set (absolute_section, 0); 312760484Sobrien demand_empty_rest_of_line (); 312833965Sjdp if (flag_mri) 312933965Sjdp mri_comment_end (stop, stopc); 313033965Sjdp} 313133965Sjdp 313233965Sjdpvoid 313333965Sjdps_text (ignore) 313460484Sobrien int ignore ATTRIBUTE_UNUSED; 313533965Sjdp{ 313633965Sjdp register int temp; 313733965Sjdp 313833965Sjdp temp = get_absolute_expression (); 313933965Sjdp subseg_set (text_section, (subsegT) temp); 314033965Sjdp demand_empty_rest_of_line (); 314133965Sjdp#ifdef OBJ_VMS 314233965Sjdp const_flag &= ~IN_DEFAULT_SECTION; 314333965Sjdp#endif 314477298Sobrien} 314533965Sjdp 314677298Sobrienvoid 314733965Sjdpdemand_empty_rest_of_line () 314833965Sjdp{ 314933965Sjdp SKIP_WHITESPACE (); 315033965Sjdp if (is_end_of_line[(unsigned char) *input_line_pointer]) 315177298Sobrien input_line_pointer++; 315233965Sjdp else 315377298Sobrien ignore_rest_of_line (); 315433965Sjdp 315577298Sobrien /* Return having already swallowed end-of-line. */ 315677298Sobrien} 315777298Sobrien 315833965Sjdpvoid 315977298Sobrienignore_rest_of_line () 316033965Sjdp{ 316177298Sobrien /* For suspect lines: gives warning. */ 316233965Sjdp if (!is_end_of_line[(unsigned char) *input_line_pointer]) 316333965Sjdp { 316489857Sobrien if (ISPRINT (*input_line_pointer)) 316589857Sobrien as_warn (_("rest of line ignored; first ignored character is `%c'"), 316689857Sobrien *input_line_pointer); 316733965Sjdp else 316889857Sobrien as_warn (_("rest of line ignored; first ignored character valued 0x%x"), 316989857Sobrien *input_line_pointer); 317077298Sobrien 317133965Sjdp while (input_line_pointer < buffer_limit 317233965Sjdp && !is_end_of_line[(unsigned char) *input_line_pointer]) 317377298Sobrien input_line_pointer++; 317433965Sjdp } 317577298Sobrien 317677298Sobrien input_line_pointer++; 317777298Sobrien 317877298Sobrien /* Return pointing just after end-of-line. */ 317933965Sjdp know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 318033965Sjdp} 318133965Sjdp 318260484Sobrienvoid 318360484Sobriendiscard_rest_of_line () 318460484Sobrien{ 318560484Sobrien while (input_line_pointer < buffer_limit 318677298Sobrien && !is_end_of_line[(unsigned char) *input_line_pointer]) 318777298Sobrien input_line_pointer++; 318877298Sobrien 318977298Sobrien input_line_pointer++; 319077298Sobrien 319177298Sobrien /* Return pointing just after end-of-line. */ 319260484Sobrien know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 319360484Sobrien} 319460484Sobrien 319577298Sobrien/* In: Pointer to a symbol. 319677298Sobrien Input_line_pointer->expression. 319777298Sobrien 319877298Sobrien Out: Input_line_pointer->just after any whitespace after expression. 319977298Sobrien Tried to set symbol to value of expression. 320077298Sobrien Will change symbols type, value, and frag; */ 320177298Sobrien 320233965Sjdpvoid 320333965Sjdppseudo_set (symbolP) 320433965Sjdp symbolS *symbolP; 320533965Sjdp{ 320633965Sjdp expressionS exp; 320733965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 320833965Sjdp int ext; 320933965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 321033965Sjdp 321177298Sobrien know (symbolP); /* NULL pointer is logic error. */ 321233965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 321333965Sjdp ext = S_IS_EXTERNAL (symbolP); 321433965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 321533965Sjdp 321633965Sjdp (void) expression (&exp); 321733965Sjdp 321833965Sjdp if (exp.X_op == O_illegal) 321989857Sobrien as_bad (_("illegal expression")); 322033965Sjdp else if (exp.X_op == O_absent) 322189857Sobrien as_bad (_("missing expression")); 322233965Sjdp else if (exp.X_op == O_big) 322360484Sobrien { 322460484Sobrien if (exp.X_add_number > 0) 322589857Sobrien as_bad (_("bignum invalid")); 322660484Sobrien else 322789857Sobrien as_bad (_("floating point number invalid")); 322860484Sobrien } 322933965Sjdp else if (exp.X_op == O_subtract 323033965Sjdp && (S_GET_SEGMENT (exp.X_add_symbol) 323133965Sjdp == S_GET_SEGMENT (exp.X_op_symbol)) 323233965Sjdp && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol)) 323360484Sobrien && (symbol_get_frag (exp.X_add_symbol) 323460484Sobrien == symbol_get_frag (exp.X_op_symbol))) 323533965Sjdp { 323633965Sjdp exp.X_op = O_constant; 323733965Sjdp exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol) 323833965Sjdp - S_GET_VALUE (exp.X_op_symbol)); 323933965Sjdp } 324033965Sjdp 324133965Sjdp switch (exp.X_op) 324233965Sjdp { 324333965Sjdp case O_illegal: 324433965Sjdp case O_absent: 324533965Sjdp case O_big: 324633965Sjdp exp.X_add_number = 0; 324733965Sjdp /* Fall through. */ 324833965Sjdp case O_constant: 324933965Sjdp S_SET_SEGMENT (symbolP, absolute_section); 325033965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 325133965Sjdp if (ext) 325233965Sjdp S_SET_EXTERNAL (symbolP); 325333965Sjdp else 325433965Sjdp S_CLEAR_EXTERNAL (symbolP); 325533965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 325633965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 325738889Sjdp if (exp.X_op != O_constant) 325877298Sobrien symbol_set_frag (symbolP, &zero_address_frag); 325933965Sjdp break; 326033965Sjdp 326133965Sjdp case O_register: 326233965Sjdp S_SET_SEGMENT (symbolP, reg_section); 326333965Sjdp S_SET_VALUE (symbolP, (valueT) exp.X_add_number); 326460484Sobrien symbol_set_frag (symbolP, &zero_address_frag); 326533965Sjdp break; 326633965Sjdp 326733965Sjdp case O_symbol: 326833965Sjdp if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section 326933965Sjdp || exp.X_add_number != 0) 327060484Sobrien symbol_set_value_expression (symbolP, &exp); 327160484Sobrien else if (symbol_section_p (symbolP)) 327289857Sobrien as_bad ("attempt to set value of section symbol"); 327333965Sjdp else 327433965Sjdp { 327533965Sjdp symbolS *s = exp.X_add_symbol; 327633965Sjdp 327733965Sjdp S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s)); 327833965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) 327933965Sjdp if (ext) 328033965Sjdp S_SET_EXTERNAL (symbolP); 328133965Sjdp else 328233965Sjdp S_CLEAR_EXTERNAL (symbolP); 328333965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */ 328433965Sjdp S_SET_VALUE (symbolP, 328533965Sjdp exp.X_add_number + S_GET_VALUE (s)); 328660484Sobrien symbol_set_frag (symbolP, symbol_get_frag (s)); 328733965Sjdp copy_symbol_attributes (symbolP, s); 328833965Sjdp } 328933965Sjdp break; 329033965Sjdp 329133965Sjdp default: 329233965Sjdp /* The value is some complex expression. 329333965Sjdp FIXME: Should we set the segment to anything? */ 329460484Sobrien symbol_set_value_expression (symbolP, &exp); 329533965Sjdp break; 329633965Sjdp } 329733965Sjdp} 329833965Sjdp 329977298Sobrien/* cons() 330033965Sjdp 330177298Sobrien CONStruct more frag of .bytes, or .words etc. 330277298Sobrien Should need_pass_2 be 1 then emit no frag(s). 330377298Sobrien This understands EXPRESSIONS. 330477298Sobrien 330577298Sobrien Bug (?) 330677298Sobrien 330777298Sobrien This has a split personality. We use expression() to read the 330877298Sobrien value. We can detect if the value won't fit in a byte or word. 330977298Sobrien But we can't detect if expression() discarded significant digits 331077298Sobrien in the case of a long. Not worth the crocks required to fix it. */ 331177298Sobrien 331233965Sjdp/* Select a parser for cons expressions. */ 331333965Sjdp 331433965Sjdp/* Some targets need to parse the expression in various fancy ways. 331533965Sjdp You can define TC_PARSE_CONS_EXPRESSION to do whatever you like 331633965Sjdp (for example, the HPPA does this). Otherwise, you can define 331733965Sjdp BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or 331833965Sjdp REPEAT_CONS_EXPRESSIONS to permit repeat counts. If none of these 331933965Sjdp are defined, which is the normal case, then only simple expressions 332033965Sjdp are permitted. */ 332133965Sjdp 332260484Sobrien#ifdef TC_M68K 332333965Sjdpstatic void 332433965Sjdpparse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes)); 332560484Sobrien#endif 332633965Sjdp 332733965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION 332833965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS 332933965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES) 333077298Sobrienstatic void 333133965Sjdpparse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes)); 333233965Sjdp#endif 333333965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 333433965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES) 333533965Sjdpstatic void 333633965Sjdpparse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes)); 333733965Sjdp#endif 333833965Sjdp 333933965Sjdp/* If we haven't gotten one yet, just call expression. */ 334033965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION 334133965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP) 334233965Sjdp#endif 334333965Sjdp#endif 334433965Sjdp 334577298Sobrien/* Worker to do .byte etc statements. 334677298Sobrien Clobbers input_line_pointer and checks end-of-line. */ 334777298Sobrien 334877298Sobrienstatic void 334933965Sjdpcons_worker (nbytes, rva) 335077298Sobrien register int nbytes; /* 1=.byte, 2=.word, 4=.long. */ 335133965Sjdp int rva; 335233965Sjdp{ 335333965Sjdp int c; 335433965Sjdp expressionS exp; 335533965Sjdp char *stop = NULL; 335633965Sjdp char stopc; 335733965Sjdp 335833965Sjdp#ifdef md_flush_pending_output 335933965Sjdp md_flush_pending_output (); 336033965Sjdp#endif 336133965Sjdp 336233965Sjdp if (flag_mri) 336333965Sjdp stop = mri_comment_field (&stopc); 336433965Sjdp 336533965Sjdp if (is_it_end_of_statement ()) 336633965Sjdp { 336760484Sobrien demand_empty_rest_of_line (); 336833965Sjdp if (flag_mri) 336933965Sjdp mri_comment_end (stop, stopc); 337033965Sjdp return; 337133965Sjdp } 337233965Sjdp 337333965Sjdp#ifdef md_cons_align 337433965Sjdp md_cons_align (nbytes); 337533965Sjdp#endif 337633965Sjdp 337733965Sjdp c = 0; 337833965Sjdp do 337933965Sjdp { 338060484Sobrien#ifdef TC_M68K 338133965Sjdp if (flag_m68k_mri) 338233965Sjdp parse_mri_cons (&exp, (unsigned int) nbytes); 338333965Sjdp else 338460484Sobrien#endif 338533965Sjdp TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); 338633965Sjdp 338733965Sjdp if (rva) 338833965Sjdp { 338933965Sjdp if (exp.X_op == O_symbol) 339033965Sjdp exp.X_op = O_symbol_rva; 339133965Sjdp else 339260484Sobrien as_fatal (_("rva without symbol")); 339333965Sjdp } 339433965Sjdp emit_expr (&exp, (unsigned int) nbytes); 339533965Sjdp ++c; 339633965Sjdp } 339733965Sjdp while (*input_line_pointer++ == ','); 339833965Sjdp 339933965Sjdp /* In MRI mode, after an odd number of bytes, we must align to an 340033965Sjdp even word boundary, unless the next instruction is a dc.b, ds.b 340133965Sjdp or dcb.b. */ 340233965Sjdp if (flag_mri && nbytes == 1 && (c & 1) != 0) 340333965Sjdp mri_pending_align = 1; 340433965Sjdp 340577298Sobrien input_line_pointer--; /* Put terminator back into stream. */ 340633965Sjdp 340760484Sobrien demand_empty_rest_of_line (); 340860484Sobrien 340933965Sjdp if (flag_mri) 341033965Sjdp mri_comment_end (stop, stopc); 341133965Sjdp} 341233965Sjdp 341333965Sjdpvoid 341433965Sjdpcons (size) 341533965Sjdp int size; 341633965Sjdp{ 341733965Sjdp cons_worker (size, 0); 341833965Sjdp} 341933965Sjdp 342077298Sobrienvoid 342133965Sjdps_rva (size) 342233965Sjdp int size; 342333965Sjdp{ 342433965Sjdp cons_worker (size, 1); 342533965Sjdp} 342633965Sjdp 342733965Sjdp/* Put the contents of expression EXP into the object file using 342833965Sjdp NBYTES bytes. If need_pass_2 is 1, this does nothing. */ 342933965Sjdp 343033965Sjdpvoid 343133965Sjdpemit_expr (exp, nbytes) 343233965Sjdp expressionS *exp; 343333965Sjdp unsigned int nbytes; 343433965Sjdp{ 343533965Sjdp operatorT op; 343633965Sjdp register char *p; 343733965Sjdp valueT extra_digit = 0; 343833965Sjdp 343933965Sjdp /* Don't do anything if we are going to make another pass. */ 344033965Sjdp if (need_pass_2) 344133965Sjdp return; 344233965Sjdp 344338889Sjdp#ifndef NO_LISTING 344438889Sjdp#ifdef OBJ_ELF 344538889Sjdp /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will 344638889Sjdp appear as a four byte positive constant in the .line section, 344738889Sjdp followed by a 2 byte 0xffff. Look for that case here. */ 344838889Sjdp { 344938889Sjdp static int dwarf_line = -1; 345038889Sjdp 345138889Sjdp if (strcmp (segment_name (now_seg), ".line") != 0) 345238889Sjdp dwarf_line = -1; 345338889Sjdp else if (dwarf_line >= 0 345438889Sjdp && nbytes == 2 345538889Sjdp && exp->X_op == O_constant 345638889Sjdp && (exp->X_add_number == -1 || exp->X_add_number == 0xffff)) 345738889Sjdp listing_source_line ((unsigned int) dwarf_line); 345838889Sjdp else if (nbytes == 4 345938889Sjdp && exp->X_op == O_constant 346038889Sjdp && exp->X_add_number >= 0) 346138889Sjdp dwarf_line = exp->X_add_number; 346238889Sjdp else 346338889Sjdp dwarf_line = -1; 346438889Sjdp } 346538889Sjdp 346638889Sjdp /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will 346738889Sjdp appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte 346838889Sjdp AT_sibling (0x12) followed by a four byte address of the sibling 346938889Sjdp followed by a 2 byte AT_name (0x38) followed by the name of the 347038889Sjdp file. We look for that case here. */ 347138889Sjdp { 347238889Sjdp static int dwarf_file = 0; 347338889Sjdp 347438889Sjdp if (strcmp (segment_name (now_seg), ".debug") != 0) 347538889Sjdp dwarf_file = 0; 347638889Sjdp else if (dwarf_file == 0 347738889Sjdp && nbytes == 2 347838889Sjdp && exp->X_op == O_constant 347938889Sjdp && exp->X_add_number == 0x11) 348038889Sjdp dwarf_file = 1; 348138889Sjdp else if (dwarf_file == 1 348238889Sjdp && nbytes == 2 348338889Sjdp && exp->X_op == O_constant 348438889Sjdp && exp->X_add_number == 0x12) 348538889Sjdp dwarf_file = 2; 348638889Sjdp else if (dwarf_file == 2 348738889Sjdp && nbytes == 4) 348838889Sjdp dwarf_file = 3; 348938889Sjdp else if (dwarf_file == 3 349038889Sjdp && nbytes == 2 349138889Sjdp && exp->X_op == O_constant 349238889Sjdp && exp->X_add_number == 0x38) 349338889Sjdp dwarf_file = 4; 349438889Sjdp else 349538889Sjdp dwarf_file = 0; 349638889Sjdp 349738889Sjdp /* The variable dwarf_file_string tells stringer that the string 349838889Sjdp may be the name of the source file. */ 349938889Sjdp if (dwarf_file == 4) 350038889Sjdp dwarf_file_string = 1; 350138889Sjdp else 350238889Sjdp dwarf_file_string = 0; 350338889Sjdp } 350438889Sjdp#endif 350538889Sjdp#endif 350638889Sjdp 350738889Sjdp if (check_eh_frame (exp, &nbytes)) 350838889Sjdp return; 350938889Sjdp 351033965Sjdp op = exp->X_op; 351133965Sjdp 351233965Sjdp /* Allow `.word 0' in the absolute section. */ 351333965Sjdp if (now_seg == absolute_section) 351433965Sjdp { 351533965Sjdp if (op != O_constant || exp->X_add_number != 0) 351660484Sobrien as_bad (_("attempt to store value in absolute section")); 351733965Sjdp abs_section_offset += nbytes; 351833965Sjdp return; 351933965Sjdp } 352033965Sjdp 352133965Sjdp /* Handle a negative bignum. */ 352233965Sjdp if (op == O_uminus 352333965Sjdp && exp->X_add_number == 0 352460484Sobrien && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big 352560484Sobrien && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0) 352633965Sjdp { 352733965Sjdp int i; 352833965Sjdp unsigned long carry; 352933965Sjdp 353060484Sobrien exp = symbol_get_value_expression (exp->X_add_symbol); 353133965Sjdp 353233965Sjdp /* Negate the bignum: one's complement each digit and add 1. */ 353333965Sjdp carry = 1; 353433965Sjdp for (i = 0; i < exp->X_add_number; i++) 353533965Sjdp { 353633965Sjdp unsigned long next; 353733965Sjdp 353877298Sobrien next = (((~(generic_bignum[i] & LITTLENUM_MASK)) 353933965Sjdp & LITTLENUM_MASK) 354033965Sjdp + carry); 354133965Sjdp generic_bignum[i] = next & LITTLENUM_MASK; 354233965Sjdp carry = next >> LITTLENUM_NUMBER_OF_BITS; 354333965Sjdp } 354433965Sjdp 354533965Sjdp /* We can ignore any carry out, because it will be handled by 354633965Sjdp extra_digit if it is needed. */ 354733965Sjdp 354833965Sjdp extra_digit = (valueT) -1; 354933965Sjdp op = O_big; 355033965Sjdp } 355133965Sjdp 355233965Sjdp if (op == O_absent || op == O_illegal) 355333965Sjdp { 355460484Sobrien as_warn (_("zero assumed for missing expression")); 355533965Sjdp exp->X_add_number = 0; 355633965Sjdp op = O_constant; 355733965Sjdp } 355833965Sjdp else if (op == O_big && exp->X_add_number <= 0) 355933965Sjdp { 356089857Sobrien as_bad (_("floating point number invalid")); 356133965Sjdp exp->X_add_number = 0; 356233965Sjdp op = O_constant; 356333965Sjdp } 356433965Sjdp else if (op == O_register) 356533965Sjdp { 356660484Sobrien as_warn (_("register value used as expression")); 356733965Sjdp op = O_constant; 356833965Sjdp } 356933965Sjdp 357033965Sjdp p = frag_more ((int) nbytes); 357133965Sjdp 357233965Sjdp#ifndef WORKING_DOT_WORD 357333965Sjdp /* If we have the difference of two symbols in a word, save it on 357433965Sjdp the broken_words list. See the code in write.c. */ 357533965Sjdp if (op == O_subtract && nbytes == 2) 357633965Sjdp { 357733965Sjdp struct broken_word *x; 357833965Sjdp 357933965Sjdp x = (struct broken_word *) xmalloc (sizeof (struct broken_word)); 358033965Sjdp x->next_broken_word = broken_words; 358133965Sjdp broken_words = x; 358260484Sobrien x->seg = now_seg; 358360484Sobrien x->subseg = now_subseg; 358433965Sjdp x->frag = frag_now; 358533965Sjdp x->word_goes_here = p; 358633965Sjdp x->dispfrag = 0; 358733965Sjdp x->add = exp->X_add_symbol; 358833965Sjdp x->sub = exp->X_op_symbol; 358933965Sjdp x->addnum = exp->X_add_number; 359033965Sjdp x->added = 0; 359133965Sjdp new_broken_words++; 359233965Sjdp return; 359333965Sjdp } 359433965Sjdp#endif 359533965Sjdp 359633965Sjdp /* If we have an integer, but the number of bytes is too large to 359733965Sjdp pass to md_number_to_chars, handle it as a bignum. */ 359833965Sjdp if (op == O_constant && nbytes > sizeof (valueT)) 359933965Sjdp { 360033965Sjdp valueT val; 360133965Sjdp int gencnt; 360233965Sjdp 360377298Sobrien if (!exp->X_unsigned && exp->X_add_number < 0) 360433965Sjdp extra_digit = (valueT) -1; 360533965Sjdp val = (valueT) exp->X_add_number; 360633965Sjdp gencnt = 0; 360733965Sjdp do 360833965Sjdp { 360933965Sjdp generic_bignum[gencnt] = val & LITTLENUM_MASK; 361033965Sjdp val >>= LITTLENUM_NUMBER_OF_BITS; 361133965Sjdp ++gencnt; 361233965Sjdp } 361333965Sjdp while (val != 0); 361433965Sjdp op = exp->X_op = O_big; 361533965Sjdp exp->X_add_number = gencnt; 361633965Sjdp } 361733965Sjdp 361833965Sjdp if (op == O_constant) 361933965Sjdp { 362033965Sjdp register valueT get; 362133965Sjdp register valueT use; 362233965Sjdp register valueT mask; 362333965Sjdp valueT hibit; 362433965Sjdp register valueT unmask; 362533965Sjdp 362633965Sjdp /* JF << of >= number of bits in the object is undefined. In 362777298Sobrien particular SPARC (Sun 4) has problems. */ 362833965Sjdp if (nbytes >= sizeof (valueT)) 362933965Sjdp { 363033965Sjdp mask = 0; 363133965Sjdp if (nbytes > sizeof (valueT)) 363233965Sjdp hibit = 0; 363333965Sjdp else 363433965Sjdp hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); 363533965Sjdp } 363633965Sjdp else 363733965Sjdp { 363877298Sobrien /* Don't store these bits. */ 363933965Sjdp mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); 364033965Sjdp hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1); 364133965Sjdp } 364233965Sjdp 364377298Sobrien unmask = ~mask; /* Do store these bits. */ 364433965Sjdp 364533965Sjdp#ifdef NEVER 364633965Sjdp "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; 364777298Sobrien mask = ~(unmask >> 1); /* Includes sign bit now. */ 364833965Sjdp#endif 364933965Sjdp 365033965Sjdp get = exp->X_add_number; 365133965Sjdp use = get & unmask; 365233965Sjdp if ((get & mask) != 0 365333965Sjdp && ((get & mask) != mask 365433965Sjdp || (get & hibit) == 0)) 365577298Sobrien { /* Leading bits contain both 0s & 1s. */ 365689857Sobrien as_warn (_("value 0x%lx truncated to 0x%lx"), 365733965Sjdp (unsigned long) get, (unsigned long) use); 365833965Sjdp } 365977298Sobrien /* Put bytes in right order. */ 366033965Sjdp md_number_to_chars (p, use, (int) nbytes); 366133965Sjdp } 366233965Sjdp else if (op == O_big) 366333965Sjdp { 366438889Sjdp unsigned int size; 366533965Sjdp LITTLENUM_TYPE *nums; 366633965Sjdp 366733965Sjdp know (nbytes % CHARS_PER_LITTLENUM == 0); 366833965Sjdp 366933965Sjdp size = exp->X_add_number * CHARS_PER_LITTLENUM; 367033965Sjdp if (nbytes < size) 367133965Sjdp { 367289857Sobrien as_warn (_("bignum truncated to %d bytes"), nbytes); 367333965Sjdp size = nbytes; 367433965Sjdp } 367533965Sjdp 367633965Sjdp if (target_big_endian) 367733965Sjdp { 367833965Sjdp while (nbytes > size) 367933965Sjdp { 368033965Sjdp md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); 368133965Sjdp nbytes -= CHARS_PER_LITTLENUM; 368233965Sjdp p += CHARS_PER_LITTLENUM; 368333965Sjdp } 368433965Sjdp 368533965Sjdp nums = generic_bignum + size / CHARS_PER_LITTLENUM; 368689857Sobrien while (size >= CHARS_PER_LITTLENUM) 368733965Sjdp { 368833965Sjdp --nums; 368933965Sjdp md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); 369033965Sjdp size -= CHARS_PER_LITTLENUM; 369133965Sjdp p += CHARS_PER_LITTLENUM; 369233965Sjdp } 369333965Sjdp } 369433965Sjdp else 369533965Sjdp { 369633965Sjdp nums = generic_bignum; 369789857Sobrien while (size >= CHARS_PER_LITTLENUM) 369833965Sjdp { 369933965Sjdp md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); 370033965Sjdp ++nums; 370133965Sjdp size -= CHARS_PER_LITTLENUM; 370233965Sjdp p += CHARS_PER_LITTLENUM; 370333965Sjdp nbytes -= CHARS_PER_LITTLENUM; 370433965Sjdp } 370533965Sjdp 370689857Sobrien while (nbytes >= CHARS_PER_LITTLENUM) 370733965Sjdp { 370833965Sjdp md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); 370933965Sjdp nbytes -= CHARS_PER_LITTLENUM; 371033965Sjdp p += CHARS_PER_LITTLENUM; 371133965Sjdp } 371233965Sjdp } 371333965Sjdp } 371433965Sjdp else 371533965Sjdp { 371633965Sjdp memset (p, 0, nbytes); 371733965Sjdp 371833965Sjdp /* Now we need to generate a fixS to record the symbol value. 371933965Sjdp This is easy for BFD. For other targets it can be more 372033965Sjdp complex. For very complex cases (currently, the HPPA and 372133965Sjdp NS32K), you can define TC_CONS_FIX_NEW to do whatever you 372233965Sjdp want. For simpler cases, you can define TC_CONS_RELOC to be 372333965Sjdp the name of the reloc code that should be stored in the fixS. 372433965Sjdp If neither is defined, the code uses NO_RELOC if it is 372533965Sjdp defined, and otherwise uses 0. */ 372633965Sjdp 372733965Sjdp#ifdef BFD_ASSEMBLER 372833965Sjdp#ifdef TC_CONS_FIX_NEW 372933965Sjdp TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp); 373033965Sjdp#else 373133965Sjdp { 373233965Sjdp bfd_reloc_code_real_type r; 373333965Sjdp 373433965Sjdp switch (nbytes) 373533965Sjdp { 373633965Sjdp case 1: 373733965Sjdp r = BFD_RELOC_8; 373833965Sjdp break; 373933965Sjdp case 2: 374033965Sjdp r = BFD_RELOC_16; 374133965Sjdp break; 374233965Sjdp case 4: 374333965Sjdp r = BFD_RELOC_32; 374433965Sjdp break; 374533965Sjdp case 8: 374633965Sjdp r = BFD_RELOC_64; 374733965Sjdp break; 374833965Sjdp default: 374960484Sobrien as_bad (_("unsupported BFD relocation size %u"), nbytes); 375033965Sjdp r = BFD_RELOC_32; 375133965Sjdp break; 375233965Sjdp } 375333965Sjdp fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 375433965Sjdp 0, r); 375533965Sjdp } 375633965Sjdp#endif 375733965Sjdp#else 375833965Sjdp#ifdef TC_CONS_FIX_NEW 375933965Sjdp TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp); 376033965Sjdp#else 376133965Sjdp /* Figure out which reloc number to use. Use TC_CONS_RELOC if 376233965Sjdp it is defined, otherwise use NO_RELOC if it is defined, 376333965Sjdp otherwise use 0. */ 376433965Sjdp#ifndef TC_CONS_RELOC 376533965Sjdp#ifdef NO_RELOC 376633965Sjdp#define TC_CONS_RELOC NO_RELOC 376733965Sjdp#else 376833965Sjdp#define TC_CONS_RELOC 0 376933965Sjdp#endif 377033965Sjdp#endif 377133965Sjdp fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0, 377233965Sjdp TC_CONS_RELOC); 377333965Sjdp#endif /* TC_CONS_FIX_NEW */ 377433965Sjdp#endif /* BFD_ASSEMBLER */ 377533965Sjdp } 377633965Sjdp} 377733965Sjdp 377833965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS 377933965Sjdp 378033965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as 378133965Sjdp w:x,y:z, where w and y are bitwidths and x and y are values. They 378233965Sjdp then pack them all together. We do a little better in that we allow 378333965Sjdp them in words, longs, etc. and we'll pack them in target byte order 378433965Sjdp for you. 378533965Sjdp 378633965Sjdp The rules are: pack least significat bit first, if a field doesn't 378733965Sjdp entirely fit, put it in the next unit. Overflowing the bitfield is 378833965Sjdp explicitly *not* even a warning. The bitwidth should be considered 378933965Sjdp a "mask". 379033965Sjdp 379133965Sjdp To use this function the tc-XXX.h file should define 379233965Sjdp BITFIELD_CONS_EXPRESSIONS. */ 379333965Sjdp 379477298Sobrienstatic void 379533965Sjdpparse_bitfield_cons (exp, nbytes) 379633965Sjdp expressionS *exp; 379733965Sjdp unsigned int nbytes; 379833965Sjdp{ 379933965Sjdp unsigned int bits_available = BITS_PER_CHAR * nbytes; 380033965Sjdp char *hold = input_line_pointer; 380133965Sjdp 380233965Sjdp (void) expression (exp); 380333965Sjdp 380433965Sjdp if (*input_line_pointer == ':') 380577298Sobrien { 380677298Sobrien /* Bitfields. */ 380733965Sjdp long value = 0; 380833965Sjdp 380933965Sjdp for (;;) 381033965Sjdp { 381133965Sjdp unsigned long width; 381233965Sjdp 381333965Sjdp if (*input_line_pointer != ':') 381433965Sjdp { 381533965Sjdp input_line_pointer = hold; 381633965Sjdp break; 381777298Sobrien } /* Next piece is not a bitfield. */ 381833965Sjdp 381933965Sjdp /* In the general case, we can't allow 382033965Sjdp full expressions with symbol 382133965Sjdp differences and such. The relocation 382233965Sjdp entries for symbols not defined in this 382333965Sjdp assembly would require arbitrary field 382433965Sjdp widths, positions, and masks which most 382533965Sjdp of our current object formats don't 382633965Sjdp support. 382733965Sjdp 382833965Sjdp In the specific case where a symbol 382933965Sjdp *is* defined in this assembly, we 383033965Sjdp *could* build fixups and track it, but 383133965Sjdp this could lead to confusion for the 383233965Sjdp backends. I'm lazy. I'll take any 383333965Sjdp SEG_ABSOLUTE. I think that means that 383433965Sjdp you can use a previous .set or 383577298Sobrien .equ type symbol. xoxorich. */ 383633965Sjdp 383733965Sjdp if (exp->X_op == O_absent) 383833965Sjdp { 383960484Sobrien as_warn (_("using a bit field width of zero")); 384033965Sjdp exp->X_add_number = 0; 384133965Sjdp exp->X_op = O_constant; 384277298Sobrien } /* Implied zero width bitfield. */ 384333965Sjdp 384433965Sjdp if (exp->X_op != O_constant) 384533965Sjdp { 384633965Sjdp *input_line_pointer = '\0'; 384760484Sobrien as_bad (_("field width \"%s\" too complex for a bitfield"), hold); 384833965Sjdp *input_line_pointer = ':'; 384933965Sjdp demand_empty_rest_of_line (); 385033965Sjdp return; 385177298Sobrien } /* Too complex. */ 385233965Sjdp 385333965Sjdp if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes)) 385433965Sjdp { 385560484Sobrien as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), 385633965Sjdp width, nbytes, (BITS_PER_CHAR * nbytes)); 385733965Sjdp width = BITS_PER_CHAR * nbytes; 385877298Sobrien } /* Too big. */ 385933965Sjdp 386033965Sjdp if (width > bits_available) 386133965Sjdp { 386233965Sjdp /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */ 386333965Sjdp input_line_pointer = hold; 386433965Sjdp exp->X_add_number = value; 386533965Sjdp break; 386677298Sobrien } /* Won't fit. */ 386733965Sjdp 386877298Sobrien /* Skip ':'. */ 386977298Sobrien hold = ++input_line_pointer; 387033965Sjdp 387133965Sjdp (void) expression (exp); 387233965Sjdp if (exp->X_op != O_constant) 387333965Sjdp { 387433965Sjdp char cache = *input_line_pointer; 387533965Sjdp 387633965Sjdp *input_line_pointer = '\0'; 387760484Sobrien as_bad (_("field value \"%s\" too complex for a bitfield"), hold); 387833965Sjdp *input_line_pointer = cache; 387933965Sjdp demand_empty_rest_of_line (); 388033965Sjdp return; 388177298Sobrien } /* Too complex. */ 388233965Sjdp 388333965Sjdp value |= ((~(-1 << width) & exp->X_add_number) 388433965Sjdp << ((BITS_PER_CHAR * nbytes) - bits_available)); 388533965Sjdp 388633965Sjdp if ((bits_available -= width) == 0 388733965Sjdp || is_it_end_of_statement () 388833965Sjdp || *input_line_pointer != ',') 388933965Sjdp { 389033965Sjdp break; 389177298Sobrien } /* All the bitfields we're gonna get. */ 389233965Sjdp 389333965Sjdp hold = ++input_line_pointer; 389433965Sjdp (void) expression (exp); 389577298Sobrien } 389633965Sjdp 389733965Sjdp exp->X_add_number = value; 389833965Sjdp exp->X_op = O_constant; 389933965Sjdp exp->X_unsigned = 1; 390077298Sobrien } 390177298Sobrien} 390233965Sjdp 390333965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */ 390433965Sjdp 390533965Sjdp/* Handle an MRI style string expression. */ 390633965Sjdp 390760484Sobrien#ifdef TC_M68K 390833965Sjdpstatic void 390933965Sjdpparse_mri_cons (exp, nbytes) 391033965Sjdp expressionS *exp; 391133965Sjdp unsigned int nbytes; 391233965Sjdp{ 391333965Sjdp if (*input_line_pointer != '\'' 391433965Sjdp && (input_line_pointer[1] != '\'' 391533965Sjdp || (*input_line_pointer != 'A' 391633965Sjdp && *input_line_pointer != 'E'))) 391733965Sjdp TC_PARSE_CONS_EXPRESSION (exp, nbytes); 391833965Sjdp else 391933965Sjdp { 392038889Sjdp unsigned int scan; 392133965Sjdp unsigned int result = 0; 392233965Sjdp 392333965Sjdp /* An MRI style string. Cut into as many bytes as will fit into 392433965Sjdp a nbyte chunk, left justify if necessary, and separate with 392533965Sjdp commas so we can try again later. */ 392633965Sjdp if (*input_line_pointer == 'A') 392733965Sjdp ++input_line_pointer; 392833965Sjdp else if (*input_line_pointer == 'E') 392933965Sjdp { 393060484Sobrien as_bad (_("EBCDIC constants are not supported")); 393133965Sjdp ++input_line_pointer; 393233965Sjdp } 393333965Sjdp 393433965Sjdp input_line_pointer++; 393533965Sjdp for (scan = 0; scan < nbytes; scan++) 393633965Sjdp { 393733965Sjdp if (*input_line_pointer == '\'') 393833965Sjdp { 393933965Sjdp if (input_line_pointer[1] == '\'') 394033965Sjdp { 394133965Sjdp input_line_pointer++; 394233965Sjdp } 394333965Sjdp else 394433965Sjdp break; 394533965Sjdp } 394633965Sjdp result = (result << 8) | (*input_line_pointer++); 394733965Sjdp } 394833965Sjdp 394977298Sobrien /* Left justify. */ 395033965Sjdp while (scan < nbytes) 395133965Sjdp { 395233965Sjdp result <<= 8; 395333965Sjdp scan++; 395433965Sjdp } 395577298Sobrien 395677298Sobrien /* Create correct expression. */ 395733965Sjdp exp->X_op = O_constant; 395833965Sjdp exp->X_add_number = result; 395977298Sobrien 396077298Sobrien /* Fake it so that we can read the next char too. */ 396133965Sjdp if (input_line_pointer[0] != '\'' || 396233965Sjdp (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\'')) 396333965Sjdp { 396433965Sjdp input_line_pointer -= 2; 396533965Sjdp input_line_pointer[0] = ','; 396633965Sjdp input_line_pointer[1] = '\''; 396733965Sjdp } 396833965Sjdp else 396933965Sjdp input_line_pointer++; 397033965Sjdp } 397133965Sjdp} 397260484Sobrien#endif /* TC_M68K */ 397333965Sjdp 397433965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 397533965Sjdp 397633965Sjdp/* Parse a repeat expression for cons. This is used by the MIPS 397733965Sjdp assembler. The format is NUMBER:COUNT; NUMBER appears in the 397833965Sjdp object file COUNT times. 397933965Sjdp 398033965Sjdp To use this for a target, define REPEAT_CONS_EXPRESSIONS. */ 398133965Sjdp 398233965Sjdpstatic void 398333965Sjdpparse_repeat_cons (exp, nbytes) 398433965Sjdp expressionS *exp; 398533965Sjdp unsigned int nbytes; 398633965Sjdp{ 398733965Sjdp expressionS count; 398833965Sjdp register int i; 398933965Sjdp 399033965Sjdp expression (exp); 399133965Sjdp 399233965Sjdp if (*input_line_pointer != ':') 399333965Sjdp { 399433965Sjdp /* No repeat count. */ 399533965Sjdp return; 399633965Sjdp } 399733965Sjdp 399833965Sjdp ++input_line_pointer; 399933965Sjdp expression (&count); 400033965Sjdp if (count.X_op != O_constant 400133965Sjdp || count.X_add_number <= 0) 400233965Sjdp { 400389857Sobrien as_warn (_("unresolvable or nonpositive repeat count; using 1")); 400433965Sjdp return; 400533965Sjdp } 400633965Sjdp 400733965Sjdp /* The cons function is going to output this expression once. So we 400833965Sjdp output it count - 1 times. */ 400933965Sjdp for (i = count.X_add_number - 1; i > 0; i--) 401033965Sjdp emit_expr (exp, nbytes); 401133965Sjdp} 401233965Sjdp 401333965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */ 401433965Sjdp 401533965Sjdp/* Parse a floating point number represented as a hex constant. This 401633965Sjdp permits users to specify the exact bits they want in the floating 401733965Sjdp point number. */ 401833965Sjdp 401933965Sjdpstatic int 402033965Sjdphex_float (float_type, bytes) 402133965Sjdp int float_type; 402233965Sjdp char *bytes; 402333965Sjdp{ 402433965Sjdp int length; 402533965Sjdp int i; 402633965Sjdp 402733965Sjdp switch (float_type) 402833965Sjdp { 402933965Sjdp case 'f': 403033965Sjdp case 'F': 403133965Sjdp case 's': 403233965Sjdp case 'S': 403333965Sjdp length = 4; 403433965Sjdp break; 403533965Sjdp 403633965Sjdp case 'd': 403733965Sjdp case 'D': 403833965Sjdp case 'r': 403933965Sjdp case 'R': 404033965Sjdp length = 8; 404133965Sjdp break; 404233965Sjdp 404333965Sjdp case 'x': 404433965Sjdp case 'X': 404533965Sjdp length = 12; 404633965Sjdp break; 404733965Sjdp 404833965Sjdp case 'p': 404933965Sjdp case 'P': 405033965Sjdp length = 12; 405133965Sjdp break; 405233965Sjdp 405333965Sjdp default: 405489857Sobrien as_bad (_("unknown floating type type '%c'"), float_type); 405533965Sjdp return -1; 405633965Sjdp } 405733965Sjdp 405833965Sjdp /* It would be nice if we could go through expression to parse the 405933965Sjdp hex constant, but if we get a bignum it's a pain to sort it into 406033965Sjdp the buffer correctly. */ 406133965Sjdp i = 0; 406233965Sjdp while (hex_p (*input_line_pointer) || *input_line_pointer == '_') 406333965Sjdp { 406433965Sjdp int d; 406533965Sjdp 406633965Sjdp /* The MRI assembler accepts arbitrary underscores strewn about 406777298Sobrien through the hex constant, so we ignore them as well. */ 406833965Sjdp if (*input_line_pointer == '_') 406933965Sjdp { 407033965Sjdp ++input_line_pointer; 407133965Sjdp continue; 407233965Sjdp } 407333965Sjdp 407433965Sjdp if (i >= length) 407533965Sjdp { 407689857Sobrien as_warn (_("floating point constant too large")); 407733965Sjdp return -1; 407833965Sjdp } 407933965Sjdp d = hex_value (*input_line_pointer) << 4; 408033965Sjdp ++input_line_pointer; 408133965Sjdp while (*input_line_pointer == '_') 408233965Sjdp ++input_line_pointer; 408333965Sjdp if (hex_p (*input_line_pointer)) 408433965Sjdp { 408533965Sjdp d += hex_value (*input_line_pointer); 408633965Sjdp ++input_line_pointer; 408733965Sjdp } 408833965Sjdp if (target_big_endian) 408933965Sjdp bytes[i] = d; 409033965Sjdp else 409133965Sjdp bytes[length - i - 1] = d; 409233965Sjdp ++i; 409333965Sjdp } 409433965Sjdp 409533965Sjdp if (i < length) 409633965Sjdp { 409733965Sjdp if (target_big_endian) 409833965Sjdp memset (bytes + i, 0, length - i); 409933965Sjdp else 410033965Sjdp memset (bytes, 0, length - i); 410133965Sjdp } 410233965Sjdp 410333965Sjdp return length; 410433965Sjdp} 410533965Sjdp 410677298Sobrien/* float_cons() 410733965Sjdp 410877298Sobrien CONStruct some more frag chars of .floats .ffloats etc. 410977298Sobrien Makes 0 or more new frags. 411077298Sobrien If need_pass_2 == 1, no frags are emitted. 411177298Sobrien This understands only floating literals, not expressions. Sorry. 411277298Sobrien 411377298Sobrien A floating constant is defined by atof_generic(), except it is preceded 411477298Sobrien by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its 411577298Sobrien reading, I decided to be incompatible. This always tries to give you 411677298Sobrien rounded bits to the precision of the pseudo-op. Former AS did premature 411777298Sobrien truncatation, restored noisy bits instead of trailing 0s AND gave you 411877298Sobrien a choice of 2 flavours of noise according to which of 2 floating-point 411977298Sobrien scanners you directed AS to use. 412077298Sobrien 412177298Sobrien In: input_line_pointer->whitespace before, or '0' of flonum. */ 412277298Sobrien 412333965Sjdpvoid 412433965Sjdpfloat_cons (float_type) 412577298Sobrien /* Clobbers input_line-pointer, checks end-of-line. */ 412677298Sobrien register int float_type; /* 'f':.ffloat ... 'F':.float ... */ 412733965Sjdp{ 412833965Sjdp register char *p; 412977298Sobrien int length; /* Number of chars in an object. */ 413077298Sobrien register char *err; /* Error from scanning floating literal. */ 413133965Sjdp char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 413233965Sjdp 413333965Sjdp if (is_it_end_of_statement ()) 413433965Sjdp { 413533965Sjdp demand_empty_rest_of_line (); 413633965Sjdp return; 413733965Sjdp } 413833965Sjdp 413933965Sjdp#ifdef md_flush_pending_output 414033965Sjdp md_flush_pending_output (); 414133965Sjdp#endif 414233965Sjdp 414333965Sjdp do 414433965Sjdp { 414577298Sobrien /* input_line_pointer->1st char of a flonum (we hope!). */ 414633965Sjdp SKIP_WHITESPACE (); 414733965Sjdp 414833965Sjdp /* Skip any 0{letter} that may be present. Don't even check if the 414977298Sobrien letter is legal. Someone may invent a "z" format and this routine 415077298Sobrien has no use for such information. Lusers beware: you get 415177298Sobrien diagnostics if your input is ill-conditioned. */ 415238889Sjdp if (input_line_pointer[0] == '0' 415389857Sobrien && ISALPHA (input_line_pointer[1])) 415433965Sjdp input_line_pointer += 2; 415533965Sjdp 415633965Sjdp /* Accept :xxxx, where the x's are hex digits, for a floating 415733965Sjdp point with the exact digits specified. */ 415833965Sjdp if (input_line_pointer[0] == ':') 415933965Sjdp { 416033965Sjdp ++input_line_pointer; 416133965Sjdp length = hex_float (float_type, temp); 416233965Sjdp if (length < 0) 416333965Sjdp { 416433965Sjdp ignore_rest_of_line (); 416533965Sjdp return; 416633965Sjdp } 416733965Sjdp } 416833965Sjdp else 416933965Sjdp { 417033965Sjdp err = md_atof (float_type, temp, &length); 417133965Sjdp know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 417233965Sjdp know (length > 0); 417333965Sjdp if (err) 417433965Sjdp { 417589857Sobrien as_bad (_("bad floating literal: %s"), err); 417633965Sjdp ignore_rest_of_line (); 417733965Sjdp return; 417833965Sjdp } 417933965Sjdp } 418033965Sjdp 418133965Sjdp if (!need_pass_2) 418233965Sjdp { 418333965Sjdp int count; 418433965Sjdp 418533965Sjdp count = 1; 418633965Sjdp 418733965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS 418833965Sjdp if (*input_line_pointer == ':') 418933965Sjdp { 419033965Sjdp expressionS count_exp; 419133965Sjdp 419233965Sjdp ++input_line_pointer; 419333965Sjdp expression (&count_exp); 419477298Sobrien 419533965Sjdp if (count_exp.X_op != O_constant 419633965Sjdp || count_exp.X_add_number <= 0) 419777298Sobrien as_warn (_("unresolvable or nonpositive repeat count; using 1")); 419833965Sjdp else 419933965Sjdp count = count_exp.X_add_number; 420033965Sjdp } 420133965Sjdp#endif 420233965Sjdp 420333965Sjdp while (--count >= 0) 420433965Sjdp { 420533965Sjdp p = frag_more (length); 420633965Sjdp memcpy (p, temp, (unsigned int) length); 420733965Sjdp } 420833965Sjdp } 420933965Sjdp SKIP_WHITESPACE (); 421033965Sjdp } 421133965Sjdp while (*input_line_pointer++ == ','); 421233965Sjdp 421377298Sobrien /* Put terminator back into stream. */ 421477298Sobrien --input_line_pointer; 421533965Sjdp demand_empty_rest_of_line (); 421677298Sobrien} 421733965Sjdp 421877298Sobrien/* Return the size of a LEB128 value. */ 421938889Sjdp 422038889Sjdpstatic inline int 422138889Sjdpsizeof_sleb128 (value) 422238889Sjdp offsetT value; 422338889Sjdp{ 422438889Sjdp register int size = 0; 422538889Sjdp register unsigned byte; 422638889Sjdp 422738889Sjdp do 422838889Sjdp { 422938889Sjdp byte = (value & 0x7f); 423038889Sjdp /* Sadly, we cannot rely on typical arithmetic right shift behaviour. 423138889Sjdp Fortunately, we can structure things so that the extra work reduces 423238889Sjdp to a noop on systems that do things "properly". */ 423338889Sjdp value = (value >> 7) | ~(-(offsetT)1 >> 7); 423438889Sjdp size += 1; 423538889Sjdp } 423638889Sjdp while (!(((value == 0) && ((byte & 0x40) == 0)) 423738889Sjdp || ((value == -1) && ((byte & 0x40) != 0)))); 423838889Sjdp 423938889Sjdp return size; 424038889Sjdp} 424138889Sjdp 424238889Sjdpstatic inline int 424338889Sjdpsizeof_uleb128 (value) 424438889Sjdp valueT value; 424538889Sjdp{ 424638889Sjdp register int size = 0; 424738889Sjdp register unsigned byte; 424838889Sjdp 424938889Sjdp do 425038889Sjdp { 425138889Sjdp byte = (value & 0x7f); 425238889Sjdp value >>= 7; 425338889Sjdp size += 1; 425438889Sjdp } 425538889Sjdp while (value != 0); 425638889Sjdp 425738889Sjdp return size; 425838889Sjdp} 425938889Sjdp 426060484Sobrienint 426138889Sjdpsizeof_leb128 (value, sign) 426238889Sjdp valueT value; 426338889Sjdp int sign; 426438889Sjdp{ 426538889Sjdp if (sign) 426638889Sjdp return sizeof_sleb128 ((offsetT) value); 426738889Sjdp else 426838889Sjdp return sizeof_uleb128 (value); 426938889Sjdp} 427038889Sjdp 427138889Sjdp/* Output a LEB128 value. */ 427238889Sjdp 427338889Sjdpstatic inline int 427438889Sjdpoutput_sleb128 (p, value) 427538889Sjdp char *p; 427638889Sjdp offsetT value; 427738889Sjdp{ 427838889Sjdp register char *orig = p; 427938889Sjdp register int more; 428038889Sjdp 428138889Sjdp do 428238889Sjdp { 428338889Sjdp unsigned byte = (value & 0x7f); 428438889Sjdp 428538889Sjdp /* Sadly, we cannot rely on typical arithmetic right shift behaviour. 428638889Sjdp Fortunately, we can structure things so that the extra work reduces 428738889Sjdp to a noop on systems that do things "properly". */ 428838889Sjdp value = (value >> 7) | ~(-(offsetT)1 >> 7); 428938889Sjdp 429038889Sjdp more = !((((value == 0) && ((byte & 0x40) == 0)) 429138889Sjdp || ((value == -1) && ((byte & 0x40) != 0)))); 429238889Sjdp if (more) 429338889Sjdp byte |= 0x80; 429438889Sjdp 429538889Sjdp *p++ = byte; 429638889Sjdp } 429738889Sjdp while (more); 429838889Sjdp 429938889Sjdp return p - orig; 430038889Sjdp} 430138889Sjdp 430238889Sjdpstatic inline int 430338889Sjdpoutput_uleb128 (p, value) 430438889Sjdp char *p; 430538889Sjdp valueT value; 430638889Sjdp{ 430738889Sjdp char *orig = p; 430838889Sjdp 430938889Sjdp do 431038889Sjdp { 431138889Sjdp unsigned byte = (value & 0x7f); 431238889Sjdp value >>= 7; 431338889Sjdp if (value != 0) 431438889Sjdp /* More bytes to follow. */ 431538889Sjdp byte |= 0x80; 431638889Sjdp 431738889Sjdp *p++ = byte; 431838889Sjdp } 431938889Sjdp while (value != 0); 432038889Sjdp 432138889Sjdp return p - orig; 432238889Sjdp} 432338889Sjdp 432460484Sobrienint 432538889Sjdpoutput_leb128 (p, value, sign) 432638889Sjdp char *p; 432738889Sjdp valueT value; 432838889Sjdp int sign; 432938889Sjdp{ 433038889Sjdp if (sign) 433138889Sjdp return output_sleb128 (p, (offsetT) value); 433238889Sjdp else 433338889Sjdp return output_uleb128 (p, value); 433438889Sjdp} 433538889Sjdp 433638889Sjdp/* Do the same for bignums. We combine sizeof with output here in that 433738889Sjdp we don't output for NULL values of P. It isn't really as critical as 433838889Sjdp for "normal" values that this be streamlined. */ 433938889Sjdp 434060484Sobrienstatic inline int 434138889Sjdpoutput_big_sleb128 (p, bignum, size) 434238889Sjdp char *p; 434338889Sjdp LITTLENUM_TYPE *bignum; 434438889Sjdp int size; 434538889Sjdp{ 434638889Sjdp char *orig = p; 434738889Sjdp valueT val = 0; 434838889Sjdp int loaded = 0; 434938889Sjdp unsigned byte; 435038889Sjdp 435138889Sjdp /* Strip leading sign extensions off the bignum. */ 435277298Sobrien while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1) 435338889Sjdp size--; 435438889Sjdp 435538889Sjdp do 435638889Sjdp { 435738889Sjdp if (loaded < 7 && size > 0) 435838889Sjdp { 435938889Sjdp val |= (*bignum << loaded); 436038889Sjdp loaded += 8 * CHARS_PER_LITTLENUM; 436138889Sjdp size--; 436238889Sjdp bignum++; 436338889Sjdp } 436438889Sjdp 436538889Sjdp byte = val & 0x7f; 436638889Sjdp loaded -= 7; 436738889Sjdp val >>= 7; 436838889Sjdp 436938889Sjdp if (size == 0) 437038889Sjdp { 437138889Sjdp if ((val == 0 && (byte & 0x40) == 0) 437277298Sobrien || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0 437338889Sjdp && (byte & 0x40) != 0)) 437438889Sjdp byte |= 0x80; 437538889Sjdp } 437638889Sjdp 437738889Sjdp if (orig) 437838889Sjdp *p = byte; 437938889Sjdp p++; 438038889Sjdp } 438138889Sjdp while (byte & 0x80); 438238889Sjdp 438338889Sjdp return p - orig; 438438889Sjdp} 438538889Sjdp 438660484Sobrienstatic inline int 438738889Sjdpoutput_big_uleb128 (p, bignum, size) 438838889Sjdp char *p; 438938889Sjdp LITTLENUM_TYPE *bignum; 439038889Sjdp int size; 439138889Sjdp{ 439238889Sjdp char *orig = p; 439338889Sjdp valueT val = 0; 439438889Sjdp int loaded = 0; 439538889Sjdp unsigned byte; 439638889Sjdp 439738889Sjdp /* Strip leading zeros off the bignum. */ 439838889Sjdp /* XXX: Is this needed? */ 439977298Sobrien while (size > 0 && bignum[size - 1] == 0) 440038889Sjdp size--; 440138889Sjdp 440238889Sjdp do 440338889Sjdp { 440438889Sjdp if (loaded < 7 && size > 0) 440538889Sjdp { 440638889Sjdp val |= (*bignum << loaded); 440738889Sjdp loaded += 8 * CHARS_PER_LITTLENUM; 440838889Sjdp size--; 440938889Sjdp bignum++; 441038889Sjdp } 441138889Sjdp 441238889Sjdp byte = val & 0x7f; 441338889Sjdp loaded -= 7; 441438889Sjdp val >>= 7; 441538889Sjdp 441638889Sjdp if (size > 0 || val) 441738889Sjdp byte |= 0x80; 441838889Sjdp 441938889Sjdp if (orig) 442038889Sjdp *p = byte; 442138889Sjdp p++; 442238889Sjdp } 442338889Sjdp while (byte & 0x80); 442438889Sjdp 442538889Sjdp return p - orig; 442638889Sjdp} 442738889Sjdp 442860484Sobrienstatic int 442938889Sjdpoutput_big_leb128 (p, bignum, size, sign) 443038889Sjdp char *p; 443138889Sjdp LITTLENUM_TYPE *bignum; 443238889Sjdp int size, sign; 443338889Sjdp{ 443438889Sjdp if (sign) 443538889Sjdp return output_big_sleb128 (p, bignum, size); 443638889Sjdp else 443738889Sjdp return output_big_uleb128 (p, bignum, size); 443838889Sjdp} 443938889Sjdp 444038889Sjdp/* Generate the appropriate fragments for a given expression to emit a 444138889Sjdp leb128 value. */ 444238889Sjdp 444338889Sjdpvoid 444477298Sobrienemit_leb128_expr (exp, sign) 444538889Sjdp expressionS *exp; 444638889Sjdp int sign; 444738889Sjdp{ 444838889Sjdp operatorT op = exp->X_op; 444978828Sobrien int nbytes; 445038889Sjdp 445138889Sjdp if (op == O_absent || op == O_illegal) 445238889Sjdp { 445360484Sobrien as_warn (_("zero assumed for missing expression")); 445438889Sjdp exp->X_add_number = 0; 445538889Sjdp op = O_constant; 445638889Sjdp } 445738889Sjdp else if (op == O_big && exp->X_add_number <= 0) 445838889Sjdp { 445989857Sobrien as_bad (_("floating point number invalid")); 446038889Sjdp exp->X_add_number = 0; 446138889Sjdp op = O_constant; 446238889Sjdp } 446338889Sjdp else if (op == O_register) 446438889Sjdp { 446560484Sobrien as_warn (_("register value used as expression")); 446638889Sjdp op = O_constant; 446738889Sjdp } 446838889Sjdp 446978828Sobrien /* Let check_eh_frame know that data is being emitted. nbytes == -1 is 447078828Sobrien a signal that this is leb128 data. It shouldn't optimize this away. */ 447178828Sobrien nbytes = -1; 447278828Sobrien if (check_eh_frame (exp, &nbytes)) 447378828Sobrien abort (); 447478828Sobrien 447578828Sobrien /* Let the backend know that subsequent data may be byte aligned. */ 447678828Sobrien#ifdef md_cons_align 447778828Sobrien md_cons_align (1); 447878828Sobrien#endif 447978828Sobrien 448038889Sjdp if (op == O_constant) 448138889Sjdp { 448238889Sjdp /* If we've got a constant, emit the thing directly right now. */ 448338889Sjdp 448438889Sjdp valueT value = exp->X_add_number; 448538889Sjdp int size; 448638889Sjdp char *p; 448738889Sjdp 448838889Sjdp size = sizeof_leb128 (value, sign); 448938889Sjdp p = frag_more (size); 449038889Sjdp output_leb128 (p, value, sign); 449138889Sjdp } 449238889Sjdp else if (op == O_big) 449338889Sjdp { 449438889Sjdp /* O_big is a different sort of constant. */ 449538889Sjdp 449638889Sjdp int size; 449738889Sjdp char *p; 449838889Sjdp 449938889Sjdp size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign); 450038889Sjdp p = frag_more (size); 450138889Sjdp output_big_leb128 (p, generic_bignum, exp->X_add_number, sign); 450238889Sjdp } 450338889Sjdp else 450438889Sjdp { 450577298Sobrien /* Otherwise, we have to create a variable sized fragment and 450638889Sjdp resolve things later. */ 450738889Sjdp 450877298Sobrien frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign, 450938889Sjdp make_expr_symbol (exp), 0, (char *) NULL); 451038889Sjdp } 451138889Sjdp} 451238889Sjdp 451338889Sjdp/* Parse the .sleb128 and .uleb128 pseudos. */ 451438889Sjdp 451538889Sjdpvoid 451638889Sjdps_leb128 (sign) 451738889Sjdp int sign; 451838889Sjdp{ 451938889Sjdp expressionS exp; 452038889Sjdp 452177298Sobrien do 452277298Sobrien { 452377298Sobrien expression (&exp); 452477298Sobrien emit_leb128_expr (&exp, sign); 452577298Sobrien } 452677298Sobrien while (*input_line_pointer++ == ','); 452738889Sjdp 452838889Sjdp input_line_pointer--; 452938889Sjdp demand_empty_rest_of_line (); 453038889Sjdp} 453138889Sjdp 453277298Sobrien/* We read 0 or more ',' separated, double-quoted strings. 453377298Sobrien Caller should have checked need_pass_2 is FALSE because we don't 453477298Sobrien check it. */ 453533965Sjdp 453677298Sobrienvoid 453777298Sobrienstringer (append_zero) /* Worker to do .ascii etc statements. */ 453877298Sobrien /* Checks end-of-line. */ 453977298Sobrien register int append_zero; /* 0: don't append '\0', else 1. */ 454033965Sjdp{ 454133965Sjdp register unsigned int c; 454238889Sjdp char *start; 454333965Sjdp 454433965Sjdp#ifdef md_flush_pending_output 454533965Sjdp md_flush_pending_output (); 454633965Sjdp#endif 454733965Sjdp 454877298Sobrien /* The following awkward logic is to parse ZERO or more strings, 454977298Sobrien comma separated. Recall a string expression includes spaces 455077298Sobrien before the opening '\"' and spaces after the closing '\"'. 455177298Sobrien We fake a leading ',' if there is (supposed to be) 455277298Sobrien a 1st, expression. We keep demanding expressions for each ','. */ 455333965Sjdp if (is_it_end_of_statement ()) 455433965Sjdp { 455577298Sobrien c = 0; /* Skip loop. */ 455677298Sobrien ++input_line_pointer; /* Compensate for end of loop. */ 455733965Sjdp } 455833965Sjdp else 455933965Sjdp { 456077298Sobrien c = ','; /* Do loop. */ 456133965Sjdp } 456233965Sjdp while (c == ',' || c == '<' || c == '"') 456333965Sjdp { 456433965Sjdp SKIP_WHITESPACE (); 456533965Sjdp switch (*input_line_pointer) 456633965Sjdp { 456733965Sjdp case '\"': 456877298Sobrien ++input_line_pointer; /*->1st char of string. */ 456938889Sjdp start = input_line_pointer; 457033965Sjdp while (is_a_char (c = next_char_of_string ())) 457133965Sjdp { 457233965Sjdp FRAG_APPEND_1_CHAR (c); 457333965Sjdp } 457433965Sjdp if (append_zero) 457533965Sjdp { 457633965Sjdp FRAG_APPEND_1_CHAR (0); 457733965Sjdp } 457833965Sjdp know (input_line_pointer[-1] == '\"'); 457938889Sjdp 458038889Sjdp#ifndef NO_LISTING 458138889Sjdp#ifdef OBJ_ELF 458238889Sjdp /* In ELF, when gcc is emitting DWARF 1 debugging output, it 458338889Sjdp will emit .string with a filename in the .debug section 458438889Sjdp after a sequence of constants. See the comment in 458538889Sjdp emit_expr for the sequence. emit_expr will set 458638889Sjdp dwarf_file_string to non-zero if this string might be a 458738889Sjdp source file name. */ 458838889Sjdp if (strcmp (segment_name (now_seg), ".debug") != 0) 458938889Sjdp dwarf_file_string = 0; 459038889Sjdp else if (dwarf_file_string) 459138889Sjdp { 459238889Sjdp c = input_line_pointer[-1]; 459338889Sjdp input_line_pointer[-1] = '\0'; 459438889Sjdp listing_source_file (start); 459538889Sjdp input_line_pointer[-1] = c; 459638889Sjdp } 459738889Sjdp#endif 459838889Sjdp#endif 459938889Sjdp 460033965Sjdp break; 460133965Sjdp case '<': 460233965Sjdp input_line_pointer++; 460333965Sjdp c = get_single_number (); 460433965Sjdp FRAG_APPEND_1_CHAR (c); 460533965Sjdp if (*input_line_pointer != '>') 460633965Sjdp { 460789857Sobrien as_bad (_("expected <nn>")); 460833965Sjdp } 460933965Sjdp input_line_pointer++; 461033965Sjdp break; 461133965Sjdp case ',': 461233965Sjdp input_line_pointer++; 461333965Sjdp break; 461433965Sjdp } 461533965Sjdp SKIP_WHITESPACE (); 461633965Sjdp c = *input_line_pointer; 461733965Sjdp } 461833965Sjdp 461933965Sjdp demand_empty_rest_of_line (); 462033965Sjdp} /* stringer() */ 462133965Sjdp 462233965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the 462333965Sjdp high bits set. We'll probably also have trouble with 462433965Sjdp multibyte chars, wide chars, etc. Also be careful about 462577298Sobrien returning values bigger than 1 byte. xoxorich. */ 462633965Sjdp 462777298Sobrienunsigned int 462833965Sjdpnext_char_of_string () 462933965Sjdp{ 463033965Sjdp register unsigned int c; 463133965Sjdp 463233965Sjdp c = *input_line_pointer++ & CHAR_MASK; 463333965Sjdp switch (c) 463433965Sjdp { 463533965Sjdp case '\"': 463633965Sjdp c = NOT_A_CHAR; 463733965Sjdp break; 463833965Sjdp 463933965Sjdp case '\n': 464089857Sobrien as_warn (_("unterminated string; newline inserted")); 464133965Sjdp bump_line_counters (); 464233965Sjdp break; 464333965Sjdp 464433965Sjdp#ifndef NO_STRING_ESCAPES 464533965Sjdp case '\\': 464633965Sjdp switch (c = *input_line_pointer++) 464733965Sjdp { 464833965Sjdp case 'b': 464933965Sjdp c = '\b'; 465033965Sjdp break; 465133965Sjdp 465233965Sjdp case 'f': 465333965Sjdp c = '\f'; 465433965Sjdp break; 465533965Sjdp 465633965Sjdp case 'n': 465733965Sjdp c = '\n'; 465833965Sjdp break; 465933965Sjdp 466033965Sjdp case 'r': 466133965Sjdp c = '\r'; 466233965Sjdp break; 466333965Sjdp 466433965Sjdp case 't': 466533965Sjdp c = '\t'; 466633965Sjdp break; 466733965Sjdp 466833965Sjdp case 'v': 466933965Sjdp c = '\013'; 467033965Sjdp break; 467133965Sjdp 467233965Sjdp case '\\': 467333965Sjdp case '"': 467477298Sobrien break; /* As itself. */ 467533965Sjdp 467633965Sjdp case '0': 467733965Sjdp case '1': 467833965Sjdp case '2': 467933965Sjdp case '3': 468033965Sjdp case '4': 468133965Sjdp case '5': 468233965Sjdp case '6': 468333965Sjdp case '7': 468433965Sjdp case '8': 468533965Sjdp case '9': 468633965Sjdp { 468733965Sjdp long number; 468833965Sjdp int i; 468933965Sjdp 469077298Sobrien for (i = 0, number = 0; 469189857Sobrien ISDIGIT (c) && i < 3; 469277298Sobrien c = *input_line_pointer++, i++) 469333965Sjdp { 469433965Sjdp number = number * 8 + c - '0'; 469533965Sjdp } 469677298Sobrien 469733965Sjdp c = number & 0xff; 469833965Sjdp } 469933965Sjdp --input_line_pointer; 470033965Sjdp break; 470133965Sjdp 470233965Sjdp case 'x': 470333965Sjdp case 'X': 470433965Sjdp { 470533965Sjdp long number; 470633965Sjdp 470733965Sjdp number = 0; 470833965Sjdp c = *input_line_pointer++; 470989857Sobrien while (ISXDIGIT (c)) 471033965Sjdp { 471189857Sobrien if (ISDIGIT (c)) 471233965Sjdp number = number * 16 + c - '0'; 471389857Sobrien else if (ISUPPER (c)) 471433965Sjdp number = number * 16 + c - 'A' + 10; 471533965Sjdp else 471633965Sjdp number = number * 16 + c - 'a' + 10; 471733965Sjdp c = *input_line_pointer++; 471833965Sjdp } 471933965Sjdp c = number & 0xff; 472033965Sjdp --input_line_pointer; 472133965Sjdp } 472233965Sjdp break; 472333965Sjdp 472433965Sjdp case '\n': 472577298Sobrien /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ 472689857Sobrien as_warn (_("unterminated string; newline inserted")); 472733965Sjdp c = '\n'; 472833965Sjdp bump_line_counters (); 472933965Sjdp break; 473033965Sjdp 473133965Sjdp default: 473233965Sjdp 473333965Sjdp#ifdef ONLY_STANDARD_ESCAPES 473489857Sobrien as_bad (_("bad escaped character in string")); 473533965Sjdp c = '?'; 473633965Sjdp#endif /* ONLY_STANDARD_ESCAPES */ 473733965Sjdp 473833965Sjdp break; 473977298Sobrien } 474033965Sjdp break; 474133965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */ 474233965Sjdp 474333965Sjdp default: 474433965Sjdp break; 474577298Sobrien } 474633965Sjdp return (c); 474777298Sobrien} 474833965Sjdp 474933965Sjdpstatic segT 475033965Sjdpget_segmented_expression (expP) 475133965Sjdp register expressionS *expP; 475233965Sjdp{ 475333965Sjdp register segT retval; 475433965Sjdp 475533965Sjdp retval = expression (expP); 475633965Sjdp if (expP->X_op == O_illegal 475733965Sjdp || expP->X_op == O_absent 475833965Sjdp || expP->X_op == O_big) 475933965Sjdp { 476089857Sobrien as_bad (_("expected address expression")); 476133965Sjdp expP->X_op = O_constant; 476233965Sjdp expP->X_add_number = 0; 476333965Sjdp retval = absolute_section; 476433965Sjdp } 476533965Sjdp return retval; 476633965Sjdp} 476733965Sjdp 476877298Sobrienstatic segT 476933965Sjdpget_known_segmented_expression (expP) 477033965Sjdp register expressionS *expP; 477133965Sjdp{ 477233965Sjdp register segT retval; 477333965Sjdp 477433965Sjdp if ((retval = get_segmented_expression (expP)) == undefined_section) 477533965Sjdp { 477633965Sjdp /* There is no easy way to extract the undefined symbol from the 477733965Sjdp expression. */ 477833965Sjdp if (expP->X_add_symbol != NULL 477933965Sjdp && S_GET_SEGMENT (expP->X_add_symbol) != expr_section) 478060484Sobrien as_warn (_("symbol \"%s\" undefined; zero assumed"), 478133965Sjdp S_GET_NAME (expP->X_add_symbol)); 478233965Sjdp else 478360484Sobrien as_warn (_("some symbol undefined; zero assumed")); 478433965Sjdp retval = absolute_section; 478533965Sjdp expP->X_op = O_constant; 478633965Sjdp expP->X_add_number = 0; 478733965Sjdp } 478833965Sjdp know (retval == absolute_section || SEG_NORMAL (retval)); 478933965Sjdp return (retval); 479077298Sobrien} 479133965Sjdp 479233965SjdpoffsetT 479333965Sjdpget_absolute_expression () 479433965Sjdp{ 479533965Sjdp expressionS exp; 479633965Sjdp 479733965Sjdp expression (&exp); 479833965Sjdp if (exp.X_op != O_constant) 479933965Sjdp { 480033965Sjdp if (exp.X_op != O_absent) 480189857Sobrien as_bad (_("bad or irreducible absolute expression")); 480233965Sjdp exp.X_add_number = 0; 480333965Sjdp } 480433965Sjdp return exp.X_add_number; 480533965Sjdp} 480633965Sjdp 480777298Sobrienchar /* Return terminator. */ 480833965Sjdpget_absolute_expression_and_terminator (val_pointer) 480977298Sobrien long *val_pointer; /* Return value of expression. */ 481033965Sjdp{ 481133965Sjdp /* FIXME: val_pointer should probably be offsetT *. */ 481233965Sjdp *val_pointer = (long) get_absolute_expression (); 481333965Sjdp return (*input_line_pointer++); 481433965Sjdp} 481533965Sjdp 481677298Sobrien/* Like demand_copy_string, but return NULL if the string contains any '\0's. 481777298Sobrien Give a warning if that happens. */ 481877298Sobrien 481933965Sjdpchar * 482033965Sjdpdemand_copy_C_string (len_pointer) 482133965Sjdp int *len_pointer; 482233965Sjdp{ 482333965Sjdp register char *s; 482433965Sjdp 482533965Sjdp if ((s = demand_copy_string (len_pointer)) != 0) 482633965Sjdp { 482733965Sjdp register int len; 482833965Sjdp 482933965Sjdp for (len = *len_pointer; len > 0; len--) 483033965Sjdp { 483133965Sjdp if (*s == 0) 483233965Sjdp { 483333965Sjdp s = 0; 483433965Sjdp len = 1; 483533965Sjdp *len_pointer = 0; 483689857Sobrien as_bad (_("this string may not contain \'\\0\'")); 483733965Sjdp } 483833965Sjdp } 483933965Sjdp } 484077298Sobrien 484133965Sjdp return s; 484233965Sjdp} 484333965Sjdp 484477298Sobrien/* Demand string, but return a safe (=private) copy of the string. 484577298Sobrien Return NULL if we can't read a string here. */ 484677298Sobrien 484733965Sjdpchar * 484833965Sjdpdemand_copy_string (lenP) 484933965Sjdp int *lenP; 485033965Sjdp{ 485133965Sjdp register unsigned int c; 485233965Sjdp register int len; 485333965Sjdp char *retval; 485433965Sjdp 485533965Sjdp len = 0; 485633965Sjdp SKIP_WHITESPACE (); 485733965Sjdp if (*input_line_pointer == '\"') 485833965Sjdp { 485977298Sobrien input_line_pointer++; /* Skip opening quote. */ 486033965Sjdp 486133965Sjdp while (is_a_char (c = next_char_of_string ())) 486233965Sjdp { 486333965Sjdp obstack_1grow (¬es, c); 486433965Sjdp len++; 486533965Sjdp } 486633965Sjdp /* JF this next line is so demand_copy_C_string will return a 486777298Sobrien null terminated string. */ 486833965Sjdp obstack_1grow (¬es, '\0'); 486933965Sjdp retval = obstack_finish (¬es); 487033965Sjdp } 487133965Sjdp else 487233965Sjdp { 487389857Sobrien as_warn (_("missing string")); 487433965Sjdp retval = NULL; 487533965Sjdp ignore_rest_of_line (); 487633965Sjdp } 487733965Sjdp *lenP = len; 487833965Sjdp return (retval); 487977298Sobrien} 488033965Sjdp 488177298Sobrien/* In: Input_line_pointer->next character. 488277298Sobrien 488377298Sobrien Do: Skip input_line_pointer over all whitespace. 488477298Sobrien 488577298Sobrien Out: 1 if input_line_pointer->end-of-line. */ 488677298Sobrien 488777298Sobrienint 488833965Sjdpis_it_end_of_statement () 488933965Sjdp{ 489033965Sjdp SKIP_WHITESPACE (); 489133965Sjdp return (is_end_of_line[(unsigned char) *input_line_pointer]); 489277298Sobrien} 489333965Sjdp 489477298Sobrienvoid 489533965Sjdpequals (sym_name, reassign) 489633965Sjdp char *sym_name; 489733965Sjdp int reassign; 489833965Sjdp{ 489977298Sobrien register symbolS *symbolP; /* Symbol we are working with. */ 490038889Sjdp char *stop = NULL; 490133965Sjdp char stopc; 490233965Sjdp 490333965Sjdp input_line_pointer++; 490433965Sjdp if (*input_line_pointer == '=') 490533965Sjdp input_line_pointer++; 490633965Sjdp 490733965Sjdp while (*input_line_pointer == ' ' || *input_line_pointer == '\t') 490833965Sjdp input_line_pointer++; 490933965Sjdp 491033965Sjdp if (flag_mri) 491133965Sjdp stop = mri_comment_field (&stopc); 491233965Sjdp 491333965Sjdp if (sym_name[0] == '.' && sym_name[1] == '\0') 491433965Sjdp { 491577298Sobrien /* Turn '. = mumble' into a .org mumble. */ 491633965Sjdp register segT segment; 491733965Sjdp expressionS exp; 491833965Sjdp 491933965Sjdp segment = get_known_segmented_expression (&exp); 492033965Sjdp if (!need_pass_2) 492133965Sjdp do_org (segment, &exp, 0); 492233965Sjdp } 492333965Sjdp else 492433965Sjdp { 492578828Sobrien#ifdef OBJ_COFF 492678828Sobrien int local; 492778828Sobrien 492878828Sobrien symbolP = symbol_find (sym_name); 492978828Sobrien local = symbolP == NULL; 493078828Sobrien if (local) 493178828Sobrien#endif /* OBJ_COFF */ 493233965Sjdp symbolP = symbol_find_or_make (sym_name); 493333965Sjdp /* Permit register names to be redefined. */ 493477298Sobrien if (!reassign 493533965Sjdp && S_IS_DEFINED (symbolP) 493633965Sjdp && S_GET_SEGMENT (symbolP) != reg_section) 493789857Sobrien as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 493878828Sobrien 493978828Sobrien#ifdef OBJ_COFF 494078828Sobrien /* "set" symbols are local unless otherwise specified. */ 494178828Sobrien if (local) 494278828Sobrien SF_SET_LOCAL (symbolP); 494378828Sobrien#endif /* OBJ_COFF */ 494478828Sobrien 494533965Sjdp pseudo_set (symbolP); 494633965Sjdp } 494733965Sjdp 494833965Sjdp if (flag_mri) 494977298Sobrien { 495077298Sobrien /* Check garbage after the expression. */ 495177298Sobrien ignore_rest_of_line (); 495277298Sobrien mri_comment_end (stop, stopc); 495377298Sobrien } 495477298Sobrien} 495533965Sjdp 495689857Sobrien/* .incbin -- include a file verbatim at the current location. */ 495789857Sobrien 495889857Sobrienvoid 495989857Sobriens_incbin (x) 496089857Sobrien int x ATTRIBUTE_UNUSED; 496189857Sobrien{ 496289857Sobrien FILE * binfile; 496389857Sobrien char * path; 496489857Sobrien char * filename; 496589857Sobrien char * binfrag; 496689857Sobrien long skip = 0; 496789857Sobrien long count = 0; 496889857Sobrien long bytes; 496989857Sobrien int len; 497089857Sobrien 497189857Sobrien#ifdef md_flush_pending_output 497289857Sobrien md_flush_pending_output (); 497389857Sobrien#endif 497489857Sobrien 497589857Sobrien SKIP_WHITESPACE (); 497689857Sobrien filename = demand_copy_string (& len); 497789857Sobrien if (filename == NULL) 497889857Sobrien return; 497989857Sobrien 498089857Sobrien SKIP_WHITESPACE (); 498189857Sobrien 498289857Sobrien /* Look for optional skip and count. */ 498389857Sobrien if (* input_line_pointer == ',') 498489857Sobrien { 498589857Sobrien ++ input_line_pointer; 498689857Sobrien skip = get_absolute_expression (); 498789857Sobrien 498889857Sobrien SKIP_WHITESPACE (); 498989857Sobrien 499089857Sobrien if (* input_line_pointer == ',') 499189857Sobrien { 499289857Sobrien ++ input_line_pointer; 499389857Sobrien 499489857Sobrien count = get_absolute_expression (); 499589857Sobrien if (count == 0) 499689857Sobrien as_warn (_(".incbin count zero, ignoring `%s'"), filename); 499789857Sobrien 499889857Sobrien SKIP_WHITESPACE (); 499989857Sobrien } 500089857Sobrien } 500189857Sobrien 500289857Sobrien demand_empty_rest_of_line (); 500389857Sobrien 500489857Sobrien /* Try opening absolute path first, then try include dirs. */ 500589857Sobrien binfile = fopen (filename, FOPEN_RB); 500689857Sobrien if (binfile == NULL) 500789857Sobrien { 500889857Sobrien int i; 500989857Sobrien 501089857Sobrien path = xmalloc ((unsigned long) len + include_dir_maxlen + 5); 501189857Sobrien 501289857Sobrien for (i = 0; i < include_dir_count; i++) 501389857Sobrien { 501489857Sobrien sprintf (path, "%s/%s", include_dirs[i], filename); 501589857Sobrien 501689857Sobrien binfile = fopen (path, FOPEN_RB); 501789857Sobrien if (binfile != NULL) 501889857Sobrien break; 501989857Sobrien } 502089857Sobrien 502189857Sobrien if (binfile == NULL) 502289857Sobrien as_bad (_("file not found: %s"), filename); 502389857Sobrien } 502489857Sobrien else 502589857Sobrien path = xstrdup (filename); 502689857Sobrien 502789857Sobrien if (binfile) 502889857Sobrien { 502989857Sobrien long file_len; 503089857Sobrien 503189857Sobrien register_dependency (path); 503289857Sobrien 503389857Sobrien /* Compute the length of the file. */ 503489857Sobrien if (fseek (binfile, 0, SEEK_END) != 0) 503589857Sobrien { 503689857Sobrien as_bad (_("seek to end of .incbin file failed `%s'"), path); 503789857Sobrien goto done; 503889857Sobrien } 503989857Sobrien file_len = ftell (binfile); 504089857Sobrien 504189857Sobrien /* If a count was not specified use the size of the file. */ 504289857Sobrien if (count == 0) 504389857Sobrien count = file_len; 504489857Sobrien 504589857Sobrien if (skip + count > file_len) 504689857Sobrien { 504789857Sobrien as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"), 504889857Sobrien skip, count, file_len); 504989857Sobrien goto done; 505089857Sobrien } 505189857Sobrien 505289857Sobrien if (fseek (binfile, skip, SEEK_SET) != 0) 505389857Sobrien { 505489857Sobrien as_bad (_("could not skip to %ld in file `%s'"), skip, path); 505589857Sobrien goto done; 505689857Sobrien } 505789857Sobrien 505889857Sobrien /* Allocate frag space and store file contents in it. */ 505989857Sobrien binfrag = frag_more (count); 506089857Sobrien 506189857Sobrien bytes = fread (binfrag, 1, count, binfile); 506289857Sobrien if (bytes < count) 506389857Sobrien as_warn (_("truncated file `%s', %ld of %ld bytes read"), 506489857Sobrien path, bytes, count); 506589857Sobrien } 506689857Sobriendone: 506789857Sobrien if (binfile != NULL) 506889857Sobrien fclose (binfile); 506989857Sobrien if (path) 507089857Sobrien free (path); 507189857Sobrien} 507289857Sobrien 507377298Sobrien/* .include -- include a file at this point. */ 507433965Sjdp 507577298Sobrienvoid 507633965Sjdps_include (arg) 507760484Sobrien int arg ATTRIBUTE_UNUSED; 507833965Sjdp{ 507933965Sjdp char *filename; 508033965Sjdp int i; 508133965Sjdp FILE *try; 508233965Sjdp char *path; 508333965Sjdp 508477298Sobrien if (!flag_m68k_mri) 508538889Sjdp { 508638889Sjdp filename = demand_copy_string (&i); 508738889Sjdp if (filename == NULL) 508838889Sjdp { 508938889Sjdp /* demand_copy_string has already printed an error and 509038889Sjdp called ignore_rest_of_line. */ 509138889Sjdp return; 509238889Sjdp } 509338889Sjdp } 509433965Sjdp else 509533965Sjdp { 509633965Sjdp SKIP_WHITESPACE (); 509733965Sjdp i = 0; 509877298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer] 509933965Sjdp && *input_line_pointer != ' ' 510033965Sjdp && *input_line_pointer != '\t') 510133965Sjdp { 510233965Sjdp obstack_1grow (¬es, *input_line_pointer); 510333965Sjdp ++input_line_pointer; 510433965Sjdp ++i; 510533965Sjdp } 510677298Sobrien 510733965Sjdp obstack_1grow (¬es, '\0'); 510833965Sjdp filename = obstack_finish (¬es); 510977298Sobrien while (!is_end_of_line[(unsigned char) *input_line_pointer]) 511033965Sjdp ++input_line_pointer; 511133965Sjdp } 511277298Sobrien 511333965Sjdp demand_empty_rest_of_line (); 511433965Sjdp path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ ); 511577298Sobrien 511633965Sjdp for (i = 0; i < include_dir_count; i++) 511733965Sjdp { 511833965Sjdp strcpy (path, include_dirs[i]); 511933965Sjdp strcat (path, "/"); 512033965Sjdp strcat (path, filename); 512189857Sobrien if (0 != (try = fopen (path, FOPEN_RT))) 512233965Sjdp { 512333965Sjdp fclose (try); 512433965Sjdp goto gotit; 512533965Sjdp } 512633965Sjdp } 512777298Sobrien 512833965Sjdp free (path); 512933965Sjdp path = filename; 513033965Sjdpgotit: 513177298Sobrien /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ 513238889Sjdp register_dependency (path); 513360484Sobrien input_scrub_insert_file (path); 513477298Sobrien} 513533965Sjdp 513677298Sobrienvoid 513733965Sjdpadd_include_dir (path) 513833965Sjdp char *path; 513933965Sjdp{ 514033965Sjdp int i; 514133965Sjdp 514233965Sjdp if (include_dir_count == 0) 514333965Sjdp { 514433965Sjdp include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs)); 514577298Sobrien include_dirs[0] = "."; /* Current dir. */ 514633965Sjdp include_dir_count = 2; 514733965Sjdp } 514833965Sjdp else 514933965Sjdp { 515033965Sjdp include_dir_count++; 515177298Sobrien include_dirs = 515277298Sobrien (char **) realloc (include_dirs, 515377298Sobrien include_dir_count * sizeof (*include_dirs)); 515433965Sjdp } 515533965Sjdp 515677298Sobrien include_dirs[include_dir_count - 1] = path; /* New one. */ 515733965Sjdp 515833965Sjdp i = strlen (path); 515933965Sjdp if (i > include_dir_maxlen) 516033965Sjdp include_dir_maxlen = i; 516177298Sobrien} 516260484Sobrien 516360484Sobrien/* Output debugging information to denote the source file. */ 516433965Sjdp 516560484Sobrienstatic void 516660484Sobriengenerate_file_debug () 516760484Sobrien{ 516860484Sobrien if (debug_type == DEBUG_STABS) 516960484Sobrien stabs_generate_asm_file (); 517060484Sobrien} 517160484Sobrien 517260484Sobrien/* Output line number debugging information for the current source line. */ 517360484Sobrien 517460484Sobrienvoid 517560484Sobriengenerate_lineno_debug () 517660484Sobrien{ 517760484Sobrien switch (debug_type) 517860484Sobrien { 517960484Sobrien case DEBUG_UNSPECIFIED: 518060484Sobrien case DEBUG_NONE: 518177298Sobrien case DEBUG_DWARF: 518260484Sobrien break; 518360484Sobrien case DEBUG_STABS: 518460484Sobrien stabs_generate_asm_lineno (); 518560484Sobrien break; 518660484Sobrien case DEBUG_ECOFF: 518760484Sobrien ecoff_generate_asm_lineno (); 518860484Sobrien break; 518960484Sobrien case DEBUG_DWARF2: 519077298Sobrien /* ??? We could here indicate to dwarf2dbg.c that something 519177298Sobrien has changed. However, since there is additional backend 519277298Sobrien support that is required (calling dwarf2_emit_insn), we 519377298Sobrien let dwarf2dbg.c call as_where on its own. */ 519460484Sobrien break; 519560484Sobrien } 519660484Sobrien} 519760484Sobrien 519860484Sobrien/* Output debugging information to mark a function entry point or end point. 519960484Sobrien END_P is zero for .func, and non-zero for .endfunc. */ 520060484Sobrien 520160484Sobrienvoid 520260484Sobriens_func (end_p) 520360484Sobrien int end_p; 520460484Sobrien{ 520560484Sobrien do_s_func (end_p, NULL); 520660484Sobrien} 520760484Sobrien 520860484Sobrien/* Subroutine of s_func so targets can choose a different default prefix. 520960484Sobrien If DEFAULT_PREFIX is NULL, use the target's "leading char". */ 521060484Sobrien 521160484Sobrienvoid 521260484Sobriendo_s_func (end_p, default_prefix) 521360484Sobrien int end_p; 521460484Sobrien const char *default_prefix; 521560484Sobrien{ 521660484Sobrien /* Record the current function so that we can issue an error message for 521760484Sobrien misplaced .func,.endfunc, and also so that .endfunc needs no 521860484Sobrien arguments. */ 521960484Sobrien static char *current_name; 522060484Sobrien static char *current_label; 522160484Sobrien 522260484Sobrien if (end_p) 522360484Sobrien { 522460484Sobrien if (current_name == NULL) 522560484Sobrien { 522660484Sobrien as_bad (_("missing .func")); 522760484Sobrien ignore_rest_of_line (); 522860484Sobrien return; 522960484Sobrien } 523060484Sobrien 523160484Sobrien if (debug_type == DEBUG_STABS) 523260484Sobrien stabs_generate_asm_endfunc (current_name, current_label); 523360484Sobrien 523460484Sobrien current_name = current_label = NULL; 523560484Sobrien } 523660484Sobrien else /* ! end_p */ 523760484Sobrien { 523877298Sobrien char *name, *label; 523977298Sobrien char delim1, delim2; 524060484Sobrien 524160484Sobrien if (current_name != NULL) 524260484Sobrien { 524360484Sobrien as_bad (_(".endfunc missing for previous .func")); 524460484Sobrien ignore_rest_of_line (); 524560484Sobrien return; 524660484Sobrien } 524760484Sobrien 524860484Sobrien name = input_line_pointer; 524960484Sobrien delim1 = get_symbol_end (); 525060484Sobrien name = xstrdup (name); 525160484Sobrien *input_line_pointer = delim1; 525260484Sobrien SKIP_WHITESPACE (); 525360484Sobrien if (*input_line_pointer != ',') 525460484Sobrien { 525560484Sobrien if (default_prefix) 525660484Sobrien asprintf (&label, "%s%s", default_prefix, name); 525760484Sobrien else 525860484Sobrien { 525960484Sobrien char leading_char = 0; 526060484Sobrien#ifdef BFD_ASSEMBLER 526160484Sobrien leading_char = bfd_get_symbol_leading_char (stdoutput); 526260484Sobrien#endif 526360484Sobrien /* Missing entry point, use function's name with the leading 526460484Sobrien char prepended. */ 526560484Sobrien if (leading_char) 526660484Sobrien asprintf (&label, "%c%s", leading_char, name); 526760484Sobrien else 526860484Sobrien label = name; 526960484Sobrien } 527060484Sobrien } 527160484Sobrien else 527260484Sobrien { 527360484Sobrien ++input_line_pointer; 527460484Sobrien SKIP_WHITESPACE (); 527560484Sobrien label = input_line_pointer; 527660484Sobrien delim2 = get_symbol_end (); 527760484Sobrien label = xstrdup (label); 527860484Sobrien *input_line_pointer = delim2; 527960484Sobrien } 528060484Sobrien 528160484Sobrien if (debug_type == DEBUG_STABS) 528260484Sobrien stabs_generate_asm_func (name, label); 528360484Sobrien 528460484Sobrien current_name = name; 528560484Sobrien current_label = label; 528660484Sobrien } 528760484Sobrien 528860484Sobrien demand_empty_rest_of_line (); 528960484Sobrien} 529060484Sobrien 529177298Sobrienvoid 529233965Sjdps_ignore (arg) 529360484Sobrien int arg ATTRIBUTE_UNUSED; 529433965Sjdp{ 529533965Sjdp while (!is_end_of_line[(unsigned char) *input_line_pointer]) 529633965Sjdp { 529733965Sjdp ++input_line_pointer; 529833965Sjdp } 529933965Sjdp ++input_line_pointer; 530033965Sjdp} 530133965Sjdp 530233965Sjdpvoid 530333965Sjdpread_print_statistics (file) 530433965Sjdp FILE *file; 530533965Sjdp{ 530633965Sjdp hash_print_statistics (file, "pseudo-op table", po_hash); 530733965Sjdp} 530833965Sjdp 530977298Sobrien/* Inserts the given line into the input stream. 531077298Sobrien 531160484Sobrien This call avoids macro/conditionals nesting checking, since the contents of 531260484Sobrien the line are assumed to replace the contents of a line already scanned. 531360484Sobrien 531460484Sobrien An appropriate use of this function would be substition of input lines when 531560484Sobrien called by md_start_line_hook(). The given line is assumed to already be 531660484Sobrien properly scrubbed. */ 531760484Sobrien 531860484Sobrienvoid 531960484Sobrieninput_scrub_insert_line (line) 532077298Sobrien const char *line; 532160484Sobrien{ 532260484Sobrien sb newline; 532360484Sobrien sb_new (&newline); 532460484Sobrien sb_add_string (&newline, line); 532560484Sobrien input_scrub_include_sb (&newline, input_line_pointer, 0); 532660484Sobrien sb_kill (&newline); 532760484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 532860484Sobrien} 532960484Sobrien 533060484Sobrien/* Insert a file into the input stream; the path must resolve to an actual 533177298Sobrien file; no include path searching or dependency registering is performed. */ 533260484Sobrien 533360484Sobrienvoid 533460484Sobrieninput_scrub_insert_file (path) 533577298Sobrien char *path; 533660484Sobrien{ 533760484Sobrien input_scrub_include_file (path, input_line_pointer); 533860484Sobrien buffer_limit = input_scrub_next_buffer (&input_line_pointer); 533960484Sobrien} 5340