171671b9obrien/* BFD back-end for ieee-695 objects.
271671b9obrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3d0f678fdim   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
471671b9obrien   Free Software Foundation, Inc.
571671b9obrien
671671b9obrien   Written by Steve Chamberlain of Cygnus Support.
771671b9obrien
871671b9obrien   This file is part of BFD, the Binary File Descriptor library.
971671b9obrien
1071671b9obrien   This program is free software; you can redistribute it and/or modify
1171671b9obrien   it under the terms of the GNU General Public License as published by
1271671b9obrien   the Free Software Foundation; either version 2 of the License, or
1371671b9obrien   (at your option) any later version.
1471671b9obrien
1571671b9obrien   This program is distributed in the hope that it will be useful,
1671671b9obrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1771671b9obrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1871671b9obrien   GNU General Public License for more details.
1971671b9obrien
2071671b9obrien   You should have received a copy of the GNU General Public License
2171671b9obrien   along with this program; if not, write to the Free Software
220acbbeedim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2371671b9obrien
2471671b9obrien#define KEEPMINUSPCININST 0
2571671b9obrien
2671671b9obrien/* IEEE 695 format is a stream of records, which we parse using a simple one-
2771671b9obrien   token (which is one byte in this lexicon) lookahead recursive decent
2871671b9obrien   parser.  */
2971671b9obrien
3071671b9obrien#include "sysdep.h"
31d0f678fdim#include "bfd.h"
3271671b9obrien#include "libbfd.h"
3371671b9obrien#include "ieee.h"
3471671b9obrien#include "libieee.h"
3571671b9obrien#include "safe-ctype.h"
3671671b9obrien
3771671b9obrienstruct output_buffer_struct
3871671b9obrien{
3971671b9obrien  unsigned char *ptrp;
4071671b9obrien  int buffer;
4171671b9obrien};
4271671b9obrien
430acbbeedimstatic unsigned char *output_ptr_start;
440acbbeedimstatic unsigned char *output_ptr;
450acbbeedimstatic unsigned char *output_ptr_end;
460acbbeedimstatic unsigned char *input_ptr_start;
470acbbeedimstatic unsigned char *input_ptr;
480acbbeedimstatic unsigned char *input_ptr_end;
490acbbeedimstatic bfd *input_bfd;
500acbbeedimstatic bfd *output_bfd;
510acbbeedimstatic int output_buffer;
520acbbeedim
530acbbeedim
540acbbeedimstatic void block (void);
5571671b9obrien
5671671b9obrien/* Functions for writing to ieee files in the strange way that the
570acbbeedim   standard requires.  */
5871671b9obrien
5971671b9obrienstatic bfd_boolean
600acbbeedimieee_write_byte (bfd *abfd, int barg)
6171671b9obrien{
6271671b9obrien  bfd_byte byte;
6371671b9obrien
6471671b9obrien  byte = barg;
650acbbeedim  if (bfd_bwrite ((void *) &byte, (bfd_size_type) 1, abfd) != 1)
6671671b9obrien    return FALSE;
6771671b9obrien  return TRUE;
6871671b9obrien}
6971671b9obrien
7071671b9obrienstatic bfd_boolean
710acbbeedimieee_write_2bytes (bfd *abfd, int bytes)
7271671b9obrien{
7371671b9obrien  bfd_byte buffer[2];
7471671b9obrien
7571671b9obrien  buffer[0] = bytes >> 8;
7671671b9obrien  buffer[1] = bytes & 0xff;
770acbbeedim  if (bfd_bwrite ((void *) buffer, (bfd_size_type) 2, abfd) != 2)
7871671b9obrien    return FALSE;
7971671b9obrien  return TRUE;
8071671b9obrien}
8171671b9obrien
8271671b9obrienstatic bfd_boolean
830acbbeedimieee_write_int (bfd *abfd, bfd_vma value)
8471671b9obrien{
8571671b9obrien  if (value <= 127)
8671671b9obrien    {
8771671b9obrien      if (! ieee_write_byte (abfd, (bfd_byte) value))
8871671b9obrien	return FALSE;
8971671b9obrien    }
9071671b9obrien  else
9171671b9obrien    {
9271671b9obrien      unsigned int length;
9371671b9obrien
9471671b9obrien      /* How many significant bytes ?  */
9571671b9obrien      /* FIXME FOR LONGER INTS.  */
9671671b9obrien      if (value & 0xff000000)
9771671b9obrien	length = 4;
9871671b9obrien      else if (value & 0x00ff0000)
9971671b9obrien	length = 3;
10071671b9obrien      else if (value & 0x0000ff00)
10171671b9obrien	length = 2;
10271671b9obrien      else
10371671b9obrien	length = 1;
10471671b9obrien
10571671b9obrien      if (! ieee_write_byte (abfd,
10671671b9obrien			     (bfd_byte) ((int) ieee_number_repeat_start_enum
10771671b9obrien					 + length)))
10871671b9obrien	return FALSE;
10971671b9obrien      switch (length)
11071671b9obrien	{
11171671b9obrien	case 4:
11271671b9obrien	  if (! ieee_write_byte (abfd, (bfd_byte) (value >> 24)))
11371671b9obrien	    return FALSE;
11471671b9obrien	  /* Fall through.  */
11571671b9obrien	case 3:
11671671b9obrien	  if (! ieee_write_byte (abfd, (bfd_byte) (value >> 16)))
11771671b9obrien	    return FALSE;
11871671b9obrien	  /* Fall through.  */
11971671b9obrien	case 2:
12071671b9obrien	  if (! ieee_write_byte (abfd, (bfd_byte) (value >> 8)))
12171671b9obrien	    return FALSE;
12271671b9obrien	  /* Fall through.  */
12371671b9obrien	case 1:
12471671b9obrien	  if (! ieee_write_byte (abfd, (bfd_byte) (value)))
12571671b9obrien	    return FALSE;
12671671b9obrien	}
12771671b9obrien    }
12871671b9obrien
12971671b9obrien  return TRUE;
13071671b9obrien}
13171671b9obrien
13271671b9obrienstatic bfd_boolean
1330acbbeedimieee_write_id (bfd *abfd, const char *id)
13471671b9obrien{
13571671b9obrien  size_t length = strlen (id);
13671671b9obrien
13771671b9obrien  if (length <= 127)
13871671b9obrien    {
13971671b9obrien      if (! ieee_write_byte (abfd, (bfd_byte) length))
14071671b9obrien	return FALSE;
14171671b9obrien    }
14271671b9obrien  else if (length < 255)
14371671b9obrien    {
14471671b9obrien      if (! ieee_write_byte (abfd, ieee_extension_length_1_enum)
14571671b9obrien	  || ! ieee_write_byte (abfd, (bfd_byte) length))
14671671b9obrien	return FALSE;
14771671b9obrien    }
14871671b9obrien  else if (length < 65535)
14971671b9obrien    {
15071671b9obrien      if (! ieee_write_byte (abfd, ieee_extension_length_2_enum)
15171671b9obrien	  || ! ieee_write_2bytes (abfd, (int) length))
15271671b9obrien	return FALSE;
15371671b9obrien    }
15471671b9obrien  else
15571671b9obrien    {
15671671b9obrien      (*_bfd_error_handler)
15771671b9obrien	(_("%s: string too long (%d chars, max 65535)"),
15871671b9obrien	 bfd_get_filename (abfd), length);
15971671b9obrien      bfd_set_error (bfd_error_invalid_operation);
16071671b9obrien      return FALSE;
16171671b9obrien    }
16271671b9obrien
1630acbbeedim  if (bfd_bwrite ((void *) id, (bfd_size_type) length, abfd) != length)
16471671b9obrien    return FALSE;
16571671b9obrien  return TRUE;
16671671b9obrien}
16771671b9obrien
16871671b9obrien/* Functions for reading from ieee files in the strange way that the
16971671b9obrien   standard requires.  */
17071671b9obrien
1710acbbeedim#define this_byte(ieee)           *((ieee)->input_p)
1720acbbeedim#define next_byte(ieee)            ((ieee)->input_p++)
17371671b9obrien#define this_byte_and_next(ieee) (*((ieee)->input_p++))
17471671b9obrien
17571671b9obrienstatic unsigned short
1760acbbeedimread_2bytes (common_header_type *ieee)
17771671b9obrien{
17871671b9obrien  unsigned char c1 = this_byte_and_next (ieee);
17971671b9obrien  unsigned char c2 = this_byte_and_next (ieee);
18071671b9obrien
18171671b9obrien  return (c1 << 8) | c2;
18271671b9obrien}
18371671b9obrien
18471671b9obrienstatic void
1850acbbeedimbfd_get_string (common_header_type *ieee, char *string, size_t length)
18671671b9obrien{
18771671b9obrien  size_t i;
18871671b9obrien
18971671b9obrien  for (i = 0; i < length; i++)
19071671b9obrien    string[i] = this_byte_and_next (ieee);
19171671b9obrien}
19271671b9obrien
19371671b9obrienstatic char *
1940acbbeedimread_id (common_header_type *ieee)
19571671b9obrien{
19671671b9obrien  size_t length;
19771671b9obrien  char *string;
19871671b9obrien
19971671b9obrien  length = this_byte_and_next (ieee);
20071671b9obrien  if (length <= 0x7f)
2010acbbeedim    /* Simple string of length 0 to 127.  */
2020acbbeedim    ;
2030acbbeedim
20471671b9obrien  else if (length == 0xde)
2050acbbeedim    /* Length is next byte, allowing 0..255.  */
2060acbbeedim    length = this_byte_and_next (ieee);
2070acbbeedim
20871671b9obrien  else if (length == 0xdf)
20971671b9obrien    {
21071671b9obrien      /* Length is next two bytes, allowing 0..65535.  */
21171671b9obrien      length = this_byte_and_next (ieee);
21271671b9obrien      length = (length * 256) + this_byte_and_next (ieee);
21371671b9obrien    }
21471671b9obrien
21571671b9obrien  /* Buy memory and read string.  */
21671671b9obrien  string = bfd_alloc (ieee->abfd, (bfd_size_type) length + 1);
21771671b9obrien  if (!string)
21871671b9obrien    return NULL;
21971671b9obrien  bfd_get_string (ieee, string, length);
22071671b9obrien  string[length] = 0;
22171671b9obrien  return string;
22271671b9obrien}
22371671b9obrien
22471671b9obrienstatic bfd_boolean
2250acbbeedimieee_write_expression (bfd *abfd,
2260acbbeedim		       bfd_vma value,
2270acbbeedim		       asymbol *symbol,
2280acbbeedim		       bfd_boolean pcrel,
2290acbbeedim		       unsigned int index)
23071671b9obrien{
23171671b9obrien  unsigned int term_count = 0;
23271671b9obrien
23371671b9obrien  if (value != 0)
23471671b9obrien    {
23571671b9obrien      if (! ieee_write_int (abfd, value))
23671671b9obrien	return FALSE;
23771671b9obrien      term_count++;
23871671b9obrien    }
23971671b9obrien
24071671b9obrien  /* Badly formatted binaries can have a missing symbol,
24171671b9obrien     so test here to prevent a seg fault.  */
24271671b9obrien  if (symbol != NULL)
24371671b9obrien    {
24471671b9obrien      if (bfd_is_com_section (symbol->section)
24571671b9obrien	  || bfd_is_und_section (symbol->section))
24671671b9obrien	{
24771671b9obrien	  /* Def of a common symbol.  */
24871671b9obrien	  if (! ieee_write_byte (abfd, ieee_variable_X_enum)
24971671b9obrien	      || ! ieee_write_int (abfd, symbol->value))
25071671b9obrien	    return FALSE;
25171671b9obrien	  term_count ++;
25271671b9obrien	}
25371671b9obrien      else if (! bfd_is_abs_section (symbol->section))
25471671b9obrien	{
25571671b9obrien	  /* Ref to defined symbol -  */
25671671b9obrien	  if (symbol->flags & BSF_GLOBAL)
25771671b9obrien	    {
25871671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_I_enum)
25971671b9obrien		  || ! ieee_write_int (abfd, symbol->value))
26071671b9obrien		return FALSE;
26171671b9obrien	      term_count++;
26271671b9obrien	    }
26371671b9obrien	  else if (symbol->flags & (BSF_LOCAL | BSF_SECTION_SYM))
26471671b9obrien	    {
26571671b9obrien	      /* This is a reference to a defined local symbol.  We can
26671671b9obrien		 easily do a local as a section+offset.  */
26771671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_R_enum)
26871671b9obrien		  || ! ieee_write_byte (abfd,
26971671b9obrien					(bfd_byte) (symbol->section->index
27071671b9obrien						    + IEEE_SECTION_NUMBER_BASE)))
27171671b9obrien		return FALSE;
27271671b9obrien
27371671b9obrien	      term_count++;
27471671b9obrien	      if (symbol->value != 0)
27571671b9obrien		{
27671671b9obrien		  if (! ieee_write_int (abfd, symbol->value))
27771671b9obrien		    return FALSE;
27871671b9obrien		  term_count++;
27971671b9obrien		}
28071671b9obrien	    }
28171671b9obrien	  else
28271671b9obrien	    {
28371671b9obrien	      (*_bfd_error_handler)
28471671b9obrien		(_("%s: unrecognized symbol `%s' flags 0x%x"),
28571671b9obrien		 bfd_get_filename (abfd), bfd_asymbol_name (symbol),
28671671b9obrien		 symbol->flags);
28771671b9obrien	      bfd_set_error (bfd_error_invalid_operation);
28871671b9obrien	      return FALSE;
28971671b9obrien	    }
29071671b9obrien	}
29171671b9obrien    }
29271671b9obrien
29371671b9obrien  if (pcrel)
29471671b9obrien    {
29571671b9obrien      /* Subtract the pc from here by asking for PC of this section.  */
29671671b9obrien      if (! ieee_write_byte (abfd, ieee_variable_P_enum)
29771671b9obrien	  || ! ieee_write_byte (abfd,
29871671b9obrien				(bfd_byte) (index + IEEE_SECTION_NUMBER_BASE))
29971671b9obrien	  || ! ieee_write_byte (abfd, ieee_function_minus_enum))
30071671b9obrien	return FALSE;
30171671b9obrien    }
30271671b9obrien
30371671b9obrien  /* Handle the degenerate case of a 0 address.  */
30471671b9obrien  if (term_count == 0)
30571671b9obrien    if (! ieee_write_int (abfd, (bfd_vma) 0))
30671671b9obrien      return FALSE;
30771671b9obrien
30871671b9obrien  while (term_count > 1)
30971671b9obrien    {
31071671b9obrien      if (! ieee_write_byte (abfd, ieee_function_plus_enum))
31171671b9obrien	return FALSE;
31271671b9obrien      term_count--;
31371671b9obrien    }
31471671b9obrien
31571671b9obrien  return TRUE;
31671671b9obrien}
31771671b9obrien
31871671b9obrien/* Writes any integer into the buffer supplied and always takes 5 bytes.  */
31971671b9obrien
32071671b9obrienstatic void
3210acbbeedimieee_write_int5 (bfd_byte *buffer, bfd_vma value)
32271671b9obrien{
32371671b9obrien  buffer[0] = (bfd_byte) ieee_number_repeat_4_enum;
32471671b9obrien  buffer[1] = (value >> 24) & 0xff;
32571671b9obrien  buffer[2] = (value >> 16) & 0xff;
32671671b9obrien  buffer[3] = (value >> 8) & 0xff;
32771671b9obrien  buffer[4] = (value >> 0) & 0xff;
32871671b9obrien}
32971671b9obrien
33071671b9obrienstatic bfd_boolean
3310acbbeedimieee_write_int5_out (bfd *abfd, bfd_vma value)
33271671b9obrien{
33371671b9obrien  bfd_byte b[5];
33471671b9obrien
33571671b9obrien  ieee_write_int5 (b, value);
3360acbbeedim  if (bfd_bwrite ((void *) b, (bfd_size_type) 5, abfd) != 5)
33771671b9obrien    return FALSE;
33871671b9obrien  return TRUE;
33971671b9obrien}
34071671b9obrien
34171671b9obrienstatic bfd_boolean
3420acbbeedimparse_int (common_header_type *ieee, bfd_vma *value_ptr)
34371671b9obrien{
34471671b9obrien  int value = this_byte (ieee);
34571671b9obrien  int result;
34671671b9obrien
34771671b9obrien  if (value >= 0 && value <= 127)
34871671b9obrien    {
34971671b9obrien      *value_ptr = value;
35071671b9obrien      next_byte (ieee);
35171671b9obrien      return TRUE;
35271671b9obrien    }
35371671b9obrien  else if (value >= 0x80 && value <= 0x88)
35471671b9obrien    {
35571671b9obrien      unsigned int count = value & 0xf;
35671671b9obrien
35771671b9obrien      result = 0;
35871671b9obrien      next_byte (ieee);
35971671b9obrien      while (count)
36071671b9obrien	{
36171671b9obrien	  result = (result << 8) | this_byte_and_next (ieee);
36271671b9obrien	  count--;
36371671b9obrien	}
36471671b9obrien      *value_ptr = result;
36571671b9obrien      return TRUE;
36671671b9obrien    }
36771671b9obrien  return FALSE;
36871671b9obrien}
36971671b9obrien
37071671b9obrienstatic int
3710acbbeedimparse_i (common_header_type *ieee, bfd_boolean *ok)
37271671b9obrien{
373d0f678fdim  bfd_vma x = 0;
37471671b9obrien  *ok = parse_int (ieee, &x);
37571671b9obrien  return x;
37671671b9obrien}
37771671b9obrien
37871671b9obrienstatic bfd_vma
3790acbbeedimmust_parse_int (common_header_type *ieee)
38071671b9obrien{
381d0f678fdim  bfd_vma result = 0;
38271671b9obrien  BFD_ASSERT (parse_int (ieee, &result));
38371671b9obrien  return result;
38471671b9obrien}
38571671b9obrien
38671671b9obrientypedef struct
38771671b9obrien{
38871671b9obrien  bfd_vma value;
38971671b9obrien  asection *section;
39071671b9obrien  ieee_symbol_index_type symbol;
39171671b9obrien} ieee_value_type;
39271671b9obrien
39371671b9obrien
39471671b9obrien#if KEEPMINUSPCININST
39571671b9obrien
39671671b9obrien#define SRC_MASK(arg) arg
39771671b9obrien#define PCREL_OFFSET FALSE
39871671b9obrien
39971671b9obrien#else
40071671b9obrien
40171671b9obrien#define SRC_MASK(arg) 0
40271671b9obrien#define PCREL_OFFSET TRUE
40371671b9obrien
40471671b9obrien#endif
40571671b9obrien
40671671b9obrienstatic reloc_howto_type abs32_howto =
40771671b9obrien  HOWTO (1,
40871671b9obrien	 0,
40971671b9obrien	 2,
41071671b9obrien	 32,
41171671b9obrien	 FALSE,
41271671b9obrien	 0,
41371671b9obrien	 complain_overflow_bitfield,
41471671b9obrien	 0,
41571671b9obrien	 "abs32",
41671671b9obrien	 TRUE,
41771671b9obrien	 0xffffffff,
41871671b9obrien	 0xffffffff,
41971671b9obrien	 FALSE);
42071671b9obrien
42171671b9obrienstatic reloc_howto_type abs16_howto =
42271671b9obrien  HOWTO (1,
42371671b9obrien	 0,
42471671b9obrien	 1,
42571671b9obrien	 16,
42671671b9obrien	 FALSE,
42771671b9obrien	 0,
42871671b9obrien	 complain_overflow_bitfield,
42971671b9obrien	 0,
43071671b9obrien	 "abs16",
43171671b9obrien	 TRUE,
43271671b9obrien	 0x0000ffff,
43371671b9obrien	 0x0000ffff,
43471671b9obrien	 FALSE);
43571671b9obrien
43671671b9obrienstatic reloc_howto_type abs8_howto =
43771671b9obrien  HOWTO (1,
43871671b9obrien	 0,
43971671b9obrien	 0,
44071671b9obrien	 8,
44171671b9obrien	 FALSE,
44271671b9obrien	 0,
44371671b9obrien	 complain_overflow_bitfield,
44471671b9obrien	 0,
44571671b9obrien	 "abs8",
44671671b9obrien	 TRUE,
44771671b9obrien	 0x000000ff,
44871671b9obrien	 0x000000ff,
44971671b9obrien	 FALSE);
45071671b9obrien
45171671b9obrienstatic reloc_howto_type rel32_howto =
45271671b9obrien  HOWTO (1,
45371671b9obrien	 0,
45471671b9obrien	 2,
45571671b9obrien	 32,
45671671b9obrien	 TRUE,
45771671b9obrien	 0,
45871671b9obrien	 complain_overflow_signed,
45971671b9obrien	 0,
46071671b9obrien	 "rel32",
46171671b9obrien	 TRUE,
46271671b9obrien	 SRC_MASK (0xffffffff),
46371671b9obrien	 0xffffffff,
46471671b9obrien	 PCREL_OFFSET);
46571671b9obrien
46671671b9obrienstatic reloc_howto_type rel16_howto =
46771671b9obrien  HOWTO (1,
46871671b9obrien	 0,
46971671b9obrien	 1,
47071671b9obrien	 16,
47171671b9obrien	 TRUE,
47271671b9obrien	 0,
47371671b9obrien	 complain_overflow_signed,
47471671b9obrien	 0,
47571671b9obrien	 "rel16",
47671671b9obrien	 TRUE,
47771671b9obrien	 SRC_MASK (0x0000ffff),
47871671b9obrien	 0x0000ffff,
47971671b9obrien	 PCREL_OFFSET);
48071671b9obrien
48171671b9obrienstatic reloc_howto_type rel8_howto =
48271671b9obrien  HOWTO (1,
48371671b9obrien	 0,
48471671b9obrien	 0,
48571671b9obrien	 8,
48671671b9obrien	 TRUE,
48771671b9obrien	 0,
48871671b9obrien	 complain_overflow_signed,
48971671b9obrien	 0,
49071671b9obrien	 "rel8",
49171671b9obrien	 TRUE,
49271671b9obrien	 SRC_MASK (0x000000ff),
49371671b9obrien	 0x000000ff,
49471671b9obrien	 PCREL_OFFSET);
49571671b9obrien
49671671b9obrienstatic ieee_symbol_index_type NOSYMBOL = {0, 0};
49771671b9obrien
49871671b9obrienstatic void
4990acbbeedimparse_expression (ieee_data_type *ieee,
5000acbbeedim		  bfd_vma *value,
5010acbbeedim		  ieee_symbol_index_type *symbol,
5020acbbeedim		  bfd_boolean *pcrel,
5030acbbeedim		  unsigned int *extra,
5040acbbeedim		  asection **section)
50571671b9obrien
50671671b9obrien{
5070acbbeedim  bfd_boolean loop = TRUE;
5080acbbeedim  ieee_value_type stack[10];
5090acbbeedim  ieee_value_type *sp = stack;
5100acbbeedim  asection *dummy;
5110acbbeedim
51271671b9obrien#define POS sp[1]
51371671b9obrien#define TOS sp[0]
51471671b9obrien#define NOS sp[-1]
51571671b9obrien#define INC sp++;
51671671b9obrien#define DEC sp--;
51771671b9obrien
51871671b9obrien  /* The stack pointer always points to the next unused location.  */
5190acbbeedim#define PUSH(x,y,z) TOS.symbol = x; TOS.section = y; TOS.value = z; INC;
5200acbbeedim#define POP(x,y,z)  DEC; x = TOS.symbol; y = TOS.section; z = TOS.value;
52171671b9obrien
52271671b9obrien  while (loop && ieee->h.input_p < ieee->h.last_byte)
52371671b9obrien    {
52471671b9obrien      switch (this_byte (&(ieee->h)))
52571671b9obrien	{
52671671b9obrien	case ieee_variable_P_enum:
52771671b9obrien	  /* P variable, current program counter for section n.  */
52871671b9obrien	  {
52971671b9obrien	    int section_n;
53071671b9obrien
53171671b9obrien	    next_byte (&(ieee->h));
53271671b9obrien	    *pcrel = TRUE;
53371671b9obrien	    section_n = must_parse_int (&(ieee->h));
53471671b9obrien	    PUSH (NOSYMBOL, bfd_abs_section_ptr, 0);
53571671b9obrien	    break;
53671671b9obrien	  }
53771671b9obrien	case ieee_variable_L_enum:
53871671b9obrien	  /* L variable  address of section N.  */
53971671b9obrien	  next_byte (&(ieee->h));
54071671b9obrien	  PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0);
54171671b9obrien	  break;
54271671b9obrien	case ieee_variable_R_enum:
54371671b9obrien	  /* R variable, logical address of section module.  */
54471671b9obrien	  /* FIXME, this should be different to L.  */
54571671b9obrien	  next_byte (&(ieee->h));
54671671b9obrien	  PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0);
54771671b9obrien	  break;
54871671b9obrien	case ieee_variable_S_enum:
54971671b9obrien	  /* S variable, size in MAUS of section module.  */
55071671b9obrien	  next_byte (&(ieee->h));
55171671b9obrien	  PUSH (NOSYMBOL,
55271671b9obrien		0,
5530acbbeedim		ieee->section_table[must_parse_int (&(ieee->h))]->size);
55471671b9obrien	  break;
55571671b9obrien	case ieee_variable_I_enum:
55671671b9obrien	  /* Push the address of variable n.  */
55771671b9obrien	  {
55871671b9obrien	    ieee_symbol_index_type sy;
5590acbbeedim
56071671b9obrien	    next_byte (&(ieee->h));
56171671b9obrien	    sy.index = (int) must_parse_int (&(ieee->h));
56271671b9obrien	    sy.letter = 'I';
56371671b9obrien
56471671b9obrien	    PUSH (sy, bfd_abs_section_ptr, 0);
56571671b9obrien	  }
56671671b9obrien	  break;
56771671b9obrien	case ieee_variable_X_enum:
56871671b9obrien	  /* Push the address of external variable n.  */
56971671b9obrien	  {
57071671b9obrien	    ieee_symbol_index_type sy;
5710acbbeedim
57271671b9obrien	    next_byte (&(ieee->h));
57371671b9obrien	    sy.index = (int) (must_parse_int (&(ieee->h)));
57471671b9obrien	    sy.letter = 'X';
57571671b9obrien
57671671b9obrien	    PUSH (sy, bfd_und_section_ptr, 0);
57771671b9obrien	  }
57871671b9obrien	  break;
57971671b9obrien	case ieee_function_minus_enum:
58071671b9obrien	  {
58171671b9obrien	    bfd_vma value1, value2;
58271671b9obrien	    asection *section1, *section_dummy;
58371671b9obrien	    ieee_symbol_index_type sy;
5840acbbeedim
58571671b9obrien	    next_byte (&(ieee->h));
58671671b9obrien
58771671b9obrien	    POP (sy, section1, value1);
58871671b9obrien	    POP (sy, section_dummy, value2);
58971671b9obrien	    PUSH (sy, section1 ? section1 : section_dummy, value2 - value1);
59071671b9obrien	  }
59171671b9obrien	  break;
59271671b9obrien	case ieee_function_plus_enum:
59371671b9obrien	  {
59471671b9obrien	    bfd_vma value1, value2;
59571671b9obrien	    asection *section1;
59671671b9obrien	    asection *section2;
59771671b9obrien	    ieee_symbol_index_type sy1;
59871671b9obrien	    ieee_symbol_index_type sy2;
5990acbbeedim
60071671b9obrien	    next_byte (&(ieee->h));
60171671b9obrien
60271671b9obrien	    POP (sy1, section1, value1);
60371671b9obrien	    POP (sy2, section2, value2);
60471671b9obrien	    PUSH (sy1.letter ? sy1 : sy2,
60571671b9obrien		  bfd_is_abs_section (section1) ? section2 : section1,
60671671b9obrien		  value1 + value2);
60771671b9obrien	  }
60871671b9obrien	  break;
60971671b9obrien	default:
61071671b9obrien	  {
61171671b9obrien	    bfd_vma va;
6120acbbeedim
61371671b9obrien	    BFD_ASSERT (this_byte (&(ieee->h)) < (int) ieee_variable_A_enum
61471671b9obrien		    || this_byte (&(ieee->h)) > (int) ieee_variable_Z_enum);
61571671b9obrien	    if (parse_int (&(ieee->h), &va))
61671671b9obrien	      {
61771671b9obrien		PUSH (NOSYMBOL, bfd_abs_section_ptr, va);
61871671b9obrien	      }
61971671b9obrien	    else
6200acbbeedim	      /* Thats all that we can understand.  */
6210acbbeedim	      loop = FALSE;
62271671b9obrien	  }
62371671b9obrien	}
62471671b9obrien    }
62571671b9obrien
62671671b9obrien  /* As far as I can see there is a bug in the Microtec IEEE output
62771671b9obrien     which I'm using to scan, whereby the comma operator is omitted
62871671b9obrien     sometimes in an expression, giving expressions with too many
62971671b9obrien     terms.  We can tell if that's the case by ensuring that
63071671b9obrien     sp == stack here.  If not, then we've pushed something too far,
63171671b9obrien     so we keep adding.  */
63271671b9obrien  while (sp != stack + 1)
63371671b9obrien    {
63471671b9obrien      asection *section1;
63571671b9obrien      ieee_symbol_index_type sy1;
6360acbbeedim
63771671b9obrien      POP (sy1, section1, *extra);
63871671b9obrien    }
63971671b9obrien
64071671b9obrien  POP (*symbol, dummy, *value);
64171671b9obrien  if (section)
64271671b9obrien    *section = dummy;
64371671b9obrien}
64471671b9obrien
64571671b9obrien
64671671b9obrien#define ieee_seek(ieee, offset) \
64771671b9obrien  do								\
64871671b9obrien    {								\
64971671b9obrien      ieee->h.input_p = ieee->h.first_byte + offset;		\
65071671b9obrien      ieee->h.last_byte = (ieee->h.first_byte			\
65171671b9obrien			   + ieee_part_after (ieee, offset));	\
65271671b9obrien    }								\
65371671b9obrien  while (0)
65471671b9obrien
65571671b9obrien#define ieee_pos(ieee) \
65671671b9obrien  (ieee->h.input_p - ieee->h.first_byte)
65771671b9obrien
65871671b9obrien/* Find the first part of the ieee file after HERE.  */
65971671b9obrien
66071671b9obrienstatic file_ptr
6610acbbeedimieee_part_after (ieee_data_type *ieee, file_ptr here)
66271671b9obrien{
66371671b9obrien  int part;
66471671b9obrien  file_ptr after = ieee->w.r.me_record;
66571671b9obrien
66671671b9obrien  /* File parts can come in any order, except that module end is
66771671b9obrien     guaranteed to be last (and the header first).  */
66871671b9obrien  for (part = 0; part < N_W_VARIABLES; part++)
66971671b9obrien    if (ieee->w.offset[part] > here && after > ieee->w.offset[part])
67071671b9obrien      after = ieee->w.offset[part];
67171671b9obrien
67271671b9obrien  return after;
67371671b9obrien}
67471671b9obrien
67571671b9obrienstatic unsigned int last_index;
67671671b9obrienstatic char last_type;		/* Is the index for an X or a D.  */
67771671b9obrien
67871671b9obrienstatic ieee_symbol_type *
6790acbbeedimget_symbol (bfd *abfd ATTRIBUTE_UNUSED,
6800acbbeedim	    ieee_data_type *ieee,
6810acbbeedim	    ieee_symbol_type *last_symbol,
6820acbbeedim	    unsigned int *symbol_count,
6830acbbeedim	    ieee_symbol_type ***pptr,
6840acbbeedim	    unsigned int *max_index,
6850acbbeedim	    int this_type)
68671671b9obrien{
68771671b9obrien  /* Need a new symbol.  */
68871671b9obrien  unsigned int new_index = must_parse_int (&(ieee->h));
68971671b9obrien
69071671b9obrien  if (new_index != last_index || this_type != last_type)
69171671b9obrien    {
69271671b9obrien      ieee_symbol_type *new_symbol;
69371671b9obrien      bfd_size_type amt = sizeof (ieee_symbol_type);
69471671b9obrien
6950acbbeedim      new_symbol = bfd_alloc (ieee->h.abfd, amt);
69671671b9obrien      if (!new_symbol)
69771671b9obrien	return NULL;
69871671b9obrien
69971671b9obrien      new_symbol->index = new_index;
70071671b9obrien      last_index = new_index;
70171671b9obrien      (*symbol_count)++;
70271671b9obrien      **pptr = new_symbol;
70371671b9obrien      *pptr = &new_symbol->next;
70471671b9obrien      if (new_index > *max_index)
70571671b9obrien	*max_index = new_index;
70671671b9obrien
70771671b9obrien      last_type = this_type;
70871671b9obrien      new_symbol->symbol.section = bfd_abs_section_ptr;
70971671b9obrien      return new_symbol;
71071671b9obrien    }
71171671b9obrien  return last_symbol;
71271671b9obrien}
71371671b9obrien
71471671b9obrienstatic bfd_boolean
7150acbbeedimieee_slurp_external_symbols (bfd *abfd)
71671671b9obrien{
71771671b9obrien  ieee_data_type *ieee = IEEE_DATA (abfd);
71871671b9obrien  file_ptr offset = ieee->w.r.external_part;
71971671b9obrien
72071671b9obrien  ieee_symbol_type **prev_symbols_ptr = &ieee->external_symbols;
72171671b9obrien  ieee_symbol_type **prev_reference_ptr = &ieee->external_reference;
7220acbbeedim  ieee_symbol_type *symbol = NULL;
72371671b9obrien  unsigned int symbol_count = 0;
72471671b9obrien  bfd_boolean loop = TRUE;
7250acbbeedim
72671671b9obrien  last_index = 0xffffff;
72771671b9obrien  ieee->symbol_table_full = TRUE;
72871671b9obrien
72971671b9obrien  ieee_seek (ieee, offset);
73071671b9obrien
73171671b9obrien  while (loop)
73271671b9obrien    {
73371671b9obrien      switch (this_byte (&(ieee->h)))
73471671b9obrien	{
73571671b9obrien	case ieee_nn_record:
73671671b9obrien	  next_byte (&(ieee->h));
73771671b9obrien
73871671b9obrien	  symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
7390acbbeedim			       & prev_symbols_ptr,
7400acbbeedim			       & ieee->external_symbol_max_index, 'I');
74171671b9obrien	  if (symbol == NULL)
74271671b9obrien	    return FALSE;
74371671b9obrien
74471671b9obrien	  symbol->symbol.the_bfd = abfd;
74571671b9obrien	  symbol->symbol.name = read_id (&(ieee->h));
7460acbbeedim	  symbol->symbol.udata.p = NULL;
74771671b9obrien	  symbol->symbol.flags = BSF_NO_FLAGS;
74871671b9obrien	  break;
74971671b9obrien	case ieee_external_symbol_enum:
75071671b9obrien	  next_byte (&(ieee->h));
75171671b9obrien
75271671b9obrien	  symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
75371671b9obrien			       &prev_symbols_ptr,
75471671b9obrien			       &ieee->external_symbol_max_index, 'D');
75571671b9obrien	  if (symbol == NULL)
75671671b9obrien	    return FALSE;
75771671b9obrien
75871671b9obrien	  BFD_ASSERT (symbol->index >= ieee->external_symbol_min_index);
75971671b9obrien
76071671b9obrien	  symbol->symbol.the_bfd = abfd;
76171671b9obrien	  symbol->symbol.name = read_id (&(ieee->h));
7620acbbeedim	  symbol->symbol.udata.p = NULL;
76371671b9obrien	  symbol->symbol.flags = BSF_NO_FLAGS;
76471671b9obrien	  break;
76571671b9obrien	case ieee_attribute_record_enum >> 8:
76671671b9obrien	  {
76771671b9obrien	    unsigned int symbol_name_index;
76871671b9obrien	    unsigned int symbol_type_index;
76971671b9obrien	    unsigned int symbol_attribute_def;
770d0f678fdim	    bfd_vma value = 0;
7710acbbeedim
77271671b9obrien	    switch (read_2bytes (&ieee->h))
77371671b9obrien	      {
77471671b9obrien	      case ieee_attribute_record_enum:
77571671b9obrien		symbol_name_index = must_parse_int (&(ieee->h));
77671671b9obrien		symbol_type_index = must_parse_int (&(ieee->h));
77771671b9obrien		symbol_attribute_def = must_parse_int (&(ieee->h));
77871671b9obrien		switch (symbol_attribute_def)
77971671b9obrien		  {
78071671b9obrien		  case 8:
78171671b9obrien		  case 19:
78271671b9obrien		    parse_int (&ieee->h, &value);
78371671b9obrien		    break;
78471671b9obrien		  default:
78571671b9obrien		    (*_bfd_error_handler)
7860acbbeedim		      (_("%B: unimplemented ATI record %u for symbol %u"),
7870acbbeedim		       abfd, symbol_attribute_def, symbol_name_index);
78871671b9obrien		    bfd_set_error (bfd_error_bad_value);
78971671b9obrien		    return FALSE;
79071671b9obrien		    break;
79171671b9obrien		  }
79271671b9obrien		break;
79371671b9obrien	      case ieee_external_reference_info_record_enum:
79471671b9obrien		/* Skip over ATX record.  */
79571671b9obrien		parse_int (&(ieee->h), &value);
79671671b9obrien		parse_int (&(ieee->h), &value);
79771671b9obrien		parse_int (&(ieee->h), &value);
79871671b9obrien		parse_int (&(ieee->h), &value);
79971671b9obrien		break;
80071671b9obrien	      case ieee_atn_record_enum:
80171671b9obrien		/* We may get call optimization information here,
80271671b9obrien		   which we just ignore.  The format is
80371671b9obrien		   {$F1}${CE}{index}{$00}{$3F}{$3F}{#_of_ASNs}.  */
80471671b9obrien		parse_int (&ieee->h, &value);
80571671b9obrien		parse_int (&ieee->h, &value);
80671671b9obrien		parse_int (&ieee->h, &value);
80771671b9obrien		if (value != 0x3f)
80871671b9obrien		  {
80971671b9obrien		    (*_bfd_error_handler)
8100acbbeedim		      (_("%B: unexpected ATN type %d in external part"),
8110acbbeedim			 abfd, (int) value);
81271671b9obrien		    bfd_set_error (bfd_error_bad_value);
81371671b9obrien		    return FALSE;
81471671b9obrien		  }
81571671b9obrien		parse_int (&ieee->h, &value);
81671671b9obrien		parse_int (&ieee->h, &value);
81771671b9obrien		while (value > 0)
81871671b9obrien		  {
81971671b9obrien		    bfd_vma val1;
82071671b9obrien
82171671b9obrien		    --value;
82271671b9obrien
82371671b9obrien		    switch (read_2bytes (&ieee->h))
82471671b9obrien		      {
82571671b9obrien		      case ieee_asn_record_enum:
82671671b9obrien			parse_int (&ieee->h, &val1);
82771671b9obrien			parse_int (&ieee->h, &val1);
82871671b9obrien			break;
82971671b9obrien
83071671b9obrien		      default:
83171671b9obrien			(*_bfd_error_handler)
8320acbbeedim			  (_("%B: unexpected type after ATN"), abfd);
83371671b9obrien			bfd_set_error (bfd_error_bad_value);
83471671b9obrien			return FALSE;
83571671b9obrien		      }
83671671b9obrien		  }
83771671b9obrien	      }
83871671b9obrien	  }
83971671b9obrien	  break;
84071671b9obrien	case ieee_value_record_enum >> 8:
84171671b9obrien	  {
84271671b9obrien	    unsigned int symbol_name_index;
84371671b9obrien	    ieee_symbol_index_type symbol_ignore;
84471671b9obrien	    bfd_boolean pcrel_ignore;
84571671b9obrien	    unsigned int extra;
8460acbbeedim
84771671b9obrien	    next_byte (&(ieee->h));
84871671b9obrien	    next_byte (&(ieee->h));
84971671b9obrien
85071671b9obrien	    symbol_name_index = must_parse_int (&(ieee->h));
85171671b9obrien	    parse_expression (ieee,
85271671b9obrien			      &symbol->symbol.value,
85371671b9obrien			      &symbol_ignore,
85471671b9obrien			      &pcrel_ignore,
85571671b9obrien			      &extra,
85671671b9obrien			      &symbol->symbol.section);
85771671b9obrien
85871671b9obrien	    /* Fully linked IEEE-695 files tend to give every symbol
85971671b9obrien               an absolute value.  Try to convert that back into a
86071671b9obrien               section relative value.  FIXME: This won't always to
86171671b9obrien               the right thing.  */
86271671b9obrien	    if (bfd_is_abs_section (symbol->symbol.section)
86371671b9obrien		&& (abfd->flags & HAS_RELOC) == 0)
86471671b9obrien	      {
86571671b9obrien		bfd_vma val;
86671671b9obrien		asection *s;
86771671b9obrien
86871671b9obrien		val = symbol->symbol.value;
86971671b9obrien		for (s = abfd->sections; s != NULL; s = s->next)
87071671b9obrien		  {
8710acbbeedim		    if (val >= s->vma && val < s->vma + s->size)
87271671b9obrien		      {
87371671b9obrien			symbol->symbol.section = s;
87471671b9obrien			symbol->symbol.value -= s->vma;
87571671b9obrien			break;
87671671b9obrien		      }
87771671b9obrien		  }
87871671b9obrien	      }
87971671b9obrien
88071671b9obrien	    symbol->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
88171671b9obrien
88271671b9obrien	  }
88371671b9obrien	  break;
88471671b9obrien	case ieee_weak_external_reference_enum:
88571671b9obrien	  {
88671671b9obrien	    bfd_vma size;
88771671b9obrien	    bfd_vma value;
8880acbbeedim
88971671b9obrien	    next_byte (&(ieee->h));
89071671b9obrien	    /* Throw away the external reference index.  */
89171671b9obrien	    (void) must_parse_int (&(ieee->h));
89271671b9obrien	    /* Fetch the default size if not resolved.  */
89371671b9obrien	    size = must_parse_int (&(ieee->h));
89471671b9obrien	    /* Fetch the default value if available.  */
89571671b9obrien	    if (! parse_int (&(ieee->h), &value))
8960acbbeedim	      value = 0;
89771671b9obrien	    /* This turns into a common.  */
89871671b9obrien	    symbol->symbol.section = bfd_com_section_ptr;
89971671b9obrien	    symbol->symbol.value = size;
90071671b9obrien	  }
90171671b9obrien	  break;
90271671b9obrien
90371671b9obrien	case ieee_external_reference_enum:
90471671b9obrien	  next_byte (&(ieee->h));
90571671b9obrien
90671671b9obrien	  symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
90771671b9obrien			       &prev_reference_ptr,
90871671b9obrien			       &ieee->external_reference_max_index, 'X');
90971671b9obrien	  if (symbol == NULL)
91071671b9obrien	    return FALSE;
91171671b9obrien
91271671b9obrien	  symbol->symbol.the_bfd = abfd;
91371671b9obrien	  symbol->symbol.name = read_id (&(ieee->h));
9140acbbeedim	  symbol->symbol.udata.p = NULL;
91571671b9obrien	  symbol->symbol.section = bfd_und_section_ptr;
91671671b9obrien	  symbol->symbol.value = (bfd_vma) 0;
91771671b9obrien	  symbol->symbol.flags = 0;
91871671b9obrien
91971671b9obrien	  BFD_ASSERT (symbol->index >= ieee->external_reference_min_index);
92071671b9obrien	  break;
92171671b9obrien
92271671b9obrien	default:
92371671b9obrien	  loop = FALSE;
92471671b9obrien	}
92571671b9obrien    }
92671671b9obrien
92771671b9obrien  if (ieee->external_symbol_max_index != 0)
92871671b9obrien    {
92971671b9obrien      ieee->external_symbol_count =
93071671b9obrien	ieee->external_symbol_max_index -
93171671b9obrien	ieee->external_symbol_min_index + 1;
93271671b9obrien    }
93371671b9obrien  else
9340acbbeedim    ieee->external_symbol_count = 0;
93571671b9obrien
93671671b9obrien  if (ieee->external_reference_max_index != 0)
93771671b9obrien    {
93871671b9obrien      ieee->external_reference_count =
93971671b9obrien	ieee->external_reference_max_index -
94071671b9obrien	ieee->external_reference_min_index + 1;
94171671b9obrien    }
94271671b9obrien  else
9430acbbeedim    ieee->external_reference_count = 0;
94471671b9obrien
94571671b9obrien  abfd->symcount =
94671671b9obrien    ieee->external_reference_count + ieee->external_symbol_count;
94771671b9obrien
94871671b9obrien  if (symbol_count != abfd->symcount)
9490acbbeedim    /* There are gaps in the table -- */
9500acbbeedim    ieee->symbol_table_full = FALSE;
95171671b9obrien
9520acbbeedim  *prev_symbols_ptr   = NULL;
9530acbbeedim  *prev_reference_ptr = NULL;
95471671b9obrien
95571671b9obrien  return TRUE;
95671671b9obrien}
95771671b9obrien
95871671b9obrienstatic bfd_boolean
9590acbbeedimieee_slurp_symbol_table (bfd *abfd)
96071671b9obrien{
96171671b9obrien  if (! IEEE_DATA (abfd)->read_symbols)
96271671b9obrien    {
96371671b9obrien      if (! ieee_slurp_external_symbols (abfd))
96471671b9obrien	return FALSE;
96571671b9obrien      IEEE_DATA (abfd)->read_symbols = TRUE;
96671671b9obrien    }
96771671b9obrien  return TRUE;
96871671b9obrien}
96971671b9obrien
97071671b9obrienstatic long
9710acbbeedimieee_get_symtab_upper_bound (bfd *abfd)
97271671b9obrien{
97371671b9obrien  if (! ieee_slurp_symbol_table (abfd))
97471671b9obrien    return -1;
97571671b9obrien
97671671b9obrien  return (abfd->symcount != 0) ?
97771671b9obrien    (abfd->symcount + 1) * (sizeof (ieee_symbol_type *)) : 0;
97871671b9obrien}
97971671b9obrien
98071671b9obrien/* Move from our internal lists to the canon table, and insert in
98171671b9obrien   symbol index order.  */
98271671b9obrien
98371671b9obrienextern const bfd_target ieee_vec;
98471671b9obrien
98571671b9obrienstatic long
9860acbbeedimieee_canonicalize_symtab (bfd *abfd, asymbol **location)
98771671b9obrien{
98871671b9obrien  ieee_symbol_type *symp;
98971671b9obrien  static bfd dummy_bfd;
99071671b9obrien  static asymbol empty_symbol =
99171671b9obrien  {
99271671b9obrien    &dummy_bfd,
99371671b9obrien    " ieee empty",
99471671b9obrien    (symvalue) 0,
99571671b9obrien    BSF_DEBUGGING,
99671671b9obrien    bfd_abs_section_ptr
99771671b9obrien#ifdef __STDC__
99871671b9obrien    /* K&R compilers can't initialise unions.  */
99971671b9obrien    , { 0 }
100071671b9obrien#endif
100171671b9obrien  };
100271671b9obrien
100371671b9obrien  if (abfd->symcount)
100471671b9obrien    {
100571671b9obrien      ieee_data_type *ieee = IEEE_DATA (abfd);
10060acbbeedim
100771671b9obrien      dummy_bfd.xvec = &ieee_vec;
100871671b9obrien      if (! ieee_slurp_symbol_table (abfd))
100971671b9obrien	return -1;
101071671b9obrien
101171671b9obrien      if (! ieee->symbol_table_full)
101271671b9obrien	{
101371671b9obrien	  /* Arrgh - there are gaps in the table, run through and fill them
101471671b9obrien	     up with pointers to a null place.  */
101571671b9obrien	  unsigned int i;
101671671b9obrien
101771671b9obrien	  for (i = 0; i < abfd->symcount; i++)
101871671b9obrien	    location[i] = &empty_symbol;
101971671b9obrien	}
102071671b9obrien
102171671b9obrien      ieee->external_symbol_base_offset = -ieee->external_symbol_min_index;
102271671b9obrien      for (symp = IEEE_DATA (abfd)->external_symbols;
102371671b9obrien	   symp != (ieee_symbol_type *) NULL;
102471671b9obrien	   symp = symp->next)
102571671b9obrien	/* Place into table at correct index locations.  */
102671671b9obrien	location[symp->index + ieee->external_symbol_base_offset] = &symp->symbol;
102771671b9obrien
102871671b9obrien      /* The external refs are indexed in a bit.  */
102971671b9obrien      ieee->external_reference_base_offset =
103071671b9obrien	-ieee->external_reference_min_index + ieee->external_symbol_count;
103171671b9obrien
103271671b9obrien      for (symp = IEEE_DATA (abfd)->external_reference;
103371671b9obrien	   symp != (ieee_symbol_type *) NULL;
103471671b9obrien	   symp = symp->next)
103571671b9obrien	location[symp->index + ieee->external_reference_base_offset] =
103671671b9obrien	  &symp->symbol;
103771671b9obrien    }
103871671b9obrien
103971671b9obrien  if (abfd->symcount)
104071671b9obrien    location[abfd->symcount] = (asymbol *) NULL;
104171671b9obrien
104271671b9obrien  return abfd->symcount;
104371671b9obrien}
104471671b9obrien
104571671b9obrienstatic asection *
10460acbbeedimget_section_entry (bfd *abfd, ieee_data_type *ieee, unsigned int index)
104771671b9obrien{
104871671b9obrien  if (index >= ieee->section_table_size)
104971671b9obrien    {
105071671b9obrien      unsigned int c, i;
105171671b9obrien      asection **n;
105271671b9obrien      bfd_size_type amt;
105371671b9obrien
105471671b9obrien      c = ieee->section_table_size;
105571671b9obrien      if (c == 0)
105671671b9obrien	c = 20;
105771671b9obrien      while (c <= index)
105871671b9obrien	c *= 2;
105971671b9obrien
106071671b9obrien      amt = c;
106171671b9obrien      amt *= sizeof (asection *);
10620acbbeedim      n = bfd_realloc (ieee->section_table, amt);
106371671b9obrien      if (n == NULL)
106471671b9obrien	return NULL;
106571671b9obrien
106671671b9obrien      for (i = ieee->section_table_size; i < c; i++)
106771671b9obrien	n[i] = NULL;
106871671b9obrien
106971671b9obrien      ieee->section_table = n;
107071671b9obrien      ieee->section_table_size = c;
107171671b9obrien    }
107271671b9obrien
107371671b9obrien  if (ieee->section_table[index] == (asection *) NULL)
107471671b9obrien    {
107571671b9obrien      char *tmp = bfd_alloc (abfd, (bfd_size_type) 11);
107671671b9obrien      asection *section;
107771671b9obrien
107871671b9obrien      if (!tmp)
107971671b9obrien	return NULL;
108071671b9obrien      sprintf (tmp, " fsec%4d", index);
108171671b9obrien      section = bfd_make_section (abfd, tmp);
108271671b9obrien      ieee->section_table[index] = section;
108371671b9obrien      section->target_index = index;
108471671b9obrien      ieee->section_table[index] = section;
108571671b9obrien    }
108671671b9obrien  return ieee->section_table[index];
108771671b9obrien}
108871671b9obrien
108971671b9obrienstatic void
10900acbbeedimieee_slurp_sections (bfd *abfd)
109171671b9obrien{
109271671b9obrien  ieee_data_type *ieee = IEEE_DATA (abfd);
109371671b9obrien  file_ptr offset = ieee->w.r.section_part;
109471671b9obrien  char *name;
109571671b9obrien
109671671b9obrien  if (offset != 0)
109771671b9obrien    {
109871671b9obrien      bfd_byte section_type[3];
10990acbbeedim
110071671b9obrien      ieee_seek (ieee, offset);
110171671b9obrien      while (TRUE)
110271671b9obrien	{
110371671b9obrien	  switch (this_byte (&(ieee->h)))
110471671b9obrien	    {
110571671b9obrien	    case ieee_section_type_enum:
110671671b9obrien	      {
110771671b9obrien		asection *section;
110871671b9obrien		unsigned int section_index;
11090acbbeedim
111071671b9obrien		next_byte (&(ieee->h));
111171671b9obrien		section_index = must_parse_int (&(ieee->h));
111271671b9obrien
111371671b9obrien		section = get_section_entry (abfd, ieee, section_index);
111471671b9obrien
111571671b9obrien		section_type[0] = this_byte_and_next (&(ieee->h));
111671671b9obrien
111771671b9obrien		/* Set minimal section attributes. Attributes are
111871671b9obrien		   extended later, based on section contents.  */
111971671b9obrien		switch (section_type[0])
112071671b9obrien		  {
112171671b9obrien		  case 0xC1:
112271671b9obrien		    /* Normal attributes for absolute sections.  */
112371671b9obrien		    section_type[1] = this_byte (&(ieee->h));
112471671b9obrien		    section->flags = SEC_ALLOC;
112571671b9obrien		    switch (section_type[1])
112671671b9obrien		      {
11270acbbeedim			/* AS Absolute section attributes.  */
11280acbbeedim		      case 0xD3:
112971671b9obrien			next_byte (&(ieee->h));
113071671b9obrien			section_type[2] = this_byte (&(ieee->h));
113171671b9obrien			switch (section_type[2])
113271671b9obrien			  {
113371671b9obrien			  case 0xD0:
113471671b9obrien			    /* Normal code.  */
113571671b9obrien			    next_byte (&(ieee->h));
113671671b9obrien			    section->flags |= SEC_CODE;
113771671b9obrien			    break;
113871671b9obrien			  case 0xC4:
113971671b9obrien			    /* Normal data.  */
114071671b9obrien			    next_byte (&(ieee->h));
114171671b9obrien			    section->flags |= SEC_DATA;
114271671b9obrien			    break;
114371671b9obrien			  case 0xD2:
114471671b9obrien			    next_byte (&(ieee->h));
114571671b9obrien			    /* Normal rom data.  */
114671671b9obrien			    section->flags |= SEC_ROM | SEC_DATA;
114771671b9obrien			    break;
114871671b9obrien			  default:
114971671b9obrien			    break;
115071671b9obrien			  }
115171671b9obrien		      }
115271671b9obrien		    break;
11530acbbeedim
11540acbbeedim		    /* Named relocatable sections (type C).  */
11550acbbeedim		  case 0xC3:
115671671b9obrien		    section_type[1] = this_byte (&(ieee->h));
115771671b9obrien		    section->flags = SEC_ALLOC;
115871671b9obrien		    switch (section_type[1])
115971671b9obrien		      {
116071671b9obrien		      case 0xD0:	/* Normal code (CP).  */
116171671b9obrien			next_byte (&(ieee->h));
116271671b9obrien			section->flags |= SEC_CODE;
116371671b9obrien			break;
116471671b9obrien		      case 0xC4:	/* Normal data (CD).  */
116571671b9obrien			next_byte (&(ieee->h));
116671671b9obrien			section->flags |= SEC_DATA;
116771671b9obrien			break;
116871671b9obrien		      case 0xD2:	/* Normal rom data (CR).  */
116971671b9obrien			next_byte (&(ieee->h));
117071671b9obrien			section->flags |= SEC_ROM | SEC_DATA;
117171671b9obrien			break;
117271671b9obrien		      default:
117371671b9obrien			break;
117471671b9obrien		      }
117571671b9obrien		  }
117671671b9obrien
117771671b9obrien		/* Read section name, use it if non empty.  */
117871671b9obrien		name = read_id (&ieee->h);
117971671b9obrien		if (name[0])
118071671b9obrien		  section->name = name;
118171671b9obrien
118271671b9obrien		/* Skip these fields, which we don't care about.  */
118371671b9obrien		{
118471671b9obrien		  bfd_vma parent, brother, context;
11850acbbeedim
118671671b9obrien		  parse_int (&(ieee->h), &parent);
118771671b9obrien		  parse_int (&(ieee->h), &brother);
118871671b9obrien		  parse_int (&(ieee->h), &context);
118971671b9obrien		}
119071671b9obrien	      }
119171671b9obrien	      break;
119271671b9obrien	    case ieee_section_alignment_enum:
119371671b9obrien	      {
119471671b9obrien		unsigned int section_index;
119571671b9obrien		bfd_vma value;
119671671b9obrien		asection *section;
11970acbbeedim
119871671b9obrien		next_byte (&(ieee->h));
119971671b9obrien		section_index = must_parse_int (&ieee->h);
120071671b9obrien		section = get_section_entry (abfd, ieee, section_index);
120171671b9obrien		if (section_index > ieee->section_count)
12020acbbeedim		  ieee->section_count = section_index;
12030acbbeedim
120471671b9obrien		section->alignment_power =
120571671b9obrien		  bfd_log2 (must_parse_int (&ieee->h));
120671671b9obrien		(void) parse_int (&(ieee->h), &value);
120771671b9obrien	      }
120871671b9obrien	      break;
120971671b9obrien	    case ieee_e2_first_byte_enum:
121071671b9obrien	      {
121171671b9obrien		asection *section;
121271671b9obrien		ieee_record_enum_type t;
121371671b9obrien
121471671b9obrien		t = (ieee_record_enum_type) (read_2bytes (&(ieee->h)));
121571671b9obrien		switch (t)
121671671b9obrien		  {
121771671b9obrien		  case ieee_section_size_enum:
121871671b9obrien		    section = ieee->section_table[must_parse_int (&(ieee->h))];
12190acbbeedim		    section->size = must_parse_int (&(ieee->h));
122071671b9obrien		    break;
122171671b9obrien		  case ieee_physical_region_size_enum:
122271671b9obrien		    section = ieee->section_table[must_parse_int (&(ieee->h))];
12230acbbeedim		    section->size = must_parse_int (&(ieee->h));
122471671b9obrien		    break;
122571671b9obrien		  case ieee_region_base_address_enum:
122671671b9obrien		    section = ieee->section_table[must_parse_int (&(ieee->h))];
122771671b9obrien		    section->vma = must_parse_int (&(ieee->h));
122871671b9obrien		    section->lma = section->vma;
122971671b9obrien		    break;
123071671b9obrien		  case ieee_mau_size_enum:
123171671b9obrien		    must_parse_int (&(ieee->h));
123271671b9obrien		    must_parse_int (&(ieee->h));
123371671b9obrien		    break;
123471671b9obrien		  case ieee_m_value_enum:
123571671b9obrien		    must_parse_int (&(ieee->h));
123671671b9obrien		    must_parse_int (&(ieee->h));
123771671b9obrien		    break;
123871671b9obrien		  case ieee_section_base_address_enum:
123971671b9obrien		    section = ieee->section_table[must_parse_int (&(ieee->h))];
124071671b9obrien		    section->vma = must_parse_int (&(ieee->h));
124171671b9obrien		    section->lma = section->vma;
124271671b9obrien		    break;
124371671b9obrien		  case ieee_section_offset_enum:
124471671b9obrien		    (void) must_parse_int (&(ieee->h));
124571671b9obrien		    (void) must_parse_int (&(ieee->h));
124671671b9obrien		    break;
124771671b9obrien		  default:
124871671b9obrien		    return;
124971671b9obrien		  }
125071671b9obrien	      }
125171671b9obrien	      break;
125271671b9obrien	    default:
125371671b9obrien	      return;
125471671b9obrien	    }
125571671b9obrien	}
125671671b9obrien    }
125771671b9obrien}
125871671b9obrien
125971671b9obrien/* Make a section for the debugging information, if any.  We don't try
126071671b9obrien   to interpret the debugging information; we just point the section
126171671b9obrien   at the area in the file so that program which understand can dig it
126271671b9obrien   out.  */
126371671b9obrien
126471671b9obrienstatic bfd_boolean
12650acbbeedimieee_slurp_debug (bfd *abfd)
126671671b9obrien{
126771671b9obrien  ieee_data_type *ieee = IEEE_DATA (abfd);
126871671b9obrien  asection *sec;
126971671b9obrien  file_ptr debug_end;
1270d0f678fdim  flagword flags;
127171671b9obrien
127271671b9obrien  if (ieee->w.r.debug_information_part == 0)
127371671b9obrien    return TRUE;
127471671b9obrien
1275d0f678fdim  flags = SEC_DEBUGGING | SEC_HAS_CONTENTS;
1276d0f678fdim  sec = bfd_make_section_with_flags (abfd, ".debug", flags);
127771671b9obrien  if (sec == NULL)
127871671b9obrien    return FALSE;
127971671b9obrien  sec->filepos = ieee->w.r.debug_information_part;
128071671b9obrien
128171671b9obrien  debug_end = ieee_part_after (ieee, ieee->w.r.debug_information_part);
12820acbbeedim  sec->size = debug_end - ieee->w.r.debug_information_part;
128371671b9obrien
128471671b9obrien  return TRUE;
128571671b9obrien}
128671671b9obrien
128771671b9obrien/* Archive stuff.  */
128871671b9obrien
12890acbbeedimstatic const bfd_target *
12900acbbeedimieee_archive_p (bfd *abfd)
129171671b9obrien{
129271671b9obrien  char *library;
129371671b9obrien  unsigned int i;
129471671b9obrien  unsigned char buffer[512];
129571671b9obrien  file_ptr buffer_offset = 0;
129671671b9obrien  ieee_ar_data_type *save = abfd->tdata.ieee_ar_data;
129771671b9obrien  ieee_ar_data_type *ieee;
129871671b9obrien  bfd_size_type alc_elts;
129971671b9obrien  ieee_ar_obstack_type *elts = NULL;
130071671b9obrien  bfd_size_type amt = sizeof (ieee_ar_data_type);
130171671b9obrien
13020acbbeedim  abfd->tdata.ieee_ar_data = bfd_alloc (abfd, amt);
130371671b9obrien  if (!abfd->tdata.ieee_ar_data)
130471671b9obrien    goto error_ret_restore;
130571671b9obrien  ieee = IEEE_AR_DATA (abfd);
130671671b9obrien
130771671b9obrien  /* Ignore the return value here.  It doesn't matter if we don't read
130871671b9obrien     the entire buffer.  We might have a very small ieee file.  */
13090acbbeedim  bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
131071671b9obrien
131171671b9obrien  ieee->h.first_byte = buffer;
131271671b9obrien  ieee->h.input_p = buffer;
131371671b9obrien
131471671b9obrien  ieee->h.abfd = abfd;
131571671b9obrien
131671671b9obrien  if (this_byte (&(ieee->h)) != Module_Beginning)
131771671b9obrien    goto got_wrong_format_error;
131871671b9obrien
131971671b9obrien  next_byte (&(ieee->h));
132071671b9obrien  library = read_id (&(ieee->h));
132171671b9obrien  if (strcmp (library, "LIBRARY") != 0)
132271671b9obrien    goto got_wrong_format_error;
132371671b9obrien
132471671b9obrien  /* Throw away the filename.  */
132571671b9obrien  read_id (&(ieee->h));
132671671b9obrien
132771671b9obrien  ieee->element_count = 0;
132871671b9obrien  ieee->element_index = 0;
132971671b9obrien
133071671b9obrien  next_byte (&(ieee->h));	/* Drop the ad part.  */
133171671b9obrien  must_parse_int (&(ieee->h));	/* And the two dummy numbers.  */
133271671b9obrien  must_parse_int (&(ieee->h));
133371671b9obrien
133471671b9obrien  alc_elts = 10;
13350acbbeedim  elts = bfd_malloc (alc_elts * sizeof *elts);
133671671b9obrien  if (elts == NULL)
133771671b9obrien    goto error_return;
133871671b9obrien
133971671b9obrien  /* Read the index of the BB table.  */
134071671b9obrien  while (1)
134171671b9obrien    {
134271671b9obrien      int rec;
134371671b9obrien      ieee_ar_obstack_type *t;
134471671b9obrien
134571671b9obrien      rec = read_2bytes (&(ieee->h));
134671671b9obrien      if (rec != (int) ieee_assign_value_to_variable_enum)
134771671b9obrien	break;
134871671b9obrien
134971671b9obrien      if (ieee->element_count >= alc_elts)
135071671b9obrien	{
135171671b9obrien	  ieee_ar_obstack_type *n;
135271671b9obrien
135371671b9obrien	  alc_elts *= 2;
13540acbbeedim	  n = bfd_realloc (elts, alc_elts * sizeof (* elts));
135571671b9obrien	  if (n == NULL)
135671671b9obrien	    goto error_return;
135771671b9obrien	  elts = n;
135871671b9obrien	}
135971671b9obrien
136071671b9obrien      t = &elts[ieee->element_count];
136171671b9obrien      ieee->element_count++;
136271671b9obrien
136371671b9obrien      must_parse_int (&(ieee->h));
136471671b9obrien      t->file_offset = must_parse_int (&(ieee->h));
136571671b9obrien      t->abfd = (bfd *) NULL;
136671671b9obrien
136771671b9obrien      /* Make sure that we don't go over the end of the buffer.  */
136871671b9obrien      if ((size_t) ieee_pos (IEEE_DATA (abfd)) > sizeof (buffer) / 2)
136971671b9obrien	{
137071671b9obrien	  /* Past half way, reseek and reprime.  */
137171671b9obrien	  buffer_offset += ieee_pos (IEEE_DATA (abfd));
137271671b9obrien	  if (bfd_seek (abfd, buffer_offset, SEEK_SET) != 0)
137371671b9obrien	    goto error_return;
137471671b9obrien
137571671b9obrien	  /* Again ignore return value of bfd_bread.  */
13760acbbeedim	  bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
137771671b9obrien	  ieee->h.first_byte = buffer;
137871671b9obrien	  ieee->h.input_p = buffer;
137971671b9obrien	}
138071671b9obrien    }
138171671b9obrien
138271671b9obrien  amt = ieee->element_count;
138371671b9obrien  amt *= sizeof *ieee->elements;
13840acbbeedim  ieee->elements = bfd_alloc (abfd, amt);
138571671b9obrien  if (ieee->elements == NULL)
138671671b9obrien    goto error_return;
138771671b9obrien
138871671b9obrien  memcpy (ieee->elements, elts, (size_t) amt);
138971671b9obrien  free (elts);
139071671b9obrien  elts = NULL;
139171671b9obrien
139271671b9obrien  /* Now scan the area again, and replace BB offsets with file offsets.  */
139371671b9obrien  for (i = 2; i < ieee->element_count; i++)
139471671b9obrien    {
139571671b9obrien      if (bfd_seek (abfd, ieee->elements[i].file_offset, SEEK_SET) != 0)
139671671b9obrien	goto error_return;
139771671b9obrien
139871671b9obrien      /* Again ignore return value of bfd_bread.  */
13990acbbeedim      bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
140071671b9obrien      ieee->h.first_byte = buffer;
140171671b9obrien      ieee->h.input_p = buffer;
140271671b9obrien
140371671b9obrien      next_byte (&(ieee->h));		/* Drop F8.  */
140471671b9obrien      next_byte (&(ieee->h));		/* Drop 14.  */
140571671b9obrien      must_parse_int (&(ieee->h));	/* Drop size of block.  */
140671671b9obrien
140771671b9obrien      if (must_parse_int (&(ieee->h)) != 0)
140871671b9obrien	/* This object has been deleted.  */
140971671b9obrien	ieee->elements[i].file_offset = 0;
141071671b9obrien      else
141171671b9obrien	ieee->elements[i].file_offset = must_parse_int (&(ieee->h));
141271671b9obrien    }
141371671b9obrien
141471671b9obrien  /*  abfd->has_armap = ;*/
141571671b9obrien
141671671b9obrien  return abfd->xvec;
141771671b9obrien
141871671b9obrien got_wrong_format_error:
141971671b9obrien  bfd_set_error (bfd_error_wrong_format);
142071671b9obrien error_return:
142171671b9obrien  if (elts != NULL)
142271671b9obrien    free (elts);
142371671b9obrien  bfd_release (abfd, ieee);
142471671b9obrien error_ret_restore:
142571671b9obrien  abfd->tdata.ieee_ar_data = save;
142671671b9obrien
142771671b9obrien  return NULL;
142871671b9obrien}
142971671b9obrien
14300acbbeedimstatic bfd_boolean
14310acbbeedimieee_mkobject (bfd *abfd)
143271671b9obrien{
143371671b9obrien  bfd_size_type amt;
143471671b9obrien
14350acbbeedim  output_ptr_start = NULL;
14360acbbeedim  output_ptr = NULL;
14370acbbeedim  output_ptr_end = NULL;
14380acbbeedim  input_ptr_start = NULL;
14390acbbeedim  input_ptr = NULL;
14400acbbeedim  input_ptr_end = NULL;
14410acbbeedim  input_bfd = NULL;
14420acbbeedim  output_bfd = NULL;
14430acbbeedim  output_buffer = 0;
14440acbbeedim  amt = sizeof (ieee_data_type);
14450acbbeedim  abfd->tdata.ieee_data = bfd_zalloc (abfd, amt);
14460acbbeedim  return abfd->tdata.ieee_data != NULL;
14470acbbeedim}
144871671b9obrien
14490acbbeedimstatic bfd_boolean
14500acbbeedimdo_one (ieee_data_type *ieee,
14510acbbeedim	ieee_per_section_type *current_map,
14520acbbeedim	unsigned char *location_ptr,
14530acbbeedim	asection *s,
14540acbbeedim	int iterations)
14550acbbeedim{
14560acbbeedim  switch (this_byte (&(ieee->h)))
14570acbbeedim    {
14580acbbeedim    case ieee_load_constant_bytes_enum:
145971671b9obrien      {
14600acbbeedim	unsigned int number_of_maus;
14610acbbeedim	unsigned int i;
146271671b9obrien
14630acbbeedim	next_byte (&(ieee->h));
14640acbbeedim	number_of_maus = must_parse_int (&(ieee->h));
146571671b9obrien
14660acbbeedim	for (i = 0; i < number_of_maus; i++)
146771671b9obrien	  {
14680acbbeedim	    location_ptr[current_map->pc++] = this_byte (&(ieee->h));
14690acbbeedim	    next_byte (&(ieee->h));
147071671b9obrien	  }
147171671b9obrien      }
14720acbbeedim      break;
14730acbbeedim
14740acbbeedim    case ieee_load_with_relocation_enum:
147571671b9obrien      {
14760acbbeedim	bfd_boolean loop = TRUE;
147771671b9obrien
14780acbbeedim	next_byte (&(ieee->h));
14790acbbeedim	while (loop)
14800acbbeedim	  {
14810acbbeedim	    switch (this_byte (&(ieee->h)))
14820acbbeedim	      {
14830acbbeedim	      case ieee_variable_R_enum:
148471671b9obrien
14850acbbeedim	      case ieee_function_signed_open_b_enum:
14860acbbeedim	      case ieee_function_unsigned_open_b_enum:
14870acbbeedim	      case ieee_function_either_open_b_enum:
14880acbbeedim		{
14890acbbeedim		  unsigned int extra = 4;
14900acbbeedim		  bfd_boolean pcrel = FALSE;
14910acbbeedim		  asection *section;
14920acbbeedim		  ieee_reloc_type *r;
149371671b9obrien
14940acbbeedim		  r = bfd_alloc (ieee->h.abfd, sizeof (* r));
14950acbbeedim		  if (!r)
14960acbbeedim		    return FALSE;
149771671b9obrien
14980acbbeedim		  *(current_map->reloc_tail_ptr) = r;
14990acbbeedim		  current_map->reloc_tail_ptr = &r->next;
15000acbbeedim		  r->next = (ieee_reloc_type *) NULL;
15010acbbeedim		  next_byte (&(ieee->h));
15020acbbeedim/*			    abort();*/
15030acbbeedim		  r->relent.sym_ptr_ptr = 0;
15040acbbeedim		  parse_expression (ieee,
15050acbbeedim				    &r->relent.addend,
15060acbbeedim				    &r->symbol,
15070acbbeedim				    &pcrel, &extra, &section);
15080acbbeedim		  r->relent.address = current_map->pc;
15090acbbeedim		  s->flags |= SEC_RELOC;
15100acbbeedim		  s->owner->flags |= HAS_RELOC;
15110acbbeedim		  s->reloc_count++;
15120acbbeedim		  if (r->relent.sym_ptr_ptr == NULL && section != NULL)
15130acbbeedim		    r->relent.sym_ptr_ptr = section->symbol_ptr_ptr;
151471671b9obrien
15150acbbeedim		  if (this_byte (&(ieee->h)) == (int) ieee_comma)
15160acbbeedim		    {
15170acbbeedim		      next_byte (&(ieee->h));
15180acbbeedim		      /* Fetch number of bytes to pad.  */
15190acbbeedim		      extra = must_parse_int (&(ieee->h));
15200acbbeedim		    };
152171671b9obrien
15220acbbeedim		  switch (this_byte (&(ieee->h)))
15230acbbeedim		    {
15240acbbeedim		    case ieee_function_signed_close_b_enum:
15250acbbeedim		      next_byte (&(ieee->h));
15260acbbeedim		      break;
15270acbbeedim		    case ieee_function_unsigned_close_b_enum:
15280acbbeedim		      next_byte (&(ieee->h));
15290acbbeedim		      break;
15300acbbeedim		    case ieee_function_either_close_b_enum:
15310acbbeedim		      next_byte (&(ieee->h));
15320acbbeedim		      break;
15330acbbeedim		    default:
15340acbbeedim		      break;
15350acbbeedim		    }
15360acbbeedim		  /* Build a relocation entry for this type.  */
15370acbbeedim		  /* If pc rel then stick -ve pc into instruction
15380acbbeedim		     and take out of reloc ..
153971671b9obrien
15400acbbeedim		     I've changed this. It's all too complicated. I
15410acbbeedim		     keep 0 in the instruction now.  */
154271671b9obrien
154371671b9obrien		  switch (extra)
154471671b9obrien		    {
154571671b9obrien		    case 0:
154671671b9obrien		    case 4:
154771671b9obrien
154871671b9obrien		      if (pcrel)
154971671b9obrien			{
155071671b9obrien#if KEEPMINUSPCININST
155171671b9obrien			  bfd_put_32 (ieee->h.abfd, -current_map->pc,
155271671b9obrien				      location_ptr + current_map->pc);
155371671b9obrien			  r->relent.howto = &rel32_howto;
155471671b9obrien			  r->relent.addend -= current_map->pc;
155571671b9obrien#else
155671671b9obrien			  bfd_put_32 (ieee->h.abfd, (bfd_vma) 0, location_ptr +
155771671b9obrien				      current_map->pc);
155871671b9obrien			  r->relent.howto = &rel32_howto;
155971671b9obrien#endif
156071671b9obrien			}
156171671b9obrien		      else
156271671b9obrien			{
156371671b9obrien			  bfd_put_32 (ieee->h.abfd, (bfd_vma) 0,
156471671b9obrien				      location_ptr + current_map->pc);
156571671b9obrien			  r->relent.howto = &abs32_howto;
156671671b9obrien			}
156771671b9obrien		      current_map->pc += 4;
156871671b9obrien		      break;
156971671b9obrien		    case 2:
157071671b9obrien		      if (pcrel)
157171671b9obrien			{
157271671b9obrien#if KEEPMINUSPCININST
157371671b9obrien			  bfd_put_16 (ieee->h.abfd, (bfd_vma) -current_map->pc,
157471671b9obrien				      location_ptr + current_map->pc);
157571671b9obrien			  r->relent.addend -= current_map->pc;
157671671b9obrien			  r->relent.howto = &rel16_howto;
157771671b9obrien#else
157871671b9obrien
157971671b9obrien			  bfd_put_16 (ieee->h.abfd, (bfd_vma) 0,
158071671b9obrien				      location_ptr + current_map->pc);
158171671b9obrien			  r->relent.howto = &rel16_howto;
158271671b9obrien#endif
158371671b9obrien			}
158471671b9obrien
158571671b9obrien		      else
158671671b9obrien			{
158771671b9obrien			  bfd_put_16 (ieee->h.abfd, (bfd_vma) 0,
158871671b9obrien				      location_ptr + current_map->pc);
158971671b9obrien			  r->relent.howto = &abs16_howto;
159071671b9obrien			}
159171671b9obrien		      current_map->pc += 2;
159271671b9obrien		      break;
159371671b9obrien		    case 1:
159471671b9obrien		      if (pcrel)
159571671b9obrien			{
159671671b9obrien#if KEEPMINUSPCININST
159771671b9obrien			  bfd_put_8 (ieee->h.abfd, (int) (-current_map->pc), location_ptr + current_map->pc);
159871671b9obrien			  r->relent.addend -= current_map->pc;
159971671b9obrien			  r->relent.howto = &rel8_howto;
160071671b9obrien#else
160171671b9obrien			  bfd_put_8 (ieee->h.abfd, 0, location_ptr + current_map->pc);
160271671b9obrien			  r->relent.howto = &rel8_howto;
160371671b9obrien#endif
160471671b9obrien			}
160571671b9obrien		      else
160671671b9obrien			{
160771671b9obrien			  bfd_put_8 (ieee->h.abfd, 0, location_ptr + current_map->pc);
160871671b9obrien			  r->relent.howto = &abs8_howto;
160971671b9obrien			}
161071671b9obrien		      current_map->pc += 1;
161171671b9obrien		      break;
161271671b9obrien
161371671b9obrien		    default:
161471671b9obrien		      BFD_FAIL ();
161571671b9obrien		      return FALSE;
161671671b9obrien		    }
161771671b9obrien		}
161871671b9obrien		break;
161971671b9obrien	      default:
162071671b9obrien		{
162171671b9obrien		  bfd_vma this_size;
16220acbbeedim
162371671b9obrien		  if (parse_int (&(ieee->h), &this_size))
162471671b9obrien		    {
162571671b9obrien		      unsigned int i;
16260acbbeedim
162771671b9obrien		      for (i = 0; i < this_size; i++)
162871671b9obrien			{
162971671b9obrien			  location_ptr[current_map->pc++] = this_byte (&(ieee->h));
163071671b9obrien			  next_byte (&(ieee->h));
163171671b9obrien			}
163271671b9obrien		    }
163371671b9obrien		  else
16340acbbeedim		    loop = FALSE;
163571671b9obrien		}
163671671b9obrien	      }
163771671b9obrien
163871671b9obrien	    /* Prevent more than the first load-item of an LR record
16390acbbeedim	       from being repeated (MRI convention).  */
164071671b9obrien	    if (iterations != 1)
164171671b9obrien	      loop = FALSE;
164271671b9obrien	  }
164371671b9obrien      }
164471671b9obrien    }
164571671b9obrien  return TRUE;
164671671b9obrien}
164771671b9obrien
164871671b9obrien/* Read in all the section data and relocation stuff too.  */
164971671b9obrien
165071671b9obrienstatic bfd_boolean
16510acbbeedimieee_slurp_section_data (bfd *abfd)
165271671b9obrien{
165371671b9obrien  bfd_byte *location_ptr = (bfd_byte *) NULL;
165471671b9obrien  ieee_data_type *ieee = IEEE_DATA (abfd);
165571671b9obrien  unsigned int section_number;
16560acbbeedim  ieee_per_section_type *current_map = NULL;
165771671b9obrien  asection *s;
16580acbbeedim
165971671b9obrien  /* Seek to the start of the data area.  */
166071671b9obrien  if (ieee->read_data)
166171671b9obrien    return TRUE;
166271671b9obrien  ieee->read_data = TRUE;
166371671b9obrien  ieee_seek (ieee, ieee->w.r.data_part);
166471671b9obrien
166571671b9obrien  /* Allocate enough space for all the section contents.  */
166671671b9obrien  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
166771671b9obrien    {
166871671b9obrien      ieee_per_section_type *per = ieee_per_section (s);
16690acbbeedim      arelent **relpp;
16700acbbeedim
167171671b9obrien      if ((s->flags & SEC_DEBUGGING) != 0)
167271671b9obrien	continue;
16730acbbeedim      per->data = bfd_alloc (ieee->h.abfd, s->size);
167471671b9obrien      if (!per->data)
167571671b9obrien	return FALSE;
16760acbbeedim      relpp = &s->relocation;
16770acbbeedim      per->reloc_tail_ptr = (ieee_reloc_type **) relpp;
167871671b9obrien    }
167971671b9obrien
168071671b9obrien  while (TRUE)
168171671b9obrien    {
168271671b9obrien      switch (this_byte (&(ieee->h)))
168371671b9obrien	{
168471671b9obrien	  /* IF we see anything strange then quit.  */
168571671b9obrien	default:
168671671b9obrien	  return TRUE;
168771671b9obrien
168871671b9obrien	case ieee_set_current_section_enum:
168971671b9obrien	  next_byte (&(ieee->h));
169071671b9obrien	  section_number = must_parse_int (&(ieee->h));
169171671b9obrien	  s = ieee->section_table[section_number];
169271671b9obrien	  s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
169371671b9obrien	  current_map = ieee_per_section (s);
169471671b9obrien	  location_ptr = current_map->data - s->vma;
169571671b9obrien	  /* The document I have says that Microtec's compilers reset
169671671b9obrien	     this after a sec section, even though the standard says not
169771671b9obrien	     to, SO...  */
169871671b9obrien	  current_map->pc = s->vma;
169971671b9obrien	  break;
170071671b9obrien
17010acbbeedim	case ieee_e2_first_byte_enum:
17020acbbeedim	  next_byte (&(ieee->h));
17030acbbeedim	  switch (this_byte (&(ieee->h)))
17040acbbeedim	    {
17050acbbeedim	    case ieee_set_current_pc_enum & 0xff:
17060acbbeedim	      {
17070acbbeedim		bfd_vma value;
17080acbbeedim		ieee_symbol_index_type symbol;
17090acbbeedim		unsigned int extra;
17100acbbeedim		bfd_boolean pcrel;
17110acbbeedim
17120acbbeedim		next_byte (&(ieee->h));
17130acbbeedim		must_parse_int (&(ieee->h));	/* Throw away section #.  */
17140acbbeedim		parse_expression (ieee, &value,
17150acbbeedim				  &symbol,
17160acbbeedim				  &pcrel, &extra,
17170acbbeedim				  0);
17180acbbeedim		current_map->pc = value;
17190acbbeedim		BFD_ASSERT ((unsigned) (value - s->vma) <= s->size);
17200acbbeedim	      }
17210acbbeedim	      break;
17220acbbeedim
17230acbbeedim	    case ieee_value_starting_address_enum & 0xff:
17240acbbeedim	      next_byte (&(ieee->h));
17250acbbeedim	      if (this_byte (&(ieee->h)) == ieee_function_either_open_b_enum)
17260acbbeedim		next_byte (&(ieee->h));
17270acbbeedim	      abfd->start_address = must_parse_int (&(ieee->h));
17280acbbeedim	      /* We've got to the end of the data now -  */
17290acbbeedim	      return TRUE;
17300acbbeedim	    default:
17310acbbeedim	      BFD_FAIL ();
17320acbbeedim	      return FALSE;
17330acbbeedim	    }
17340acbbeedim	  break;
17350acbbeedim	case ieee_repeat_data_enum:
17360acbbeedim	  {
17370acbbeedim	    /* Repeat the following LD or LR n times - we do this by
17380acbbeedim	       remembering the stream pointer before running it and
17390acbbeedim	       resetting it and running it n times. We special case
17400acbbeedim	       the repetition of a repeat_data/load_constant.  */
17410acbbeedim	    unsigned int iterations;
17420acbbeedim	    unsigned char *start;
17430acbbeedim
17440acbbeedim	    next_byte (&(ieee->h));
17450acbbeedim	    iterations = must_parse_int (&(ieee->h));
17460acbbeedim	    start = ieee->h.input_p;
17470acbbeedim	    if (start[0] == (int) ieee_load_constant_bytes_enum
17480acbbeedim		&& start[1] == 1)
17490acbbeedim	      {
17500acbbeedim		while (iterations != 0)
17510acbbeedim		  {
17520acbbeedim		    location_ptr[current_map->pc++] = start[2];
17530acbbeedim		    iterations--;
17540acbbeedim		  }
17550acbbeedim		next_byte (&(ieee->h));
17560acbbeedim		next_byte (&(ieee->h));
17570acbbeedim		next_byte (&(ieee->h));
17580acbbeedim	      }
17590acbbeedim	    else
17600acbbeedim	      {
17610acbbeedim		while (iterations != 0)
17620acbbeedim		  {
17630acbbeedim		    ieee->h.input_p = start;
17640acbbeedim		    if (!do_one (ieee, current_map, location_ptr, s,
17650acbbeedim				 (int) iterations))
17660acbbeedim		      return FALSE;
17670acbbeedim		    iterations--;
17680acbbeedim		  }
17690acbbeedim	      }
17700acbbeedim	  }
17710acbbeedim	  break;
17720acbbeedim	case ieee_load_constant_bytes_enum:
17730acbbeedim	case ieee_load_with_relocation_enum:
17740acbbeedim	  if (!do_one (ieee, current_map, location_ptr, s, 1))
17750acbbeedim	    return FALSE;
17760acbbeedim	}
17770acbbeedim    }
17780acbbeedim}
17790acbbeedim
17800acbbeedimstatic const bfd_target *
17810acbbeedimieee_object_p (bfd *abfd)
17820acbbeedim{
17830acbbeedim  char *processor;
17840acbbeedim  unsigned int part;
17850acbbeedim  ieee_data_type *ieee;
17860acbbeedim  unsigned char buffer[300];
17870acbbeedim  ieee_data_type *save = IEEE_DATA (abfd);
17880acbbeedim  bfd_size_type amt;
17890acbbeedim
17900acbbeedim  abfd->tdata.ieee_data = 0;
17910acbbeedim  ieee_mkobject (abfd);
17920acbbeedim
17930acbbeedim  ieee = IEEE_DATA (abfd);
17940acbbeedim  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
17950acbbeedim    goto fail;
17960acbbeedim  /* Read the first few bytes in to see if it makes sense.  Ignore
17970acbbeedim     bfd_bread return value;  The file might be very small.  */
17980acbbeedim  bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
17990acbbeedim
18000acbbeedim  ieee->h.input_p = buffer;
18010acbbeedim  if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
18020acbbeedim    goto got_wrong_format;
18030acbbeedim
18040acbbeedim  ieee->read_symbols = FALSE;
18050acbbeedim  ieee->read_data = FALSE;
18060acbbeedim  ieee->section_count = 0;
18070acbbeedim  ieee->external_symbol_max_index = 0;
18080acbbeedim  ieee->external_symbol_min_index = IEEE_PUBLIC_BASE;
18090acbbeedim  ieee->external_reference_min_index = IEEE_REFERENCE_BASE;
18100acbbeedim  ieee->external_reference_max_index = 0;
18110acbbeedim  ieee->h.abfd = abfd;
18120acbbeedim  ieee->section_table = NULL;
18130acbbeedim  ieee->section_table_size = 0;
18140acbbeedim
18150acbbeedim  processor = ieee->mb.processor = read_id (&(ieee->h));
18160acbbeedim  if (strcmp (processor, "LIBRARY") == 0)
18170acbbeedim    goto got_wrong_format;
18180acbbeedim  ieee->mb.module_name = read_id (&(ieee->h));
18190acbbeedim  if (abfd->filename == (const char *) NULL)
18200acbbeedim    abfd->filename = ieee->mb.module_name;
18210acbbeedim
18220acbbeedim  /* Determine the architecture and machine type of the object file.  */
18230acbbeedim  {
18240acbbeedim    const bfd_arch_info_type *arch;
18250acbbeedim    char family[10];
18260acbbeedim
18270acbbeedim    /* IEEE does not specify the format of the processor identification
18280acbbeedim       string, so the compiler is free to put in it whatever it wants.
18290acbbeedim       We try here to recognize different processors belonging to the
18300acbbeedim       m68k family.  Code for other processors can be added here.  */
18310acbbeedim    if ((processor[0] == '6') && (processor[1] == '8'))
18320acbbeedim      {
18330acbbeedim	if (processor[2] == '3')	    /* 683xx integrated processors.  */
18340acbbeedim	  {
18350acbbeedim	    switch (processor[3])
18360acbbeedim	      {
18370acbbeedim	      case '0':			    /* 68302, 68306, 68307 */
18380acbbeedim	      case '2':			    /* 68322, 68328 */
18390acbbeedim	      case '5':			    /* 68356 */
18400acbbeedim		strcpy (family, "68000");   /* MC68000-based controllers.  */
18410acbbeedim		break;
18420acbbeedim
18430acbbeedim	      case '3':			    /* 68330, 68331, 68332, 68333,
18440acbbeedim					       68334, 68335, 68336, 68338 */
18450acbbeedim	      case '6':			    /* 68360 */
18460acbbeedim	      case '7':			    /* 68376 */
18470acbbeedim		strcpy (family, "68332");   /* CPU32 and CPU32+ */
18480acbbeedim		break;
18490acbbeedim
18500acbbeedim	      case '4':
18510acbbeedim		if (processor[4] == '9')    /* 68349 */
18520acbbeedim		  strcpy (family, "68030"); /* CPU030 */
18530acbbeedim		else		            /* 68340, 68341 */
18540acbbeedim		  strcpy (family, "68332"); /* CPU32 and CPU32+ */
18550acbbeedim		break;
18560acbbeedim
18570acbbeedim	      default:			    /* Does not exist yet.  */
18580acbbeedim		strcpy (family, "68332");   /* Guess it will be CPU32 */
18590acbbeedim	      }
18600acbbeedim	  }
18610acbbeedim	else if (TOUPPER (processor[3]) == 'F')  /* 68F333 */
18620acbbeedim	  strcpy (family, "68332");	           /* CPU32 */
18630acbbeedim	else if ((TOUPPER (processor[3]) == 'C') /* Embedded controllers.  */
18640acbbeedim		 && ((TOUPPER (processor[2]) == 'E')
18650acbbeedim		     || (TOUPPER (processor[2]) == 'H')
18660acbbeedim		     || (TOUPPER (processor[2]) == 'L')))
18670acbbeedim	  {
18680acbbeedim	    strcpy (family, "68");
18690acbbeedim	    strncat (family, processor + 4, 7);
18700acbbeedim	    family[9] = '\0';
18710acbbeedim	  }
18720acbbeedim	else				 /* "Regular" processors.  */
18730acbbeedim	  {
18740acbbeedim	    strncpy (family, processor, 9);
18750acbbeedim	    family[9] = '\0';
18760acbbeedim	  }
18770acbbeedim      }
1878d0f678fdim    else if ((CONST_STRNEQ (processor, "cpu32")) /* CPU32 and CPU32+  */
1879d0f678fdim	     || (CONST_STRNEQ (processor, "CPU32")))
18800acbbeedim      strcpy (family, "68332");
18810acbbeedim    else
18820acbbeedim      {
18830acbbeedim	strncpy (family, processor, 9);
18840acbbeedim	family[9] = '\0';
18850acbbeedim      }
18860acbbeedim
18870acbbeedim    arch = bfd_scan_arch (family);
18880acbbeedim    if (arch == 0)
18890acbbeedim      goto got_wrong_format;
18900acbbeedim    abfd->arch_info = arch;
18910acbbeedim  }
18920acbbeedim
18930acbbeedim  if (this_byte (&(ieee->h)) != (int) ieee_address_descriptor_enum)
18940acbbeedim    goto fail;
18950acbbeedim
18960acbbeedim  next_byte (&(ieee->h));
18970acbbeedim
18980acbbeedim  if (! parse_int (&(ieee->h), &ieee->ad.number_of_bits_mau))
18990acbbeedim    goto fail;
19000acbbeedim
19010acbbeedim  if (! parse_int (&(ieee->h), &ieee->ad.number_of_maus_in_address))
19020acbbeedim    goto fail;
19030acbbeedim
19040acbbeedim  /* If there is a byte order info, take it.  */
19050acbbeedim  if (this_byte (&(ieee->h)) == (int) ieee_variable_L_enum
19060acbbeedim      || this_byte (&(ieee->h)) == (int) ieee_variable_M_enum)
19070acbbeedim    next_byte (&(ieee->h));
19080acbbeedim
19090acbbeedim  for (part = 0; part < N_W_VARIABLES; part++)
19100acbbeedim    {
19110acbbeedim      bfd_boolean ok;
19120acbbeedim
19130acbbeedim      if (read_2bytes (&(ieee->h)) != (int) ieee_assign_value_to_variable_enum)
19140acbbeedim	goto fail;
19150acbbeedim
19160acbbeedim      if (this_byte_and_next (&(ieee->h)) != part)
19170acbbeedim	goto fail;
19180acbbeedim
19190acbbeedim      ieee->w.offset[part] = parse_i (&(ieee->h), &ok);
19200acbbeedim      if (! ok)
19210acbbeedim	goto fail;
19220acbbeedim    }
19230acbbeedim
19240acbbeedim  if (ieee->w.r.external_part != 0)
19250acbbeedim    abfd->flags = HAS_SYMS;
19260acbbeedim
19270acbbeedim  /* By now we know that this is a real IEEE file, we're going to read
19280acbbeedim     the whole thing into memory so that we can run up and down it
19290acbbeedim     quickly.  We can work out how big the file is from the trailer
19300acbbeedim     record.  */
19310acbbeedim
19320acbbeedim  amt = ieee->w.r.me_record + 1;
19330acbbeedim  IEEE_DATA (abfd)->h.first_byte = bfd_alloc (ieee->h.abfd, amt);
19340acbbeedim  if (!IEEE_DATA (abfd)->h.first_byte)
19350acbbeedim    goto fail;
19360acbbeedim  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
19370acbbeedim    goto fail;
19380acbbeedim  /* FIXME: Check return value.  I'm not sure whether it needs to read
19390acbbeedim     the entire buffer or not.  */
19400acbbeedim  bfd_bread ((void *) (IEEE_DATA (abfd)->h.first_byte),
19410acbbeedim	    (bfd_size_type) ieee->w.r.me_record + 1, abfd);
19420acbbeedim
19430acbbeedim  ieee_slurp_sections (abfd);
19440acbbeedim
19450acbbeedim  if (! ieee_slurp_debug (abfd))
19460acbbeedim    goto fail;
19470acbbeedim
19480acbbeedim  /* Parse section data to activate file and section flags implied by
19490acbbeedim     section contents.  */
19500acbbeedim  if (! ieee_slurp_section_data (abfd))
19510acbbeedim    goto fail;
19520acbbeedim
19530acbbeedim  return abfd->xvec;
19540acbbeedimgot_wrong_format:
19550acbbeedim  bfd_set_error (bfd_error_wrong_format);
19560acbbeedimfail:
19570acbbeedim  bfd_release (abfd, ieee);
19580acbbeedim  abfd->tdata.ieee_data = save;
19590acbbeedim  return (const bfd_target *) NULL;
19600acbbeedim}
19610acbbeedim
19620acbbeedimstatic void
19630acbbeedimieee_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
19640acbbeedim		      asymbol *symbol,
19650acbbeedim		      symbol_info *ret)
19660acbbeedim{
19670acbbeedim  bfd_symbol_info (symbol, ret);
19680acbbeedim  if (symbol->name[0] == ' ')
19690acbbeedim    ret->name = "* empty table entry ";
19700acbbeedim  if (!symbol->section)
19710acbbeedim    ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
19720acbbeedim}
197371671b9obrien
19740acbbeedimstatic void
19750acbbeedimieee_print_symbol (bfd *abfd,
19760acbbeedim		   void * afile,
19770acbbeedim		   asymbol *symbol,
19780acbbeedim		   bfd_print_symbol_type how)
19790acbbeedim{
19800acbbeedim  FILE *file = (FILE *) afile;
198171671b9obrien
19820acbbeedim  switch (how)
19830acbbeedim    {
19840acbbeedim    case bfd_print_symbol_name:
19850acbbeedim      fprintf (file, "%s", symbol->name);
19860acbbeedim      break;
19870acbbeedim    case bfd_print_symbol_more:
19880acbbeedim      BFD_FAIL ();
19890acbbeedim      break;
19900acbbeedim    case bfd_print_symbol_all:
19910acbbeedim      {
19920acbbeedim	const char *section_name =
19930acbbeedim	  (symbol->section == (asection *) NULL
19940acbbeedim	   ? "*abs"
19950acbbeedim	   : symbol->section->name);
19960acbbeedim
19970acbbeedim	if (symbol->name[0] == ' ')
19980acbbeedim	  fprintf (file, "* empty table entry ");
19990acbbeedim	else
200071671b9obrien	  {
20010acbbeedim	    bfd_print_symbol_vandf (abfd, (void *) file, symbol);
200271671b9obrien
20030acbbeedim	    fprintf (file, " %-5s %04x %02x %s",
20040acbbeedim		     section_name,
20050acbbeedim		     (unsigned) ieee_symbol (symbol)->index,
20060acbbeedim		     (unsigned) 0,
20070acbbeedim		     symbol->name);
200871671b9obrien	  }
20090acbbeedim      }
20100acbbeedim      break;
201171671b9obrien    }
201271671b9obrien}
201371671b9obrien
201471671b9obrienstatic bfd_boolean
20150acbbeedimieee_new_section_hook (bfd *abfd, asection *newsect)
201671671b9obrien{
201771671b9obrien  if (!newsect->used_by_bfd)
2018d0f678fdim    {
2019d0f678fdim      newsect->used_by_bfd = bfd_alloc (abfd, sizeof (ieee_per_section_type));
2020d0f678fdim      if (!newsect->used_by_bfd)
2021d0f678fdim	return FALSE;
2022d0f678fdim    }
20230acbbeedim  ieee_per_section (newsect)->data = NULL;
202471671b9obrien  ieee_per_section (newsect)->section = newsect;
2025d0f678fdim  return _bfd_generic_new_section_hook (abfd, newsect);
202671671b9obrien}
202771671b9obrien
202871671b9obrienstatic long
20290acbbeedimieee_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
203071671b9obrien{
203171671b9obrien  if ((asect->flags & SEC_DEBUGGING) != 0)
203271671b9obrien    return 0;
203371671b9obrien  if (! ieee_slurp_section_data (abfd))
203471671b9obrien    return -1;
203571671b9obrien  return (asect->reloc_count + 1) * sizeof (arelent *);
203671671b9obrien}
203771671b9obrien
203871671b9obrienstatic bfd_boolean
20390acbbeedimieee_get_section_contents (bfd *abfd,
20400acbbeedim			   sec_ptr section,
20410acbbeedim			   void * location,
20420acbbeedim			   file_ptr offset,
20430acbbeedim			   bfd_size_type count)
204471671b9obrien{
204571671b9obrien  ieee_per_section_type *p = ieee_per_section (section);
204671671b9obrien  if ((section->flags & SEC_DEBUGGING) != 0)
204771671b9obrien    return _bfd_generic_get_section_contents (abfd, section, location,
204871671b9obrien					      offset, count);
204971671b9obrien  ieee_slurp_section_data (abfd);
20500acbbeedim  (void) memcpy ((void *) location, (void *) (p->data + offset), (unsigned) count);
205171671b9obrien  return TRUE;
205271671b9obrien}
205371671b9obrien
205471671b9obrienstatic long
20550acbbeedimieee_canonicalize_reloc (bfd *abfd,
20560acbbeedim			 sec_ptr section,
20570acbbeedim			 arelent **relptr,
20580acbbeedim			 asymbol **symbols)
205971671b9obrien{
206071671b9obrien  ieee_reloc_type *src = (ieee_reloc_type *) (section->relocation);
206171671b9obrien  ieee_data_type *ieee = IEEE_DATA (abfd);
206271671b9obrien
206371671b9obrien  if ((section->flags & SEC_DEBUGGING) != 0)
206471671b9obrien    return 0;
206571671b9obrien
206671671b9obrien  while (src != (ieee_reloc_type *) NULL)
206771671b9obrien    {
206871671b9obrien      /* Work out which symbol to attach it this reloc to.  */
206971671b9obrien      switch (src->symbol.letter)
207071671b9obrien	{
207171671b9obrien	case 'I':
207271671b9obrien	  src->relent.sym_ptr_ptr =
207371671b9obrien	    symbols + src->symbol.index + ieee->external_symbol_base_offset;
207471671b9obrien	  break;
207571671b9obrien	case 'X':
207671671b9obrien	  src->relent.sym_ptr_ptr =
207771671b9obrien	    symbols + src->symbol.index + ieee->external_reference_base_offset;
207871671b9obrien	  break;
207971671b9obrien	case 0:
208071671b9obrien	  if (src->relent.sym_ptr_ptr != NULL)
208171671b9obrien	    src->relent.sym_ptr_ptr =
208271671b9obrien	      src->relent.sym_ptr_ptr[0]->section->symbol_ptr_ptr;
208371671b9obrien	  break;
208471671b9obrien	default:
208571671b9obrien
208671671b9obrien	  BFD_FAIL ();
208771671b9obrien	}
208871671b9obrien      *relptr++ = &src->relent;
208971671b9obrien      src = src->next;
209071671b9obrien    }
20910acbbeedim  *relptr = NULL;
209271671b9obrien  return section->reloc_count;
209371671b9obrien}
209471671b9obrien
209571671b9obrienstatic int
20960acbbeedimcomp (const void * ap, const void * bp)
209771671b9obrien{
209871671b9obrien  arelent *a = *((arelent **) ap);
209971671b9obrien  arelent *b = *((arelent **) bp);
210071671b9obrien  return a->address - b->address;
210171671b9obrien}
210271671b9obrien
210371671b9obrien/* Write the section headers.  */
210471671b9obrien
210571671b9obrienstatic bfd_boolean
21060acbbeedimieee_write_section_part (bfd *abfd)
210771671b9obrien{
210871671b9obrien  ieee_data_type *ieee = IEEE_DATA (abfd);
210971671b9obrien  asection *s;
21100acbbeedim
211171671b9obrien  ieee->w.r.section_part = bfd_tell (abfd);
211271671b9obrien  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
211371671b9obrien    {
211471671b9obrien      if (! bfd_is_abs_section (s)
211571671b9obrien	  && (s->flags & SEC_DEBUGGING) == 0)
211671671b9obrien	{
211771671b9obrien	  if (! ieee_write_byte (abfd, ieee_section_type_enum)
211871671b9obrien	      || ! ieee_write_byte (abfd,
211971671b9obrien				    (bfd_byte) (s->index
212071671b9obrien						+ IEEE_SECTION_NUMBER_BASE)))
212171671b9obrien	    return FALSE;
212271671b9obrien
212371671b9obrien	  if (abfd->flags & EXEC_P)
212471671b9obrien	    {
212571671b9obrien	      /* This image is executable, so output absolute sections.  */
212671671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_A_enum)
212771671b9obrien		  || ! ieee_write_byte (abfd, ieee_variable_S_enum))
212871671b9obrien		return FALSE;
212971671b9obrien	    }
213071671b9obrien	  else
213171671b9obrien	    {
213271671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_C_enum))
213371671b9obrien		return FALSE;
213471671b9obrien	    }
213571671b9obrien
213671671b9obrien	  switch (s->flags & (SEC_CODE | SEC_DATA | SEC_ROM))
213771671b9obrien	    {
213871671b9obrien	    case SEC_CODE | SEC_LOAD:
213971671b9obrien	    case SEC_CODE:
214071671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_P_enum))
214171671b9obrien		return FALSE;
214271671b9obrien	      break;
214371671b9obrien	    case SEC_DATA:
214471671b9obrien	    default:
214571671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_D_enum))
214671671b9obrien		return FALSE;
214771671b9obrien	      break;
214871671b9obrien	    case SEC_ROM:
214971671b9obrien	    case SEC_ROM | SEC_DATA:
215071671b9obrien	    case SEC_ROM | SEC_LOAD:
215171671b9obrien	    case SEC_ROM | SEC_DATA | SEC_LOAD:
215271671b9obrien	      if (! ieee_write_byte (abfd, ieee_variable_R_enum))
215371671b9obrien		return FALSE;
215471671b9obrien	    }
215571671b9obrien
215671671b9obrien
215771671b9obrien	  if (! ieee_write_id (abfd, s->name))
215871671b9obrien	    return FALSE;
215971671b9obrien	  /* Alignment.  */
216071671b9obrien	  if (! ieee_write_byte (abfd, ieee_section_alignment_enum)
216171671b9obrien	      || ! ieee_write_byte (abfd,
216271671b9obrien				    (bfd_byte) (s->index
216371671b9obrien						+ IEEE_SECTION_NUMBER_BASE))
216471671b9obrien	      || ! ieee_write_int (abfd, (bfd_vma) 1 << s->alignment_power))
216571671b9obrien	    return FALSE;
216671671b9obrien
216771671b9obrien	  /* Size.  */
216871671b9obrien	  if (! ieee_write_2bytes (abfd, ieee_section_size_enum)
216971671b9obrien	      || ! ieee_write_byte (abfd,
217071671b9obrien				    (bfd_byte) (s->index
217171671b9obrien						+ IEEE_SECTION_NUMBER_BASE))
21720acbbeedim	      || ! ieee_write_int (abfd, s->size))
217371671b9obrien	    return FALSE;
217471671b9obrien	  if (abfd->flags & EXEC_P)
217571671b9obrien	    {
217671671b9obrien	      /* Relocateable sections don't have asl records.  */
217771671b9obrien	      /* Vma.  */
217871671b9obrien	      if (! ieee_write_2bytes (abfd, ieee_section_base_address_enum)
217971671b9obrien		  || ! ieee_write_byte (abfd,
218071671b9obrien					((bfd_byte)
218171671b9obrien					 (s->index
218271671b9obrien					  + IEEE_SECTION_NUMBER_BASE)))
218371671b9obrien		  || ! ieee_write_int (abfd, s->lma))
218471671b9obrien		return FALSE;
218571671b9obrien	    }
218671671b9obrien	}
218771671b9obrien    }
218871671b9obrien
218971671b9obrien  return TRUE;
219071671b9obrien}
219171671b9obrien
219271671b9obrienstatic bfd_boolean
21930acbbeedimdo_with_relocs (bfd *abfd, asection *s)
219471671b9obrien{
219571671b9obrien  unsigned int number_of_maus_in_address =
219671671b9obrien    bfd_arch_bits_per_address (abfd) / bfd_arch_bits_per_byte (abfd);
219771671b9obrien  unsigned int relocs_to_go = s->reloc_count;
219871671b9obrien  bfd_byte *stream = ieee_per_section (s)->data;
219971671b9obrien  arelent **p = s->orelocation;
220071671b9obrien  bfd_size_type current_byte_index = 0;
220171671b9obrien
220271671b9obrien  qsort (s->orelocation,
220371671b9obrien	 relocs_to_go,
220471671b9obrien	 sizeof (arelent **),
220571671b9obrien	 comp);
220671671b9obrien
220771671b9obrien  /* Output the section preheader.  */
220871671b9obrien  if (! ieee_write_byte (abfd, ieee_set_current_section_enum)
220971671b9obrien      || ! ieee_write_byte (abfd,
221071671b9obrien			    (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE))
221171671b9obrien      || ! ieee_write_2bytes (abfd, ieee_set_current_pc_enum)
221271671b9obrien      || ! ieee_write_byte (abfd,
221371671b9obrien			    (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE)))
221471671b9obrien    return FALSE;
221571671b9obrien
221671671b9obrien  if ((abfd->flags & EXEC_P) != 0 && relocs_to_go == 0)
221771671b9obrien    {
221871671b9obrien      if (! ieee_write_int (abfd, s->lma))
221971671b9obrien	return FALSE;
222071671b9obrien    }
222171671b9obrien  else
222271671b9obrien    {
222371671b9obrien      if (! ieee_write_expression (abfd, (bfd_vma) 0, s->symbol, 0, 0))
222471671b9obrien	return FALSE;
222571671b9obrien    }
222671671b9obrien
222771671b9obrien  if (relocs_to_go == 0)
222871671b9obrien    {
222971671b9obrien      /* If there aren't any relocations then output the load constant
223071671b9obrien	 byte opcode rather than the load with relocation opcode.  */
22310acbbeedim      while (current_byte_index < s->size)
223271671b9obrien	{
223371671b9obrien	  bfd_size_type run;
223471671b9obrien	  unsigned int MAXRUN = 127;
223571671b9obrien
223671671b9obrien	  run = MAXRUN;
22370acbbeedim	  if (run > s->size - current_byte_index)
22380acbbeedim	    run = s->size - current_byte_index;
223971671b9obrien
224071671b9obrien	  if (run != 0)
224171671b9obrien	    {
224271671b9obrien	      if (! ieee_write_byte (abfd, ieee_load_constant_bytes_enum))
224371671b9obrien		return FALSE;
224471671b9obrien	      /* Output a stream of bytes.  */
224571671b9obrien	      if (! ieee_write_int (abfd, run))
224671671b9obrien		return FALSE;
22470acbbeedim	      if (bfd_bwrite ((void *) (stream + current_byte_index), run, abfd)
224871671b9obrien		  != run)
224971671b9obrien		return FALSE;
225071671b9obrien	      current_byte_index += run;
225171671b9obrien	    }
225271671b9obrien	}
225371671b9obrien    }
225471671b9obrien  else
225571671b9obrien    {
225671671b9obrien      if (! ieee_write_byte (abfd, ieee_load_with_relocation_enum))
225771671b9obrien	return FALSE;
225871671b9obrien
225971671b9obrien      /* Output the data stream as the longest sequence of bytes
226071671b9obrien	 possible, allowing for the a reasonable packet size and
226171671b9obrien	 relocation stuffs.  */
22620acbbeedim      if (stream == NULL)
226371671b9obrien	{
226471671b9obrien	  /* Outputting a section without data, fill it up.  */
22650acbbeedim	  stream = bfd_zalloc (abfd, s->size);
226671671b9obrien	  if (!stream)
226771671b9obrien	    return FALSE;
226871671b9obrien	}
22690acbbeedim      while (current_byte_index < s->size)
227071671b9obrien	{
227171671b9obrien	  bfd_size_type run;
227271671b9obrien	  unsigned int MAXRUN = 127;
227371671b9obrien
227471671b9obrien	  if (relocs_to_go)
227571671b9obrien	    {
227671671b9obrien	      run = (*p)->address - current_byte_index;
227771671b9obrien	      if (run > MAXRUN)
227871671b9obrien		run = MAXRUN;
227971671b9obrien	    }
228071671b9obrien	  else
228171671b9obrien	    run = MAXRUN;
228271671b9obrien
22830acbbeedim	  if (run > s->size - current_byte_index)
22840acbbeedim	    run = s->size - current_byte_index;
228571671b9obrien
228671671b9obrien	  if (run != 0)
228771671b9obrien	    {
228871671b9obrien	      /* Output a stream of bytes.  */
228971671b9obrien	      if (! ieee_write_int (abfd, run))
229071671b9obrien		return FALSE;
22910acbbeedim	      if (bfd_bwrite ((void *) (stream + current_byte_index), run, abfd)
229271671b9obrien		  != run)
229371671b9obrien		return FALSE;
229471671b9obrien	      current_byte_index += run;
229571671b9obrien	    }
229671671b9obrien
229771671b9obrien	  /* Output any relocations here.  */
229871671b9obrien	  if (relocs_to_go && (*p) && (*p)->address == current_byte_index)
229971671b9obrien	    {
230071671b9obrien	      while (relocs_to_go
230171671b9obrien		     && (*p) && (*p)->address == current_byte_index)
230271671b9obrien		{
230371671b9obrien		  arelent *r = *p;
230471671b9obrien		  bfd_signed_vma ov;
230571671b9obrien		  switch (r->howto->size)
230671671b9obrien		    {
230771671b9obrien		    case 2:
230871671b9obrien		      ov = bfd_get_signed_32 (abfd,
230971671b9obrien					      stream + current_byte_index);
231071671b9obrien		      current_byte_index += 4;
231171671b9obrien		      break;
231271671b9obrien		    case 1:
231371671b9obrien		      ov = bfd_get_signed_16 (abfd,
231471671b9obrien					      stream + current_byte_index);
231571671b9obrien		      current_byte_index += 2;
231671671b9obrien		      break;
231771671b9obrien		    case 0:
231871671b9obrien		      ov = bfd_get_signed_8 (abfd,
231971671b9obrien					     stream + current_byte_index);
232071671b9obrien		      current_byte_index++;
232171671b9obrien		      break;
232271671b9obrien		    default:
232371671b9obrien		      ov = 0;
232471671b9obrien		      BFD_FAIL ();
232571671b9obrien		      return FALSE;
232671671b9obrien		    }
232771671b9obrien
232871671b9obrien		  ov &= r->howto->src_mask;
232971671b9obrien
233071671b9obrien		  if (r->howto->pc_relative
233171671b9obrien		      && ! r->howto->pcrel_offset)
233271671b9obrien		    ov += r->address;
233371671b9obrien
233471671b9obrien		  if (! ieee_write_byte (abfd,
233571671b9obrien					 ieee_function_either_open_b_enum))
233671671b9obrien		    return FALSE;
233771671b9obrien
233871671b9obrien		  if (r->sym_ptr_ptr != (asymbol **) NULL)
233971671b9obrien		    {
234071671b9obrien		      if (! ieee_write_expression (abfd, r->addend + ov,
234171671b9obrien						   *(r->sym_ptr_ptr),
234271671b9obrien						   r->howto->pc_relative,
234371671b9obrien						   (unsigned) s->index))
234471671b9obrien			return FALSE;
234571671b9obrien		    }
234671671b9obrien		  else
234771671b9obrien		    {
234871671b9obrien		      if (! ieee_write_expression (abfd, r->addend + ov,
234971671b9obrien						   (asymbol *) NULL,
235071671b9obrien						   r->howto->pc_relative,
235171671b9obrien						   (unsigned) s->index))
235271671b9obrien			return FALSE;
235371671b9obrien		    }
235471671b9obrien
235571671b9obrien		  if (number_of_maus_in_address
235671671b9obrien		      != bfd_get_reloc_size (r->howto))
235771671b9obrien		    {
235871671b9obrien		      bfd_vma rsize = bfd_get_reloc_size (r->howto);
235971671b9obrien		      if (! ieee_write_int (abfd, rsize))
236071671b9obrien			return FALSE;
236171671b9obrien		    }
236271671b9obrien		  if (! ieee_write_byte (abfd,
236371671b9obrien					 ieee_function_either_close_b_enum))
236471671b9obrien		    return FALSE;
236571671b9obrien
236671671b9obrien		  relocs_to_go--;
236771671b9obrien		  p++;
236871671b9obrien		}
236971671b9obrien
237071671b9obrien	    }
237171671b9obrien	}
237271671b9obrien    }
237371671b9obrien
237471671b9obrien  return TRUE;
237571671b9obrien}
237671671b9obrien
237771671b9obrien/* If there are no relocations in the output section then we can be
237871671b9obrien   clever about how we write.  We block items up into a max of 127
237971671b9obrien   bytes.  */
238071671b9obrien
238171671b9obrienstatic bfd_boolean
23820acbbeedimdo_as_repeat (bfd *abfd, asection *s)
238371671b9obrien{
23840acbbeedim  if (s->size)
238571671b9obrien    {
238671671b9obrien      if (! ieee_write_byte (abfd, ieee_set_current_section_enum)
238771671b9obrien	  || ! ieee_write_byte (abfd,
238871671b9obrien				(bfd_byte) (s->index
238971671b9obrien					    + IEEE_SECTION_NUMBER_BASE))
239071671b9obrien	  || ! ieee_write_byte (abfd, ieee_set_current_pc_enum >> 8)
239171671b9obrien	  || ! ieee_write_byte (abfd, ieee_set_current_pc_enum & 0xff)
239271671b9obrien	  || ! ieee_write_byte (abfd,
239371671b9obrien				(bfd_byte) (s->index
239471671b9obrien					    + IEEE_SECTION_NUMBER_BASE)))
239571671b9obrien	return FALSE;
239671671b9obrien
239771671b9obrien      if ((abfd->flags & EXEC_P) != 0)
239871671b9obrien	{
239971671b9obrien	  if (! ieee_write_int (abfd, s->lma))
240071671b9obrien	    return FALSE;
240171671b9obrien	}
240271671b9obrien      else
240371671b9obrien	{
240471671b9obrien	  if (! ieee_write_expression (abfd, (bfd_vma) 0, s->symbol, 0, 0))
240571671b9obrien	    return FALSE;
240671671b9obrien	}
240771671b9obrien
240871671b9obrien      if (! ieee_write_byte (abfd, ieee_repeat_data_enum)
24090acbbeedim	  || ! ieee_write_int (abfd, s->size)
241071671b9obrien	  || ! ieee_write_byte (abfd, ieee_load_constant_bytes_enum)
241171671b9obrien	  || ! ieee_write_byte (abfd, 1)
241271671b9obrien	  || ! ieee_write_byte (abfd, 0))
241371671b9obrien	return FALSE;
241471671b9obrien    }
241571671b9obrien
241671671b9obrien  return TRUE;
241771671b9obrien}
241871671b9obrien
241971671b9obrienstatic bfd_boolean
24200acbbeedimdo_without_relocs (bfd *abfd, asection *s)
242171671b9obrien{
242271671b9obrien  bfd_byte *stream = ieee_per_section (s)->data;
242371671b9obrien
242471671b9obrien  if (stream == 0 || ((s->flags & SEC_LOAD) == 0))
242571671b9obrien    {
242671671b9obrien      if (! do_as_repeat (abfd, s))
242771671b9obrien	return FALSE;
242871671b9obrien    }
242971671b9obrien  else
243071671b9obrien    {
243171671b9obrien      unsigned int i;
243271671b9obrien
24330acbbeedim      for (i = 0; i < s->size; i++)
243471671b9obrien	{
243571671b9obrien	  if (stream[i] != 0)
243671671b9obrien	    {
243771671b9obrien	      if (! do_with_relocs (abfd, s))
243871671b9obrien		return FALSE;
243971671b9obrien	      return TRUE;
244071671b9obrien	    }
244171671b9obrien	}
244271671b9obrien      if (! do_as_repeat (abfd, s))
244371671b9obrien	return FALSE;
244471671b9obrien    }
244571671b9obrien
244671671b9obrien  return TRUE;
244771671b9obrien}
244871671b9obrien
244971671b9obrienstatic void
24500acbbeedimfill (void)
245171671b9obrien{
245271671b9obrien  bfd_size_type amt = input_ptr_end - input_ptr_start;
245371671b9obrien  /* FIXME: Check return value.  I'm not sure whether it needs to read
245471671b9obrien     the entire buffer or not.  */
24550acbbeedim  bfd_bread ((void *) input_ptr_start, amt, input_bfd);
245671671b9obrien  input_ptr = input_ptr_start;
245771671b9obrien}
245871671b9obrien
245971671b9obrienstatic void
24600acbbeedimflush (void)
246171671b9obrien{
246271671b9obrien  bfd_size_type amt = output_ptr - output_ptr_start;
246371671b9obrien
24640acbbeedim  if (bfd_bwrite ((void *) (output_ptr_start), amt, output_bfd) != amt)
246571671b9obrien    abort ();
246671671b9obrien  output_ptr = output_ptr_start;
246771671b9obrien  output_buffer++;
246871671b9obrien}
246971671b9obrien
247071671b9obrien#define THIS() ( *input_ptr )
24710acbbeedim#define NEXT() { input_ptr++; if (input_ptr == input_ptr_end) fill (); }
24720acbbeedim#define OUT(x) { *output_ptr++ = (x); if (output_ptr == output_ptr_end)  flush (); }
247371671b9obrien
247471671b9obrienstatic void
24750acbbeedimwrite_int (int value)
247671671b9obrien{
247771671b9obrien  if (value >= 0 && value <= 127)
247871671b9obrien    {
247971671b9obrien      OUT (value);
248071671b9obrien    }
248171671b9obrien  else
248271671b9obrien    {
248371671b9obrien      unsigned int length;
24840acbbeedim
248571671b9obrien      /* How many significant bytes ?  */
248671671b9obrien      /* FIXME FOR LONGER INTS.  */
248771671b9obrien      if (value & 0xff000000)
248871671b9obrien	length = 4;
248971671b9obrien      else if (value & 0x00ff0000)
249071671b9obrien	length = 3;
249171671b9obrien      else if (value & 0x0000ff00)
249271671b9obrien	length = 2;
249371671b9obrien      else
249471671b9obrien	length = 1;
249571671b9obrien
249671671b9obrien      OUT ((int) ieee_number_repeat_start_enum + length);
249771671b9obrien      switch (length)
249871671b9obrien	{
249971671b9obrien	case 4:
250071671b9obrien	  OUT (value >> 24);
250171671b9obrien	case 3:
250271671b9obrien	  OUT (value >> 16);
250371671b9obrien	case 2:
250471671b9obrien	  OUT (value >> 8);
250571671b9obrien	case 1:
250671671b9obrien	  OUT (value);
250771671b9obrien	}
250871671b9obrien    }
250971671b9obrien}
251071671b9obrien
251171671b9obrienstatic void
25120acbbeedimcopy_id (void)
251371671b9obrien{
251471671b9obrien  int length = THIS ();
251571671b9obrien  char ch;
251671671b9obrien
251771671b9obrien  OUT (length);
251871671b9obrien  NEXT ();
251971671b9obrien  while (length--)
252071671b9obrien    {
252171671b9obrien      ch = THIS ();
252271671b9obrien      OUT (ch);
252371671b9obrien      NEXT ();
252471671b9obrien    }
252571671b9obrien}
252671671b9obrien
252771671b9obrien#define VAR(x) ((x | 0x80))
252871671b9obrienstatic void
25290acbbeedimcopy_expression (void)
253071671b9obrien{
253171671b9obrien  int stack[10];
253271671b9obrien  int *tos = stack;
253371671b9obrien  int value;
253471671b9obrien
253571671b9obrien  while (1)
253671671b9obrien    {
253771671b9obrien      switch (THIS ())
253871671b9obrien	{
253971671b9obrien	case 0x84:
254071671b9obrien	  NEXT ();
254171671b9obrien	  value = THIS ();
254271671b9obrien	  NEXT ();
254371671b9obrien	  value = (value << 8) | THIS ();
254471671b9obrien	  NEXT ();
254571671b9obrien	  value = (value << 8) | THIS ();
254671671b9obrien	  NEXT ();
254771671b9obrien	  value = (value << 8) | THIS ();
254871671b9obrien	  NEXT ();
254971671b9obrien	  *tos++ = value;
255071671b9obrien	  break;
255171671b9obrien	case 0x83:
255271671b9obrien	  NEXT ();
255371671b9obrien	  value = THIS ();
255471671b9obrien	  NEXT ();
255571671b9obrien	  value = (value << 8) | THIS ();
255671671b9obrien	  NEXT ();
255771671b9obrien	  value = (value << 8) | THIS ();
255871671b9obrien	  NEXT ();
255971671b9obrien	  *tos++ = value;
256071671b9obrien	  break;
256171671b9obrien	case 0x82:
256271671b9obrien	  NEXT ();
256371671b9obrien	  value = THIS ();
256471671b9obrien	  NEXT ();
256571671b9obrien	  value = (value << 8) | THIS ();
256671671b9obrien	  NEXT ();
256771671b9obrien	  *tos++ = value;
256871671b9obrien	  break;
256971671b9obrien	case 0x81:
257071671b9obrien	  NEXT ();
257171671b9obrien	  value = THIS ();
257271671b9obrien	  NEXT ();
257371671b9obrien	  *tos++ = value;
257471671b9obrien	  break;
257571671b9obrien	case 0x80:
257671671b9obrien	  NEXT ();
257771671b9obrien	  *tos++ = 0;
257871671b9obrien	  break;
257971671b9obrien	default:
258071671b9obrien	  if (THIS () > 0x84)
258171671b9obrien	    {
258271671b9obrien	      /* Not a number, just bug out with the answer.  */
258371671b9obrien	      write_int (*(--tos));
258471671b9obrien	      return;
258571671b9obrien	    }
258671671b9obrien	  *tos++ = THIS ();
258771671b9obrien	  NEXT ();
258871671b9obrien	  break;
258971671b9obrien	case 0xa5:
259071671b9obrien	  /* PLUS anything.  */
259171671b9obrien	  value = *(--tos);
259271671b9obrien	  value += *(--tos);
259371671b9obrien	  *tos++ = value;
259471671b9obrien	  NEXT ();
259571671b9obrien	  break;
259671671b9obrien	case VAR ('R'):
259771671b9obrien	  {
259871671b9obrien	    int section_number;
259971671b9obrien	    ieee_data_type *ieee;
260071671b9obrien	    asection *s;
260171671b9obrien
260271671b9obrien	    NEXT ();
260371671b9obrien	    section_number = THIS ();
260471671b9obrien
260571671b9obrien	    NEXT ();
260671671b9obrien	    ieee = IEEE_DATA (input_bfd);
260771671b9obrien	    s = ieee->section_table[section_number];
260871671b9obrien	    value = 0;
260971671b9obrien	    if (s->output_section)
261071671b9obrien	      value = s->output_section->lma;
261171671b9obrien	    value += s->output_offset;
261271671b9obrien	    *tos++ = value;
261371671b9obrien	  }
261471671b9obrien	  break;
261571671b9obrien	case 0x90:
261671671b9obrien	  {
261771671b9obrien	    NEXT ();
261871671b9obrien	    write_int (*(--tos));
261971671b9obrien	    OUT (0x90);
262071671b9obrien	    return;
262171671b9obrien	  }
262271671b9obrien	}
262371671b9obrien    }
262471671b9obrien}
262571671b9obrien
262671671b9obrien/* Drop the int in the buffer, and copy a null into the gap, which we
26270acbbeedim   will overwrite later.  */
262871671b9obrien
262971671b9obrienstatic void
26300acbbeedimfill_int (struct output_buffer_struct *buf)
263171671b9obrien{
263271671b9obrien  if (buf->buffer == output_buffer)
263371671b9obrien    {
263471671b9obrien      /* Still a chance to output the size.  */
263571671b9obrien      int value = output_ptr - buf->ptrp + 3;
263671671b9obrien      buf->ptrp[0] = value >> 24;
263771671b9obrien      buf->ptrp[1] = value >> 16;
263871671b9obrien      buf->ptrp[2] = value >> 8;
263971671b9obrien      buf->ptrp[3] = value >> 0;
264071671b9obrien    }
264171671b9obrien}
264271671b9obrien
264371671b9obrienstatic void
26440acbbeedimdrop_int (struct output_buffer_struct *buf)
264571671b9obrien{
264671671b9obrien  int type = THIS ();
264771671b9obrien  int ch;
264871671b9obrien
264971671b9obrien  if (type <= 0x84)
265071671b9obrien    {
265171671b9obrien      NEXT ();
265271671b9obrien      switch (type)
265371671b9obrien	{
265471671b9obrien	case 0x84:
265571671b9obrien	  ch = THIS ();
265671671b9obrien	  NEXT ();
265771671b9obrien	case 0x83:
265871671b9obrien	  ch = THIS ();
265971671b9obrien	  NEXT ();
266071671b9obrien	case 0x82:
266171671b9obrien	  ch = THIS ();
266271671b9obrien	  NEXT ();
266371671b9obrien	case 0x81:
266471671b9obrien	  ch = THIS ();
266571671b9obrien	  NEXT ();
266671671b9obrien	case 0x80:
266771671b9obrien	  break;
266871671b9obrien	}
266971671b9obrien    }
267071671b9obrien  OUT (0x84);
267171671b9obrien  buf->ptrp = output_ptr;
267271671b9obrien  buf->buffer = output_buffer;
267371671b9obrien  OUT (0);
267471671b9obrien  OUT (0);
267571671b9obrien  OUT (0);
267671671b9obrien  OUT (0);
267771671b9obrien}
267871671b9obrien
267971671b9obrienstatic void
26800acbbeedimcopy_int (void)
268171671b9obrien{
268271671b9obrien  int type = THIS ();
268371671b9obrien  int ch;
268471671b9obrien  if (type <= 0x84)
268571671b9obrien    {
268671671b9obrien      OUT (type);
268771671b9obrien      NEXT ();
268871671b9obrien      switch (type)
268971671b9obrien	{
269071671b9obrien	case 0x84:
269171671b9obrien	  ch = THIS ();
269271671b9obrien	  NEXT ();
269371671b9obrien	  OUT (ch);
269471671b9obrien	case 0x83:
269571671b9obrien	  ch = THIS ();
269671671b9obrien	  NEXT ();
269771671b9obrien	  OUT (ch);
269871671b9obrien	case 0x82:
269971671b9obrien	  ch = THIS ();
270071671b9obrien	  NEXT ();
270171671b9obrien	  OUT (ch);
270271671b9obrien	case 0x81:
270371671b9obrien	  ch = THIS ();
270471671b9obrien	  NEXT ();
270571671b9obrien	  OUT (ch);
270671671b9obrien	case 0x80:
270771671b9obrien	  break;
270871671b9obrien	}
270971671b9obrien    }
271071671b9obrien}
271171671b9obrien
27120acbbeedim#define ID      copy_id ()
27130acbbeedim#define INT     copy_int ()
27140acbbeedim#define EXP     copy_expression ()
27150acbbeedim#define INTn(q) copy_int ()
27160acbbeedim#define EXPn(q) copy_expression ()
27170acbbeedim
27180acbbeedimstatic void
27190acbbeedimcopy_till_end (void)
27200acbbeedim{
27210acbbeedim  int ch = THIS ();
27220acbbeedim
27230acbbeedim  while (1)
27240acbbeedim    {
27250acbbeedim      while (ch <= 0x80)
27260acbbeedim	{
27270acbbeedim	  OUT (ch);
27280acbbeedim	  NEXT ();
27290acbbeedim	  ch = THIS ();
27300acbbeedim	}
27310acbbeedim      switch (ch)
27320acbbeedim	{
27330acbbeedim	case 0x84:
27340acbbeedim	  OUT (THIS ());
27350acbbeedim	  NEXT ();
27360acbbeedim	case 0x83:
27370acbbeedim	  OUT (THIS ());
27380acbbeedim	  NEXT ();
27390acbbeedim	case 0x82:
27400acbbeedim	  OUT (THIS ());
27410acbbeedim	  NEXT ();
27420acbbeedim	case 0x81:
27430acbbeedim	  OUT (THIS ());
27440acbbeedim	  NEXT ();
27450acbbeedim	  OUT (THIS ());
27460acbbeedim	  NEXT ();
27470acbbeedim
27480acbbeedim	  ch = THIS ();
27490acbbeedim	  break;
27500acbbeedim	default:
27510acbbeedim	  return;
27520acbbeedim	}
27530acbbeedim    }
27540acbbeedim
27550acbbeedim}
275671671b9obrien
275771671b9obrienstatic void
27580acbbeedimf1_record (void)
275971671b9obrien{
276071671b9obrien  int ch;
276171671b9obrien
276271671b9obrien  /* ATN record.  */
276371671b9obrien  NEXT ();
276471671b9obrien  ch = THIS ();
276571671b9obrien  switch (ch)
276671671b9obrien    {
276771671b9obrien    default:
276871671b9obrien      OUT (0xf1);
276971671b9obrien      OUT (ch);
277071671b9obrien      break;
277171671b9obrien    case 0xc9:
277271671b9obrien      NEXT ();
277371671b9obrien      OUT (0xf1);
277471671b9obrien      OUT (0xc9);
277571671b9obrien      INT;
277671671b9obrien      INT;
277771671b9obrien      ch = THIS ();
277871671b9obrien      switch (ch)
277971671b9obrien	{
278071671b9obrien	case 0x16:
278171671b9obrien	  NEXT ();
278271671b9obrien	  break;
278371671b9obrien	case 0x01:
278471671b9obrien	  NEXT ();
278571671b9obrien	  break;
278671671b9obrien	case 0x00:
278771671b9obrien	  NEXT ();
278871671b9obrien	  INT;
278971671b9obrien	  break;
279071671b9obrien	case 0x03:
279171671b9obrien	  NEXT ();
279271671b9obrien	  INT;
279371671b9obrien	  break;
279471671b9obrien	case 0x13:
279571671b9obrien	  EXPn (instruction address);
279671671b9obrien	  break;
279771671b9obrien	default:
279871671b9obrien	  break;
279971671b9obrien	}
280071671b9obrien      break;
280171671b9obrien    case 0xd8:
280271671b9obrien      /* EXternal ref.  */
280371671b9obrien      NEXT ();
280471671b9obrien      OUT (0xf1);
280571671b9obrien      OUT (0xd8);
280671671b9obrien      EXP;
280771671b9obrien      EXP;
280871671b9obrien      EXP;
280971671b9obrien      EXP;
281071671b9obrien      break;
281171671b9obrien    case 0xce:
281271671b9obrien      NEXT ();
281371671b9obrien      OUT (0xf1);
281471671b9obrien      OUT (0xce);
281571671b9obrien      INT;
281671671b9obrien      INT;
281771671b9obrien      ch = THIS ();
281871671b9obrien      INT;
281971671b9obrien      switch (ch)
282071671b9obrien	{
282171671b9obrien	case 0x01:
282271671b9obrien	  INT;
282371671b9obrien	  INT;
282471671b9obrien	  break;
282571671b9obrien	case 0x02:
282671671b9obrien	  INT;
282771671b9obrien	  break;
282871671b9obrien	case 0x04:
282971671b9obrien	  EXPn (external function);
283071671b9obrien	  break;
283171671b9obrien	case 0x05:
283271671b9obrien	  break;
283371671b9obrien	case 0x07:
283471671b9obrien	  INTn (line number);
283571671b9obrien	  INT;
283671671b9obrien	case 0x08:
283771671b9obrien	  break;
283871671b9obrien	case 0x0a:
283971671b9obrien	  INTn (locked register);
284071671b9obrien	  INT;
284171671b9obrien	  break;
284271671b9obrien	case 0x3f:
284371671b9obrien	  copy_till_end ();
284471671b9obrien	  break;
284571671b9obrien	case 0x3e:
284671671b9obrien	  copy_till_end ();
284771671b9obrien	  break;
284871671b9obrien	case 0x40:
284971671b9obrien	  copy_till_end ();
285071671b9obrien	  break;
285171671b9obrien	case 0x41:
285271671b9obrien	  ID;
285371671b9obrien	  break;
285471671b9obrien	}
285571671b9obrien    }
285671671b9obrien}
285771671b9obrien
285871671b9obrienstatic void
28590acbbeedimf0_record (void)
286071671b9obrien{
286171671b9obrien  /* Attribute record.  */
286271671b9obrien  NEXT ();
286371671b9obrien  OUT (0xf0);
286471671b9obrien  INTn (Symbol name);
286571671b9obrien  ID;
286671671b9obrien}
286771671b9obrien
286871671b9obrienstatic void
28690acbbeedimf2_record (void)
287071671b9obrien{
287171671b9obrien  NEXT ();
287271671b9obrien  OUT (0xf2);
287371671b9obrien  INT;
287471671b9obrien  NEXT ();
287571671b9obrien  OUT (0xce);
287671671b9obrien  INT;
287771671b9obrien  copy_till_end ();
287871671b9obrien}
287971671b9obrien
288071671b9obrienstatic void
28810acbbeedimf8_record (void)
288271671b9obrien{
288371671b9obrien  int ch;
288471671b9obrien  NEXT ();
288571671b9obrien  ch = THIS ();
288671671b9obrien  switch (ch)
288771671b9obrien    {
288871671b9obrien    case 0x01:
288971671b9obrien    case 0x02:
289071671b9obrien    case 0x03:
289171671b9obrien      /* Unique typedefs for module.  */
289271671b9obrien      /* GLobal typedefs.   */
289371671b9obrien      /* High level module scope beginning.  */
289471671b9obrien      {
289571671b9obrien	struct output_buffer_struct ob;
289671671b9obrien
289771671b9obrien	NEXT ();
289871671b9obrien	OUT (0xf8);
289971671b9obrien	OUT (ch);
290071671b9obrien	drop_int (&ob);
290171671b9obrien	ID;
290271671b9obrien
290371671b9obrien	block ();
290471671b9obrien
290571671b9obrien	NEXT ();
290671671b9obrien	fill_int (&ob);
290771671b9obrien	OUT (0xf9);
290871671b9obrien      }
290971671b9obrien      break;
291071671b9obrien    case 0x04:
291171671b9obrien      /* Global function.  */
291271671b9obrien      {
291371671b9obrien	struct output_buffer_struct ob;
291471671b9obrien
291571671b9obrien	NEXT ();
291671671b9obrien	OUT (0xf8);
291771671b9obrien	OUT (0x04);
291871671b9obrien	drop_int (&ob);
291971671b9obrien	ID;
292071671b9obrien	INTn (stack size);
292171671b9obrien	INTn (ret val);
292271671b9obrien	EXPn (offset);
292371671b9obrien
292471671b9obrien	block ();
292571671b9obrien
292671671b9obrien	NEXT ();
292771671b9obrien	OUT (0xf9);
292871671b9