mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 12:23:31 +08:00
A bunch of changes to COFF support. See the ChangeLog.
This commit is contained in:
@ -1,4 +0,0 @@
|
||||
# TDEFINES = -DBFD_HEADERS
|
||||
# LOCAL_LOADLIBES = $(srcdir)/../bfd/$(srcdir)/libbfd.a
|
||||
CC = gcc
|
||||
MINUS_G = -O
|
@ -1,5 +1,6 @@
|
||||
# Define SYSV as -DSYSV if you are using a System V operating system.
|
||||
SYSV = -DSYSV
|
||||
RANLIB = /bin/true
|
||||
RANLIB = true
|
||||
CC = gcc
|
||||
MINUS_G = -O
|
||||
# comment out the next line if you don't have gcc2 and shareable libraries.
|
||||
LDFLAGS= -shlib
|
||||
|
@ -84,10 +84,8 @@ int function_lineoff = -1; /* Offset in line#s where the last function
|
||||
started (the odd entry for line #0) */
|
||||
|
||||
|
||||
int had_lineno = 0;
|
||||
int had_reloc = 0;
|
||||
|
||||
static symbolS *last_line_symbol;
|
||||
|
||||
/* Add 4 to the real value to get the index and compensate the
|
||||
negatives. This vector is used by S_GET_SEGMENT to turn a coff
|
||||
section number into a segment number
|
||||
@ -105,12 +103,14 @@ static void EXFUN (fixup_segment, (segment_info_type *segP,
|
||||
segT this_segment_type));
|
||||
|
||||
|
||||
static void EXFUN (fixup_mdeps, (fragS *));
|
||||
static void EXFUN (fixup_mdeps, (fragS *,
|
||||
object_headers *,
|
||||
segT));
|
||||
|
||||
|
||||
static void EXFUN (fill_section, (bfd * abfd,
|
||||
struct internal_filehdr * f, unsigned
|
||||
long *));
|
||||
object_headers *,
|
||||
unsigned long *));
|
||||
|
||||
|
||||
char *EXFUN (s_get_name, (symbolS * s));
|
||||
@ -138,6 +138,8 @@ static void EXFUN (obj_coff_lcomm, (void));
|
||||
static void EXFUN (obj_coff_dim, (void));
|
||||
static void EXFUN (obj_coff_text, (void));
|
||||
static void EXFUN (obj_coff_data, (void));
|
||||
static void EXFUN( obj_coff_bss,(void));
|
||||
static void EXFUN( obj_coff_ident,(void));
|
||||
static void EXFUN (obj_coff_endef, (void));
|
||||
static void EXFUN (obj_coff_line, (void));
|
||||
static void EXFUN (obj_coff_ln, (void));
|
||||
@ -171,8 +173,8 @@ const pseudo_typeS obj_pseudo_table[] =
|
||||
{"sect", obj_coff_section, 0},
|
||||
{"text", obj_coff_text, 0},
|
||||
{"data", obj_coff_data, 0},
|
||||
/* we don't yet handle this. */
|
||||
{"ident", s_ignore, 0},
|
||||
{"bss", obj_coff_bss, 0},
|
||||
{"ident", obj_coff_ident, 0},
|
||||
{"ABORT", s_abort, 0},
|
||||
{"lcomm", obj_coff_lcomm, 0},
|
||||
{NULL} /* end sentinel */
|
||||
@ -279,7 +281,6 @@ DEFUN (size_section, (abfd, idx),
|
||||
while (frag)
|
||||
{
|
||||
size = frag->fr_address;
|
||||
#if 0
|
||||
if (frag->fr_address != size)
|
||||
{
|
||||
printf ("Out of step\n");
|
||||
@ -302,7 +303,6 @@ DEFUN (size_section, (abfd, idx),
|
||||
size += frag->fr_fix;
|
||||
size += relax_align (size, frag->fr_offset);
|
||||
}
|
||||
#endif
|
||||
frag = frag->fr_next;
|
||||
}
|
||||
segment_info[idx].scnhdr.s_size = size;
|
||||
@ -343,13 +343,15 @@ DEFUN (count_entries_in_chain, (idx),
|
||||
|
||||
/* output all the relocations for a section */
|
||||
void
|
||||
DEFUN (do_relocs_for, (abfd, file_cursor),
|
||||
DEFUN (do_relocs_for, (abfd, h, file_cursor),
|
||||
bfd * abfd AND
|
||||
object_headers * h AND
|
||||
unsigned long *file_cursor)
|
||||
{
|
||||
unsigned int nrelocs;
|
||||
unsigned int idx;
|
||||
unsigned int addr = 0;
|
||||
unsigned long reloc_start = *file_cursor;
|
||||
|
||||
for (idx = SEG_E0; idx < SEG_E9; idx++)
|
||||
{
|
||||
if (segment_info[idx].scnhdr.s_name[0])
|
||||
@ -359,19 +361,14 @@ DEFUN (do_relocs_for, (abfd, file_cursor),
|
||||
struct external_reloc *external_reloc_vec;
|
||||
unsigned int external_reloc_size;
|
||||
unsigned int count = 0;
|
||||
unsigned int base = addr;
|
||||
unsigned int base = segment_info[idx].scnhdr.s_paddr;
|
||||
fixS *fix_ptr = segment_info[idx].fix_root;
|
||||
nrelocs = count_entries_in_chain (idx);
|
||||
|
||||
if (nrelocs)
|
||||
had_reloc = 1;
|
||||
|
||||
external_reloc_size = nrelocs * RELSZ;
|
||||
external_reloc_vec =
|
||||
(struct external_reloc *) malloc (external_reloc_size);
|
||||
|
||||
|
||||
|
||||
ext_ptr = external_reloc_vec;
|
||||
|
||||
/* Fill in the internal coff style reloc struct from the
|
||||
@ -426,16 +423,25 @@ DEFUN (do_relocs_for, (abfd, file_cursor),
|
||||
ext_ptr++;
|
||||
|
||||
#if defined(TC_A29K)
|
||||
/* The 29k has a special kludge for the high 16 bit reloc.
|
||||
Two relocations are emmited, R_IHIHALF, and
|
||||
R_IHCONST. The second one doesn't contain a symbol,
|
||||
but uses the value for offset */
|
||||
|
||||
/* The 29k has a special kludge for the high 16 bit
|
||||
reloc. Two relocations are emited, R_IHIHALF,
|
||||
and R_IHCONST. The second one doesn't contain a
|
||||
symbol, but uses the value for offset. */
|
||||
|
||||
if (intr.r_type == R_IHIHALF)
|
||||
{
|
||||
/* now emit the second bit */
|
||||
intr.r_type = R_IHCONST;
|
||||
intr.r_symndx = fix_ptr->fx_addnumber;
|
||||
|
||||
/* The offset to the segment holding the symbol
|
||||
has already been counted in the R_IHIHALF.
|
||||
We don't want to add it in again for the
|
||||
R_IHCONST. */
|
||||
if (symbol_ptr)
|
||||
intr.r_symndx -=
|
||||
segment_info[S_GET_SEGMENT (symbol_ptr)].scnhdr.s_paddr;
|
||||
(void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
|
||||
ext_ptr++;
|
||||
}
|
||||
@ -446,14 +452,15 @@ DEFUN (do_relocs_for, (abfd, file_cursor),
|
||||
}
|
||||
|
||||
/* Write out the reloc table */
|
||||
segment_info[idx].scnhdr.s_relptr = *file_cursor;
|
||||
segment_info[idx].scnhdr.s_relptr = nrelocs ? *file_cursor : 0;
|
||||
segment_info[idx].scnhdr.s_nreloc = nrelocs;
|
||||
bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, abfd);
|
||||
*file_cursor += external_reloc_size;
|
||||
free (external_reloc_vec);
|
||||
}
|
||||
addr += segment_info[idx].scnhdr.s_size;
|
||||
}
|
||||
/* Set relocation_size field in file headers */
|
||||
H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -461,16 +468,14 @@ DEFUN (do_relocs_for, (abfd, file_cursor),
|
||||
in the scnhdrs with the info on the file postions
|
||||
*/
|
||||
static void
|
||||
DEFUN (fill_section, (abfd, filehdr, file_cursor),
|
||||
DEFUN (fill_section, (abfd, h, file_cursor),
|
||||
bfd * abfd AND
|
||||
struct internal_filehdr *filehdr AND
|
||||
object_headers *h AND
|
||||
unsigned long *file_cursor)
|
||||
{
|
||||
|
||||
unsigned int i;
|
||||
#ifdef ZERO_BASED_SEGMENTS
|
||||
unsigned int paddr = 0;
|
||||
#endif
|
||||
|
||||
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
|
||||
{
|
||||
@ -483,20 +488,15 @@ DEFUN (fill_section, (abfd, filehdr, file_cursor),
|
||||
fragS *frag = segment_info[i].frchainP->frch_root;
|
||||
char *buffer;
|
||||
|
||||
if (s->s_size != 0 && i != SEG_E2)
|
||||
{
|
||||
buffer = malloc (s->s_size);
|
||||
s->s_scnptr = *file_cursor;
|
||||
#ifdef ZERO_BASED_SEGMENTS
|
||||
s->s_paddr = paddr;
|
||||
s->s_vaddr = paddr;
|
||||
#endif
|
||||
}
|
||||
if (s->s_size == 0)
|
||||
s->s_scnptr = 0;
|
||||
else
|
||||
{
|
||||
buffer = NULL;
|
||||
s->s_scnptr = 0;
|
||||
buffer = xmalloc (s->s_size);
|
||||
s->s_scnptr = *file_cursor;
|
||||
}
|
||||
know (s->s_paddr == paddr);
|
||||
s->s_vaddr = paddr;
|
||||
|
||||
s->s_flags = STYP_REG;
|
||||
if (strcmp (s->s_name, ".text") == 0)
|
||||
@ -504,13 +504,23 @@ DEFUN (fill_section, (abfd, filehdr, file_cursor),
|
||||
else if (strcmp (s->s_name, ".data") == 0)
|
||||
s->s_flags |= STYP_DATA;
|
||||
else if (strcmp (s->s_name, ".bss") == 0)
|
||||
s->s_flags |= STYP_BSS | STYP_NOLOAD;
|
||||
{
|
||||
s->s_scnptr = 0;
|
||||
s->s_flags |= STYP_BSS;
|
||||
#ifndef TC_I386
|
||||
/* Apparently the SVR3 linker is confused by noload
|
||||
sections. */
|
||||
s->s_flags |= STYP_NOLOAD;
|
||||
#endif
|
||||
}
|
||||
else if (strcmp (s->s_name, ".lit") == 0)
|
||||
s->s_flags = STYP_LIT | STYP_TEXT;
|
||||
else if (strcmp (s->s_name, ".init") == 0)
|
||||
s->s_flags |= STYP_TEXT;
|
||||
else if (strcmp (s->s_name, ".fini") == 0)
|
||||
s->s_flags |= STYP_TEXT;
|
||||
else if (strncmp (s->s_name, ".comment", 8) == 0)
|
||||
s->s_flags |= STYP_INFO;
|
||||
|
||||
while (frag)
|
||||
{
|
||||
@ -545,17 +555,15 @@ DEFUN (fill_section, (abfd, filehdr, file_cursor),
|
||||
unsigned int off = frag->fr_fix;
|
||||
for (count = frag->fr_offset; count; count--)
|
||||
{
|
||||
if (fill_size < s->s_size) {
|
||||
|
||||
memcpy (buffer + frag->fr_address + off,
|
||||
frag->fr_literal + frag->fr_fix,
|
||||
fill_size);
|
||||
off += fill_size;
|
||||
offset += fill_size;
|
||||
if (fill_size < s->s_size)
|
||||
{
|
||||
memcpy (buffer + frag->fr_address + off,
|
||||
frag->fr_literal + frag->fr_fix,
|
||||
fill_size);
|
||||
off += fill_size;
|
||||
offset += fill_size;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case rs_broken_word:
|
||||
@ -566,45 +574,49 @@ DEFUN (fill_section, (abfd, filehdr, file_cursor),
|
||||
frag = frag->fr_next;
|
||||
}
|
||||
|
||||
if (s->s_size != 0 && i != SEG_E2)
|
||||
if (s->s_size != 0)
|
||||
{
|
||||
bfd_write (buffer, s->s_size, 1, abfd);
|
||||
if (s->s_scnptr != 0)
|
||||
{
|
||||
bfd_write (buffer, s->s_size, 1, abfd);
|
||||
*file_cursor += s->s_size;
|
||||
}
|
||||
free (buffer);
|
||||
*file_cursor += s->s_size;
|
||||
}
|
||||
#ifdef ZERO_BASED_SEGMENTS
|
||||
paddr += s->s_size;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Coff file generation & utilities */
|
||||
|
||||
|
||||
static void
|
||||
DEFUN (coff_header_append, (abfd, filehdr, aouthdr),
|
||||
DEFUN (coff_header_append, (abfd, h),
|
||||
bfd * abfd AND
|
||||
struct internal_filehdr *filehdr AND
|
||||
struct internal_aouthdr *aouthdr)
|
||||
object_headers * h)
|
||||
{
|
||||
unsigned int i;
|
||||
char buffer[1000];
|
||||
char buffero[1000];
|
||||
|
||||
bfd_seek (abfd, 0, 0);
|
||||
#if 0
|
||||
filehdr.f_opthdr = bfd_coff_swap_aouthdr_out (abfd, aouthdr,
|
||||
buffero);
|
||||
#else
|
||||
filehdr->f_opthdr = 0;
|
||||
#endif
|
||||
i = bfd_coff_swap_filehdr_out (abfd, filehdr, buffer);
|
||||
|
||||
#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
|
||||
H_SET_MAGIC_NUMBER (h, COFF_MAGIC);
|
||||
H_SET_VERSION_STAMP (h, 0);
|
||||
H_SET_ENTRY_POINT (h, 0);
|
||||
H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address);
|
||||
H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address);
|
||||
H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr,
|
||||
buffero));
|
||||
#else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */
|
||||
H_SET_SIZEOF_OPTIONAL_HEADER (h, 0);
|
||||
#endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */
|
||||
|
||||
i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer);
|
||||
|
||||
bfd_write (buffer, i, 1, abfd);
|
||||
bfd_write (buffero, filehdr->f_opthdr, 1, abfd);
|
||||
bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd);
|
||||
|
||||
for (i = SEG_E0; i < SEG_E9; i++)
|
||||
{
|
||||
@ -1591,8 +1603,8 @@ DEFUN_VOID (tie_tags)
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN (crawl_symbols, (headers, abfd),
|
||||
struct internal_filehdr *headers AND
|
||||
DEFUN (crawl_symbols, (h, abfd),
|
||||
object_headers *h AND
|
||||
bfd * abfd)
|
||||
{
|
||||
|
||||
@ -1654,20 +1666,21 @@ DEFUN (crawl_symbols, (headers, abfd),
|
||||
{
|
||||
if (segment_info[i].scnhdr.s_name[0])
|
||||
{
|
||||
segment_info[i].dot =
|
||||
c_section_symbol (segment_info[i].scnhdr.s_name,
|
||||
i - SEG_E0 + 1);
|
||||
char name[9];
|
||||
|
||||
strncpy (name, segment_info[i].scnhdr.s_name, 8);
|
||||
name[8] = '\0';
|
||||
segment_info[i].dot = c_section_symbol (name, i - SEG_E0 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Take all the externals out and put them into another chain */
|
||||
headers->f_nsyms = yank_symbols ();
|
||||
H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
|
||||
/* Take the externals and glue them onto the end.*/
|
||||
headers->f_nsyms += glue_symbols ();
|
||||
H_SET_SYMBOL_TABLE_SIZE (h, H_GET_SYMBOL_COUNT (h) + glue_symbols ());
|
||||
|
||||
headers->f_nsyms = tie_tags ();
|
||||
H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ());
|
||||
know (symbol_externP == NULL);
|
||||
know (symbol_extern_lastP == NULL);
|
||||
|
||||
@ -1705,16 +1718,14 @@ DEFUN (w_strings, (where),
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
DEFUN (do_linenos_for, (abfd, file_cursor),
|
||||
DEFUN (do_linenos_for, (abfd, h, file_cursor),
|
||||
bfd * abfd AND
|
||||
object_headers * h AND
|
||||
unsigned long *file_cursor)
|
||||
{
|
||||
unsigned int idx;
|
||||
unsigned long start = *file_cursor;
|
||||
|
||||
for (idx = SEG_E0; idx < SEG_E9; idx++)
|
||||
{
|
||||
@ -1763,6 +1774,7 @@ DEFUN (do_linenos_for, (abfd, file_cursor),
|
||||
*file_cursor += s->scnhdr.s_nlnno * LINESZ;
|
||||
}
|
||||
}
|
||||
H_SET_LINENO_SIZE (h, *file_cursor - start);
|
||||
}
|
||||
|
||||
|
||||
@ -1799,8 +1811,7 @@ DEFUN_VOID (write_object_file)
|
||||
int i;
|
||||
struct frchain *frchain_ptr;
|
||||
|
||||
struct internal_filehdr filehdr;
|
||||
struct internal_aouthdr aouthdr;
|
||||
object_headers headers;
|
||||
unsigned long file_cursor;
|
||||
bfd *abfd;
|
||||
unsigned int addr;
|
||||
@ -1815,8 +1826,6 @@ DEFUN_VOID (write_object_file)
|
||||
bfd_set_format (abfd, bfd_object);
|
||||
bfd_set_arch_mach (abfd, BFD_ARCH, machine);
|
||||
|
||||
|
||||
|
||||
string_byte_count = 4;
|
||||
|
||||
for (frchain_ptr = frchain_root;
|
||||
@ -1847,106 +1856,90 @@ DEFUN_VOID (write_object_file)
|
||||
relax_segment (segment_info[i].frchainP->frch_root, i);
|
||||
}
|
||||
|
||||
filehdr.f_nscns = 0;
|
||||
H_SET_NUMBER_OF_SECTIONS (&headers, 0);
|
||||
|
||||
/* Find out how big the sections are, and set the addresses. */
|
||||
addr = 0;
|
||||
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
|
||||
{
|
||||
long size;
|
||||
|
||||
segment_info[i].scnhdr.s_paddr = addr;
|
||||
segment_info[i].scnhdr.s_vaddr = addr;
|
||||
|
||||
if (segment_info[i].scnhdr.s_name[0])
|
||||
{
|
||||
filehdr.f_nscns++;
|
||||
H_SET_NUMBER_OF_SECTIONS (&headers,
|
||||
H_GET_NUMBER_OF_SECTIONS (&headers) + 1);
|
||||
}
|
||||
|
||||
/* Supposedly setting segment addresses non-zero
|
||||
causes problems for some platforms, although it
|
||||
shouldn't. If you define ZERO_BASED_SEGMENTS, all
|
||||
the segments will be based at 0. Please don't make
|
||||
this the default, since some systems (e.g., SVR3.2)
|
||||
require the segments to be non-zero based. Ian
|
||||
Taylor <ian@cygnus.com>. */
|
||||
size = size_section (abfd, i);
|
||||
addr += size;
|
||||
|
||||
if (i == SEG_E2)
|
||||
{
|
||||
/* This is a special case, we leave the size alone, which
|
||||
will have been made up from all and any lcomms seen. */
|
||||
#ifndef ZERO_BASED_SEGMENTS
|
||||
addr += segment_info[i].scnhdr.s_size;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef ZERO_BASED_SEGMENTS
|
||||
addr += size_section (abfd, i);
|
||||
#else
|
||||
size_section (abfd, i);
|
||||
#endif
|
||||
}
|
||||
if (i == SEG_E0)
|
||||
H_SET_TEXT_SIZE (&headers, size);
|
||||
else if (i == SEG_E1)
|
||||
H_SET_DATA_SIZE (&headers, size);
|
||||
else if (i == SEG_E2)
|
||||
H_SET_BSS_SIZE (&headers, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Turn the gas native symbol table shape into a coff symbol table */
|
||||
crawl_symbols (&filehdr, abfd);
|
||||
crawl_symbols (&headers, abfd);
|
||||
|
||||
if (string_byte_count == 4)
|
||||
string_byte_count = 0;
|
||||
|
||||
H_SET_STRING_SIZE (&headers, string_byte_count);
|
||||
|
||||
#if !defined(TC_H8300) && !defined(TC_Z8K)
|
||||
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
|
||||
{
|
||||
fixup_mdeps (segment_info[i].frchainP->frch_root);
|
||||
fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i);
|
||||
fixup_segment (&segment_info[i], i);
|
||||
}
|
||||
#endif
|
||||
|
||||
file_cursor = FILHSZ + SCNHSZ * filehdr.f_nscns;
|
||||
file_cursor = H_GET_TEXT_FILE_OFFSET (&headers);
|
||||
|
||||
bfd_seek (abfd, file_cursor, 0);
|
||||
|
||||
|
||||
do_relocs_for (abfd, &file_cursor);
|
||||
|
||||
do_linenos_for (abfd, &file_cursor);
|
||||
|
||||
|
||||
/* Plant the data */
|
||||
|
||||
fill_section (abfd, &filehdr, &file_cursor);
|
||||
|
||||
|
||||
|
||||
filehdr.f_magic = COFF_MAGIC;
|
||||
filehdr.f_timdat = time (0);
|
||||
filehdr.f_flags = COFF_FLAGS | coff_flags;
|
||||
|
||||
if (!had_lineno)
|
||||
{
|
||||
filehdr.f_flags |= F_LNNO;
|
||||
}
|
||||
if (!had_reloc)
|
||||
{
|
||||
filehdr.f_flags |= F_RELFLG;
|
||||
}
|
||||
|
||||
|
||||
fill_section (abfd, &headers, &file_cursor);
|
||||
|
||||
do_relocs_for (abfd, &headers, &file_cursor);
|
||||
|
||||
do_linenos_for (abfd, &headers, &file_cursor);
|
||||
|
||||
H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC);
|
||||
#ifndef OBJ_COFF_OMIT_TIMESTAMP
|
||||
H_SET_TIME_STAMP (&headers, (long)time((long*)0));
|
||||
#else
|
||||
H_SET_TIME_STAMP (&headers, 0);
|
||||
#endif
|
||||
|
||||
#ifdef KEEP_RELOC_INFO
|
||||
H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
|
||||
COFF_FLAGS | coff_flags));
|
||||
#else
|
||||
H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
|
||||
(H_GET_RELOCATION_SIZE(&headers) ? 0 : F_RELFLG) |
|
||||
COFF_FLAGS | coff_flags));
|
||||
#endif
|
||||
|
||||
{
|
||||
|
||||
unsigned int symtable_size = filehdr.f_nsyms * SYMESZ;
|
||||
char *buffer1 = malloc (symtable_size + string_byte_count + 4);
|
||||
unsigned int symtable_size = H_GET_SYMBOL_TABLE_SIZE (&headers);
|
||||
char *buffer1 = xmalloc (symtable_size + string_byte_count + 1);
|
||||
char *ptr = buffer1;
|
||||
filehdr.f_symptr = bfd_tell (abfd);
|
||||
H_SET_SYMBOL_TABLE_POINTER (&headers, bfd_tell (abfd));
|
||||
w_symbols (abfd, buffer1, symbol_rootP);
|
||||
w_strings (buffer1 + symtable_size);
|
||||
bfd_write (buffer1, 1, symtable_size + string_byte_count + 4, abfd);
|
||||
if (string_byte_count > 0)
|
||||
w_strings (buffer1 + symtable_size);
|
||||
bfd_write (buffer1, 1, symtable_size + string_byte_count, abfd);
|
||||
free (buffer1);
|
||||
|
||||
}
|
||||
coff_header_append (abfd, &filehdr, &aouthdr);
|
||||
|
||||
coff_header_append (abfd, &headers);
|
||||
|
||||
if (bfd_close_all_done (abfd) == false)
|
||||
as_fatal ("Can't close %s: %s", out_file_name,
|
||||
@ -1976,6 +1969,21 @@ DEFUN (change_to_section, (name, len, exp),
|
||||
subseg_new (i, exp);
|
||||
}
|
||||
|
||||
/*
|
||||
* implement the .section pseudo op:
|
||||
* .section name {, "flags"}
|
||||
* ^ ^
|
||||
* | +--- optional flags: 'b' for bss
|
||||
* | 'i' for info
|
||||
* +-- section name 'l' for lib
|
||||
* 'n' for noload
|
||||
* 'o' for over
|
||||
* 'w' for data
|
||||
* 'x' for text
|
||||
* But if the argument is not a quoted string, treat it as a
|
||||
* subsegment number.
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN_VOID (obj_coff_section)
|
||||
{
|
||||
@ -1983,9 +1991,10 @@ DEFUN_VOID (obj_coff_section)
|
||||
char *section_name;
|
||||
char *section_name_end;
|
||||
char c;
|
||||
|
||||
int argp;
|
||||
unsigned int len;
|
||||
unsigned int exp;
|
||||
long flags;
|
||||
|
||||
section_name = input_line_pointer;
|
||||
c = get_symbol_end ();
|
||||
@ -1995,26 +2004,53 @@ DEFUN_VOID (obj_coff_section)
|
||||
input_line_pointer++;
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
/* Some 386 assemblers stick a quoted string at the end of
|
||||
a .section; we just ignore it. */
|
||||
if (c == ',' && *input_line_pointer != '"')
|
||||
argp = 0;
|
||||
if (c == ',')
|
||||
argp = 1;
|
||||
else if (*input_line_pointer == ',')
|
||||
{
|
||||
exp = get_absolute_expression ();
|
||||
argp = 1;
|
||||
++input_line_pointer;
|
||||
SKIP_WHITESPACE ();
|
||||
}
|
||||
else if (*input_line_pointer == ','
|
||||
&& input_line_pointer[1] != '"')
|
||||
|
||||
exp = 0;
|
||||
flags = 0;
|
||||
if (argp)
|
||||
{
|
||||
input_line_pointer++;
|
||||
exp = get_absolute_expression ();
|
||||
}
|
||||
else
|
||||
{
|
||||
exp = 0;
|
||||
while (! is_end_of_line[*input_line_pointer])
|
||||
++input_line_pointer;
|
||||
if (*input_line_pointer != '"')
|
||||
exp = get_absolute_expression ();
|
||||
else
|
||||
{
|
||||
++input_line_pointer;
|
||||
while (*input_line_pointer != '"'
|
||||
&& ! is_end_of_line[*input_line_pointer])
|
||||
{
|
||||
switch (*input_line_pointer)
|
||||
{
|
||||
case 'b': flags |= STYP_BSS; break;
|
||||
case 'i': flags |= STYP_INFO; break;
|
||||
case 'l': flags |= STYP_LIB; break;
|
||||
case 'n': flags |= STYP_NOLOAD; break;
|
||||
case 'o': flags |= STYP_OVER; break;
|
||||
case 'w': flags |= STYP_DATA; break;
|
||||
case 'x': flags |= STYP_TEXT; break;
|
||||
default:
|
||||
as_warn("unknown section attribute '%c'",
|
||||
*input_line_pointer);
|
||||
break;
|
||||
}
|
||||
++input_line_pointer;
|
||||
}
|
||||
if (*input_line_pointer == '"')
|
||||
++input_line_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
change_to_section (section_name, len, exp);
|
||||
|
||||
segment_info[now_seg].scnhdr.s_flags |= flags;
|
||||
|
||||
*section_name_end = c;
|
||||
}
|
||||
|
||||
@ -2032,6 +2068,25 @@ obj_coff_data ()
|
||||
change_to_section (".data", 5, get_absolute_expression ());
|
||||
}
|
||||
|
||||
static void
|
||||
obj_coff_bss()
|
||||
{
|
||||
if (*input_line_pointer == '\n') /* .bss */
|
||||
change_to_section(".bss",4, get_absolute_expression());
|
||||
else /* .bss id,expr */
|
||||
obj_coff_lcomm();
|
||||
}
|
||||
|
||||
static void
|
||||
obj_coff_ident()
|
||||
{
|
||||
segT current_seg = now_seg; /* save current seg */
|
||||
subsegT current_subseg = now_subseg;
|
||||
change_to_section (".comment", 8, 0); /* .comment seg */
|
||||
stringer (1); /* read string */
|
||||
subseg_new (current_seg, current_subseg); /* restore current seg */
|
||||
}
|
||||
|
||||
void
|
||||
c_symbol_merge (debug, normal)
|
||||
symbolS *debug;
|
||||
@ -2067,8 +2122,6 @@ DEFUN (c_line_new, (symbol, paddr, line_number, frag),
|
||||
segment_info_type *s = segment_info + now_seg;
|
||||
new_line->line.l_lnno = line_number;
|
||||
|
||||
had_lineno = 1;
|
||||
|
||||
if (line_number == 0)
|
||||
{
|
||||
last_line_symbol = symbol;
|
||||
@ -2221,12 +2274,10 @@ DEFUN_VOID (obj_coff_lcomm)
|
||||
char c;
|
||||
int temp;
|
||||
char *p;
|
||||
unsigned long vma;
|
||||
|
||||
symbolS *symbolP;
|
||||
name = input_line_pointer;
|
||||
|
||||
|
||||
c = get_symbol_end ();
|
||||
p = input_line_pointer;
|
||||
*p = c;
|
||||
@ -2251,30 +2302,40 @@ DEFUN_VOID (obj_coff_lcomm)
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
{
|
||||
/* Allocate zero static local data in the .data section now
|
||||
instead of the bss section as a symbol with a value */
|
||||
char *x;
|
||||
segT oldseg = now_seg;
|
||||
int oldsubseg = now_subseg;
|
||||
symbolP = symbol_find_or_make(name);
|
||||
|
||||
subseg_new (SEG_DATA, 10);
|
||||
colon (name);
|
||||
frag_align (2, 0);
|
||||
record_alignment (SEG_DATA, 4);
|
||||
x = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
|
||||
temp, (char *) 0);
|
||||
*x = 0;
|
||||
if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN &&
|
||||
S_GET_VALUE(symbolP) == 0)
|
||||
{
|
||||
if (! need_pass_2)
|
||||
{
|
||||
char *p;
|
||||
segT current_seg = now_seg; /* save current seg */
|
||||
subsegT current_subseg = now_subseg;
|
||||
|
||||
subseg_new (oldseg, oldsubseg);
|
||||
}
|
||||
demand_empty_rest_of_line ();
|
||||
subseg_new (SEG_E2, 1);
|
||||
symbolP->sy_frag = frag_now;
|
||||
p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP,
|
||||
temp, (char *)0);
|
||||
*p = 0;
|
||||
subseg_new (current_seg, current_subseg); /* restore current seg */
|
||||
S_SET_SEGMENT(symbolP, SEG_E2);
|
||||
S_SET_STORAGE_CLASS(symbolP, C_STAT);
|
||||
}
|
||||
}
|
||||
else
|
||||
as_bad("Symbol %s already defined", name);
|
||||
|
||||
demand_empty_rest_of_line();
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN (fixup_mdeps, (frags),
|
||||
fragS * frags)
|
||||
DEFUN (fixup_mdeps, (frags, h, this_segment),
|
||||
fragS * frags AND
|
||||
object_headers * h AND
|
||||
segT this_segment)
|
||||
{
|
||||
subseg_change (this_segment, 0);
|
||||
while (frags)
|
||||
{
|
||||
switch (frags->fr_type)
|
||||
@ -2286,14 +2347,14 @@ DEFUN (fixup_mdeps, (frags),
|
||||
(frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
|
||||
break;
|
||||
case rs_machine_dependent:
|
||||
md_convert_frag (0, frags);
|
||||
md_convert_frag (h, frags);
|
||||
frag_wane (frags);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
frags = frags->fr_next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 1
|
||||
@ -2469,7 +2530,8 @@ DEFUN (fixup_segment, (segP, this_segment_type),
|
||||
stored in the .text segment (I've
|
||||
checked this on SVR3.2 and SCO 3.2.2)
|
||||
Ian Taylor <ian@cygnus.com>. */
|
||||
add_number += S_GET_VALUE (add_symbolP);
|
||||
if (S_IS_COMMON (add_symbolP))
|
||||
add_number += S_GET_VALUE (add_symbolP);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* coff object file format
|
||||
Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
|
||||
|
||||
@ -26,6 +25,9 @@
|
||||
#define WORKING_DOT_WORD
|
||||
#define WARN_SIGNED_OVERFLOW_WORD
|
||||
|
||||
/* By default we omit the optional aouthdr. */
|
||||
#define OBJ_COFF_OMIT_OPTIONAL_HEADER
|
||||
|
||||
#include "targ-cpu.h"
|
||||
|
||||
#include "bfd.h"
|
||||
|
@ -4488,9 +4488,11 @@ VMS_Check_For_Main ()
|
||||
/*
|
||||
* Write a VAX/VMS object file (everything else has been done!)
|
||||
*/
|
||||
VMS_write_object_file (text_siz, data_siz, text_frag_root, data_frag_root)
|
||||
VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
|
||||
data_frag_root)
|
||||
unsigned text_siz;
|
||||
unsigned data_siz;
|
||||
unsigned bss_siz;
|
||||
struct frag *text_frag_root;
|
||||
struct frag *data_frag_root;
|
||||
{
|
||||
@ -4581,11 +4583,10 @@ VMS_write_object_file (text_siz, data_siz, text_frag_root, data_frag_root)
|
||||
/*
|
||||
* Define the BSS Psect
|
||||
*/
|
||||
if (local_bss_counter > 0)
|
||||
if (bss_siz > 0)
|
||||
{
|
||||
Bss_Psect = Psect_Number++;
|
||||
VMS_Psect_Spec ("$uninitialized_data", local_bss_counter, "DATA",
|
||||
0);
|
||||
VMS_Psect_Spec ("$uninitialized_data", bss_siz, "DATA", 0);
|
||||
}
|
||||
#ifndef gxx_bug_fixed
|
||||
/*
|
||||
|
@ -22,7 +22,6 @@
|
||||
much bloody rewriting required before. There still probably is. */
|
||||
|
||||
#include "as.h"
|
||||
#include "read.h"
|
||||
|
||||
#include "opcode/a29k.h"
|
||||
|
||||
|
@ -22,20 +22,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <ctype.h>
|
||||
#include "m88k-opcode.h"
|
||||
#include "as.h"
|
||||
#include "frags.h"
|
||||
#include "struc-symbol.h"
|
||||
#include "flonum.h"
|
||||
#include "expr.h"
|
||||
#include "hash.h"
|
||||
#include "md.h"
|
||||
#include "m88k.h"
|
||||
#include "write.h"
|
||||
#include "read.h"
|
||||
/*
|
||||
#include "obstack.h"
|
||||
#include "struc-symbol.h"
|
||||
*/
|
||||
#include "symbols.h"
|
||||
|
||||
char *getval ();
|
||||
char *get_reg ();
|
||||
@ -1232,7 +1221,7 @@ s_bss ()
|
||||
char *name;
|
||||
char c;
|
||||
char *p;
|
||||
int temp, bss_align = 1;
|
||||
int temp, bss_align;
|
||||
symbolS *symbolP;
|
||||
extern const char is_end_of_line[256];
|
||||
|
||||
@ -1261,27 +1250,42 @@ s_bss ()
|
||||
{
|
||||
input_line_pointer++;
|
||||
bss_align = get_absolute_expression ();
|
||||
while (local_bss_counter % bss_align != 0)
|
||||
local_bss_counter++;
|
||||
}
|
||||
else
|
||||
bss_align = 0;
|
||||
|
||||
if (symbolP->sy_other == 0
|
||||
&& symbolP->sy_desc == 0
|
||||
&& ((symbolP->sy_type == N_BSS
|
||||
&& symbolP->sy_value == local_bss_counter)
|
||||
|| ((symbolP->sy_type & N_TYPE) == N_UNDF
|
||||
&& symbolP->sy_value == 0)))
|
||||
if (!S_IS_DEFINED(symbolP)
|
||||
|| S_GET_SEGMENT(symbolP) == SEG_BSS)
|
||||
{
|
||||
symbolP->sy_value = local_bss_counter;
|
||||
symbolP->sy_type = N_BSS;
|
||||
symbolP->sy_frag = &bss_address_frag;
|
||||
local_bss_counter += temp;
|
||||
if (! need_pass_2)
|
||||
{
|
||||
char *p;
|
||||
segT current_seg = now_seg;
|
||||
subsegT current_subseg = now_subseg;
|
||||
|
||||
subseg_new (SEG_BSS, 1); /* switch to bss */
|
||||
|
||||
if (bss_align)
|
||||
frag_align (bss_align, 0);
|
||||
|
||||
/* detach from old frag */
|
||||
if (symbolP->sy_type == N_BSS && symbolP->sy_frag != NULL)
|
||||
symbolP->sy_frag->fr_symbol = NULL;
|
||||
|
||||
symbolP->sy_frag = frag_now;
|
||||
p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
|
||||
temp, (char *)0);
|
||||
*p = 0;
|
||||
S_SET_SEGMENT (symbolP, SEG_BSS);
|
||||
|
||||
subseg_new (current_seg, current_subseg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
as_warn ("Ignoring attempt to re-define symbol from %d. to %d.",
|
||||
symbolP->sy_value, local_bss_counter);
|
||||
as_warn ("Ignoring attempt to re-define symbol %s.", name);
|
||||
}
|
||||
|
||||
while (!is_end_of_line[*input_line_pointer])
|
||||
{
|
||||
input_line_pointer++;
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
#include "as.h"
|
||||
|
||||
#include "read.h"
|
||||
#include "vax-inst.h"
|
||||
#include "obstack.h" /* For FRAG_APPEND_1_CHAR macro in "frags.h" */
|
||||
|
||||
@ -388,20 +387,20 @@ md_assemble (instruction_string)
|
||||
as_fatal ("vax_assemble\"%s\" in=\"%s\"", p, instruction_string);
|
||||
}
|
||||
/*
|
||||
* Now we try to find as many as_warn()s as we can. If we do any as_warn()s
|
||||
* then goofed=1. Notice that we don't make any frags yet.
|
||||
* Should goofed be 1, then this instruction will wedge in any pass,
|
||||
* and we can safely flush it, without causing interpass symbol phase
|
||||
* errors. That is, without changing label values in different passes.
|
||||
*/
|
||||
* Now we try to find as many as_warn()s as we can. If we do any as_warn()s
|
||||
* then goofed=1. Notice that we don't make any frags yet.
|
||||
* Should goofed be 1, then this instruction will wedge in any pass,
|
||||
* and we can safely flush it, without causing interpass symbol phase
|
||||
* errors. That is, without changing label values in different passes.
|
||||
*/
|
||||
if (goofed = (*v.vit_error))
|
||||
{
|
||||
as_warn ("Ignoring statement due to \"%s\"", v.vit_error);
|
||||
}
|
||||
/*
|
||||
* We need to use expression() and friends, which require us to diddle
|
||||
* input_line_pointer. So we save it and restore it later.
|
||||
*/
|
||||
* We need to use expression() and friends, which require us to diddle
|
||||
* input_line_pointer. So we save it and restore it later.
|
||||
*/
|
||||
save_input_line_pointer = input_line_pointer;
|
||||
for (operandP = v.vit_operand,
|
||||
expP = exp_of_operand,
|
||||
@ -418,7 +417,8 @@ md_assemble (instruction_string)
|
||||
goofed = 1;
|
||||
}
|
||||
else
|
||||
{ /* statement has no syntax goofs: lets sniff the expression */
|
||||
{
|
||||
/* statement has no syntax goofs: lets sniff the expression */
|
||||
int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal. */
|
||||
|
||||
input_line_pointer = operandP->vop_expr_begin;
|
||||
@ -431,10 +431,11 @@ md_assemble (instruction_string)
|
||||
/* for BSD4.2 compatibility, missing expression is absolute 0 */
|
||||
to_seg = expP->X_seg = SEG_ABSOLUTE;
|
||||
expP->X_add_number = 0;
|
||||
/* for SEG_ABSOLUTE, we shouldnt need to set X_subtract_symbol, X_add_symbol to any
|
||||
particular value. But, we will program defensively. Since this situation occurs rarely
|
||||
so it costs us little to do, and stops Dean worrying about the origin of random bits in
|
||||
expressionS's. */
|
||||
/* For SEG_ABSOLUTE, we shouldn't need to set X_subtract_symbol,
|
||||
X_add_symbol to any particular value. But, we will program
|
||||
defensively. Since this situation occurs rarely so it costs
|
||||
us little to do, and stops Dean worrying about the origin of
|
||||
random bits in expressionS's. */
|
||||
expP->X_add_symbol = NULL;
|
||||
expP->X_subtract_symbol = NULL;
|
||||
case SEG_TEXT:
|
||||
@ -447,18 +448,18 @@ md_assemble (instruction_string)
|
||||
case SEG_DIFFERENCE:
|
||||
case SEG_PASS1:
|
||||
/*
|
||||
* Major bug. We can't handle the case of a
|
||||
* SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC
|
||||
* variable-length instruction.
|
||||
* We don't have a frag type that is smart enough to
|
||||
* relax a SEG_DIFFERENCE, and so we just force all
|
||||
* SEG_DIFFERENCEs to behave like SEG_PASS1s.
|
||||
* Clearly, if there is a demand we can invent a new or
|
||||
* modified frag type and then coding up a frag for this
|
||||
* case will be easy. SEG_DIFFERENCE was invented for the
|
||||
* .words after a CASE opcode, and was never intended for
|
||||
* instruction operands.
|
||||
*/
|
||||
* Major bug. We can't handle the case of a
|
||||
* SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC
|
||||
* variable-length instruction.
|
||||
* We don't have a frag type that is smart enough to
|
||||
* relax a SEG_DIFFERENCE, and so we just force all
|
||||
* SEG_DIFFERENCEs to behave like SEG_PASS1s.
|
||||
* Clearly, if there is a demand we can invent a new or
|
||||
* modified frag type and then coding up a frag for this
|
||||
* case will be easy. SEG_DIFFERENCE was invented for the
|
||||
* .words after a CASE opcode, and was never intended for
|
||||
* instruction operands.
|
||||
*/
|
||||
need_pass_2 = 1;
|
||||
as_warn ("Can't relocate expression");
|
||||
break;
|
||||
@ -1828,10 +1829,10 @@ vip (vitP, instring)
|
||||
c = *p;
|
||||
*p = '\0';
|
||||
/*
|
||||
* Here with instring pointing to what better be an op-name, and p
|
||||
* pointing to character just past that.
|
||||
* We trust instring points to an op-name, with no whitespace.
|
||||
*/
|
||||
* Here with instring pointing to what better be an op-name, and p
|
||||
* pointing to character just past that.
|
||||
* We trust instring points to an op-name, with no whitespace.
|
||||
*/
|
||||
vwP = (struct vot_wot *) hash_find (op_hash, instring);
|
||||
*p = c; /* Restore char after op-code. */
|
||||
if (vwP == 0)
|
||||
@ -1843,18 +1844,18 @@ vip (vitP, instring)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We found a match! So lets pick up as many operands as the
|
||||
* instruction wants, and even gripe if there are too many.
|
||||
* We expect comma to seperate each operand.
|
||||
* We let instring track the text, while p tracks a part of the
|
||||
* struct vot.
|
||||
*/
|
||||
* We found a match! So lets pick up as many operands as the
|
||||
* instruction wants, and even gripe if there are too many.
|
||||
* We expect comma to seperate each operand.
|
||||
* We let instring track the text, while p tracks a part of the
|
||||
* struct vot.
|
||||
*/
|
||||
/*
|
||||
* The lines below know about 2-byte opcodes starting FD,FE or FF.
|
||||
* They also understand synthetic opcodes. Note:
|
||||
* we return 32 bits of opcode, including bucky bits, BUT
|
||||
* an opcode length is either 8 or 16 bits for vit_opcode_nbytes.
|
||||
*/
|
||||
* The lines below know about 2-byte opcodes starting FD,FE or FF.
|
||||
* They also understand synthetic opcodes. Note:
|
||||
* we return 32 bits of opcode, including bucky bits, BUT
|
||||
* an opcode length is either 8 or 16 bits for vit_opcode_nbytes.
|
||||
*/
|
||||
oc = vwP->vot_code; /* The op-code. */
|
||||
vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1;
|
||||
md_number_to_chars (vitP->vit_opcode, oc, 4);
|
||||
@ -1867,9 +1868,9 @@ vip (vitP, instring)
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Here to parse one operand. Leave instring pointing just
|
||||
* past any one ',' that marks the end of this operand.
|
||||
*/
|
||||
* Here to parse one operand. Leave instring pointing just
|
||||
* past any one ',' that marks the end of this operand.
|
||||
*/
|
||||
if (!p[1])
|
||||
bug = "p"; /* ODD(!!) number of bytes in vot_how?? */
|
||||
else if (*instring)
|
||||
@ -1877,9 +1878,9 @@ vip (vitP, instring)
|
||||
for (q = instring; (c = *q) && c != ','; q++)
|
||||
;
|
||||
/*
|
||||
* Q points to ',' or '\0' that ends argument. C is that
|
||||
* character.
|
||||
*/
|
||||
* Q points to ',' or '\0' that ends argument. C is that
|
||||
* character.
|
||||
*/
|
||||
*q = 0;
|
||||
operandp->vop_width = p[1];
|
||||
operandp->vop_nbytes = vax_operand_width_size[p[1]];
|
||||
@ -2355,12 +2356,13 @@ vip_op_defaults (immediate, indirect, displen) /* can be called any time */
|
||||
char * /* (code here) bug message, "" = OK */
|
||||
/* our code bug, NOT bad assembly language */
|
||||
vip_op (optext, vopP)
|
||||
char *optext; /* user's input string e.g.: */
|
||||
/* "@B^foo@bar(AP)[FP]:" */
|
||||
struct vop *vopP; /* In: vop_access, vop_width. */
|
||||
/* Out: _ndx, _reg, _mode, _short, _warn, */
|
||||
/* _error _expr_begin, _expr_end, _nbytes. */
|
||||
/* vop_nbytes : number of bytes in a datum. */
|
||||
/* user's input string e.g.: "@B^foo@bar(AP)[FP]:" */
|
||||
char *optext;
|
||||
/* Input fields: vop_access, vop_width.
|
||||
Output fields: _ndx, _reg, _mode, _short, _warn,
|
||||
_error _expr_begin, _expr_end, _nbytes.
|
||||
vop_nbytes : number of bytes in a datum. */
|
||||
struct vop *vopP;
|
||||
{
|
||||
char *p; /* track operand text forward */
|
||||
char *q; /* track operand text backward */
|
||||
@ -2467,9 +2469,9 @@ vip_op (optext, vopP)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Confusers like "[]" will eventually lose with a bad register
|
||||
* name error. So again we don't need to check for early '\0'.
|
||||
*/
|
||||
* Confusers like "[]" will eventually lose with a bad register
|
||||
* name error. So again we don't need to check for early '\0'.
|
||||
*/
|
||||
if (q[3] == ']')
|
||||
ndx = vax_reg_parse (q[1], q[2], 0);
|
||||
else if (q[4] == ']')
|
||||
@ -2522,9 +2524,9 @@ vip_op (optext, vopP)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Confusers like "()" will eventually lose with a bad register
|
||||
* name error. So again we don't need to check for early '\0'.
|
||||
*/
|
||||
* Confusers like "()" will eventually lose with a bad register
|
||||
* name error. So again we don't need to check for early '\0'.
|
||||
*/
|
||||
if (q[3] == ')')
|
||||
reg = vax_reg_parse (q[1], q[2], 0);
|
||||
else if (q[4] == ')')
|
||||
@ -2532,11 +2534,11 @@ vip_op (optext, vopP)
|
||||
else
|
||||
reg = -1;
|
||||
/*
|
||||
* Since we saw a ')' we will demand a register name in the ')'.
|
||||
* This is nasty: why can't our hypothetical assembler permit
|
||||
* parenthesised expressions? BECAUSE I AM LAZY! That is why.
|
||||
* Abuse luser if we didn't spy a register name.
|
||||
*/
|
||||
* Since we saw a ')' we will demand a register name in the ')'.
|
||||
* This is nasty: why can't our hypothetical assembler permit
|
||||
* parenthesised expressions? BECAUSE I AM LAZY! That is why.
|
||||
* Abuse luser if we didn't spy a register name.
|
||||
*/
|
||||
if (reg < 0)
|
||||
{
|
||||
/* JF allow parenthasized expressions. I hope this works */
|
||||
@ -2548,31 +2550,31 @@ vip_op (optext, vopP)
|
||||
else
|
||||
q--; /* point just before '(' of "(...)" */
|
||||
/*
|
||||
* If err == "..." then we lost. Run away.
|
||||
* Otherwise if reg >= 0 then we saw (Rn).
|
||||
*/
|
||||
* If err == "..." then we lost. Run away.
|
||||
* Otherwise if reg >= 0 then we saw (Rn).
|
||||
*/
|
||||
}
|
||||
/*
|
||||
* If err == "..." then we lost.
|
||||
* Otherwise paren==1 and reg = register in "()".
|
||||
*/
|
||||
* If err == "..." then we lost.
|
||||
* Otherwise paren==1 and reg = register in "()".
|
||||
*/
|
||||
}
|
||||
else
|
||||
paren = 0;
|
||||
/*
|
||||
* If err == "..." then we lost.
|
||||
* Otherwise, q points just before "(Rn)", if any.
|
||||
* If there was a "(...)" then paren==1, and reg is the register.
|
||||
*/
|
||||
* If err == "..." then we lost.
|
||||
* Otherwise, q points just before "(Rn)", if any.
|
||||
* If there was a "(...)" then paren==1, and reg is the register.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We should only seek '-' of "-(...)" if:
|
||||
* we saw "(...)" paren == 1
|
||||
* we have no errors so far ! *err
|
||||
* we did not see '+' of "(...)+" sign < 1
|
||||
* We don't check len. We want a specific error message later if
|
||||
* user tries "x^...-(Rn)". This is a feature not a bug.
|
||||
*/
|
||||
* We should only seek '-' of "-(...)" if:
|
||||
* we saw "(...)" paren == 1
|
||||
* we have no errors so far ! *err
|
||||
* we did not see '+' of "(...)+" sign < 1
|
||||
* We don't check len. We want a specific error message later if
|
||||
* user tries "x^...-(Rn)". This is a feature not a bug.
|
||||
*/
|
||||
if (!*err)
|
||||
{
|
||||
if (paren && sign < 1)/* !sign is adequate test */
|
||||
@ -2584,14 +2586,14 @@ vip_op (optext, vopP)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We have back-tracked over most
|
||||
* of the crud at the end of an operand.
|
||||
* Unless err, we know: sign, paren. If paren, we know reg.
|
||||
* The last case is of an expression "Rn".
|
||||
* This is worth hunting for if !err, !paren.
|
||||
* We wouldn't be here if err.
|
||||
* We remember to save q, in case we didn't want "Rn" anyway.
|
||||
*/
|
||||
* We have back-tracked over most
|
||||
* of the crud at the end of an operand.
|
||||
* Unless err, we know: sign, paren. If paren, we know reg.
|
||||
* The last case is of an expression "Rn".
|
||||
* This is worth hunting for if !err, !paren.
|
||||
* We wouldn't be here if err.
|
||||
* We remember to save q, in case we didn't want "Rn" anyway.
|
||||
*/
|
||||
if (!paren)
|
||||
{
|
||||
if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
|
||||
@ -2603,8 +2605,8 @@ vip_op (optext, vopP)
|
||||
else
|
||||
reg = -1; /* always comes here if no register at all */
|
||||
/*
|
||||
* Here with a definitive reg value.
|
||||
*/
|
||||
* Here with a definitive reg value.
|
||||
*/
|
||||
if (reg >= 0)
|
||||
{
|
||||
oldq = q;
|
||||
@ -2614,41 +2616,41 @@ vip_op (optext, vopP)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* have reg. -1:absent; else 0:15
|
||||
*/
|
||||
* have reg. -1:absent; else 0:15
|
||||
*/
|
||||
|
||||
/*
|
||||
* We have: err, at, len, hash, ndx, sign, paren, reg.
|
||||
* Also, any remaining expression is from *p through *q inclusive.
|
||||
* Should there be no expression, q==p-1. So expression length = q-p+1.
|
||||
* This completes the first part: parsing the operand text.
|
||||
*/
|
||||
* We have: err, at, len, hash, ndx, sign, paren, reg.
|
||||
* Also, any remaining expression is from *p through *q inclusive.
|
||||
* Should there be no expression, q==p-1. So expression length = q-p+1.
|
||||
* This completes the first part: parsing the operand text.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We now want to boil the data down, checking consistency on the way.
|
||||
* We want: len, mode, reg, ndx, err, p, q, wrn, bug.
|
||||
* We will deliver a 4-bit reg, and a 4-bit mode.
|
||||
*/
|
||||
* We now want to boil the data down, checking consistency on the way.
|
||||
* We want: len, mode, reg, ndx, err, p, q, wrn, bug.
|
||||
* We will deliver a 4-bit reg, and a 4-bit mode.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Case of branch operand. Different. No L^B^W^I^S^ allowed for instance.
|
||||
*
|
||||
* in: at ?
|
||||
* len ?
|
||||
* hash ?
|
||||
* p:q ?
|
||||
* sign ?
|
||||
* paren ?
|
||||
* reg ?
|
||||
* ndx ?
|
||||
*
|
||||
* out: mode 0
|
||||
* reg -1
|
||||
* len ' '
|
||||
* p:q whatever was input
|
||||
* ndx -1
|
||||
* err " " or error message, and other outputs trashed
|
||||
*/
|
||||
* Case of branch operand. Different. No L^B^W^I^S^ allowed for instance.
|
||||
*
|
||||
* in: at ?
|
||||
* len ?
|
||||
* hash ?
|
||||
* p:q ?
|
||||
* sign ?
|
||||
* paren ?
|
||||
* reg ?
|
||||
* ndx ?
|
||||
*
|
||||
* out: mode 0
|
||||
* reg -1
|
||||
* len ' '
|
||||
* p:q whatever was input
|
||||
* ndx -1
|
||||
* err " " or error message, and other outputs trashed
|
||||
*/
|
||||
/* branch operands have restricted forms */
|
||||
if (!*err && access == 'b')
|
||||
{
|
||||
@ -2661,24 +2663,24 @@ vip_op (optext, vopP)
|
||||
/* Since nobody seems to use it: comment this 'feature'(?) out for now. */
|
||||
#ifdef NEVER
|
||||
/*
|
||||
* Case of stand-alone operand. e.g. ".long foo"
|
||||
*
|
||||
* in: at ?
|
||||
* len ?
|
||||
* hash ?
|
||||
* p:q ?
|
||||
* sign ?
|
||||
* paren ?
|
||||
* reg ?
|
||||
* ndx ?
|
||||
*
|
||||
* out: mode 0
|
||||
* reg -1
|
||||
* len ' '
|
||||
* p:q whatever was input
|
||||
* ndx -1
|
||||
* err " " or error message, and other outputs trashed
|
||||
*/
|
||||
* Case of stand-alone operand. e.g. ".long foo"
|
||||
*
|
||||
* in: at ?
|
||||
* len ?
|
||||
* hash ?
|
||||
* p:q ?
|
||||
* sign ?
|
||||
* paren ?
|
||||
* reg ?
|
||||
* ndx ?
|
||||
*
|
||||
* out: mode 0
|
||||
* reg -1
|
||||
* len ' '
|
||||
* p:q whatever was input
|
||||
* ndx -1
|
||||
* err " " or error message, and other outputs trashed
|
||||
*/
|
||||
if (!*err)
|
||||
{
|
||||
if (access == ' ')
|
||||
@ -2730,23 +2732,23 @@ vip_op (optext, vopP)
|
||||
#endif /*#Ifdef NEVER*/
|
||||
|
||||
/*
|
||||
* Case of S^#.
|
||||
*
|
||||
* in: at 0
|
||||
* len 's' definition
|
||||
* hash 1 demand
|
||||
* p:q demand not empty
|
||||
* sign 0 by paren==0
|
||||
* paren 0 by "()" scan logic because "S^" seen
|
||||
* reg -1 or nn by mistake
|
||||
* ndx -1
|
||||
*
|
||||
* out: mode 0
|
||||
* reg -1
|
||||
* len 's'
|
||||
* exp
|
||||
* ndx -1
|
||||
*/
|
||||
* Case of S^#.
|
||||
*
|
||||
* in: at 0
|
||||
* len 's' definition
|
||||
* hash 1 demand
|
||||
* p:q demand not empty
|
||||
* sign 0 by paren==0
|
||||
* paren 0 by "()" scan logic because "S^" seen
|
||||
* reg -1 or nn by mistake
|
||||
* ndx -1
|
||||
*
|
||||
* out: mode 0
|
||||
* reg -1
|
||||
* len 's'
|
||||
* exp
|
||||
* ndx -1
|
||||
*/
|
||||
if (!*err && len == 's')
|
||||
{
|
||||
if (!hash || paren || at || ndx >= 0)
|
||||
@ -2779,23 +2781,23 @@ vip_op (optext, vopP)
|
||||
}
|
||||
|
||||
/*
|
||||
* Case of -(Rn), which is weird case.
|
||||
*
|
||||
* in: at 0
|
||||
* len '
|
||||
* hash 0
|
||||
* p:q q<p
|
||||
* sign -1 by definition
|
||||
* paren 1 by definition
|
||||
* reg present by definition
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 7
|
||||
* reg present
|
||||
* len ' '
|
||||
* exp "" enforce empty expression
|
||||
* ndx optional warn if same as reg
|
||||
*/
|
||||
* Case of -(Rn), which is weird case.
|
||||
*
|
||||
* in: at 0
|
||||
* len '
|
||||
* hash 0
|
||||
* p:q q<p
|
||||
* sign -1 by definition
|
||||
* paren 1 by definition
|
||||
* reg present by definition
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 7
|
||||
* reg present
|
||||
* len ' '
|
||||
* exp "" enforce empty expression
|
||||
* ndx optional warn if same as reg
|
||||
*/
|
||||
if (!*err && sign < 0)
|
||||
{
|
||||
if (len != ' ' || hash || at || p <= q)
|
||||
@ -2812,10 +2814,10 @@ vip_op (optext, vopP)
|
||||
}
|
||||
|
||||
/*
|
||||
* We convert "(Rn)" to "@Rn" for our convenience.
|
||||
* (I hope this is convenient: has someone got a better way to parse this?)
|
||||
* A side-effect of this is that "@Rn" is a valid operand.
|
||||
*/
|
||||
* We convert "(Rn)" to "@Rn" for our convenience.
|
||||
* (I hope this is convenient: has someone got a better way to parse this?)
|
||||
* A side-effect of this is that "@Rn" is a valid operand.
|
||||
*/
|
||||
if (paren && !sign && !hash && !at && len == ' ' && p > q)
|
||||
{
|
||||
at = 1;
|
||||
@ -2823,23 +2825,23 @@ vip_op (optext, vopP)
|
||||
}
|
||||
|
||||
/*
|
||||
* Case of (Rn)+, which is slightly different.
|
||||
*
|
||||
* in: at
|
||||
* len ' '
|
||||
* hash 0
|
||||
* p:q q<p
|
||||
* sign +1 by definition
|
||||
* paren 1 by definition
|
||||
* reg present by definition
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 8+@
|
||||
* reg present
|
||||
* len ' '
|
||||
* exp "" enforce empty expression
|
||||
* ndx optional warn if same as reg
|
||||
*/
|
||||
* Case of (Rn)+, which is slightly different.
|
||||
*
|
||||
* in: at
|
||||
* len ' '
|
||||
* hash 0
|
||||
* p:q q<p
|
||||
* sign +1 by definition
|
||||
* paren 1 by definition
|
||||
* reg present by definition
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 8+@
|
||||
* reg present
|
||||
* len ' '
|
||||
* exp "" enforce empty expression
|
||||
* ndx optional warn if same as reg
|
||||
*/
|
||||
if (!*err && sign > 0)
|
||||
{
|
||||
if (len != ' ' || hash || p <= q)
|
||||
@ -2856,23 +2858,23 @@ vip_op (optext, vopP)
|
||||
}
|
||||
|
||||
/*
|
||||
* Case of #, without S^.
|
||||
*
|
||||
* in: at
|
||||
* len ' ' or 'i'
|
||||
* hash 1 by definition
|
||||
* p:q
|
||||
* sign 0
|
||||
* paren 0
|
||||
* reg absent
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 8+@
|
||||
* reg PC
|
||||
* len ' ' or 'i'
|
||||
* exp
|
||||
* ndx optional
|
||||
*/
|
||||
* Case of #, without S^.
|
||||
*
|
||||
* in: at
|
||||
* len ' ' or 'i'
|
||||
* hash 1 by definition
|
||||
* p:q
|
||||
* sign 0
|
||||
* paren 0
|
||||
* reg absent
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 8+@
|
||||
* reg PC
|
||||
* len ' ' or 'i'
|
||||
* exp
|
||||
* ndx optional
|
||||
*/
|
||||
if (!*err && hash)
|
||||
{
|
||||
if (len != 'i' && len != ' ')
|
||||
@ -2884,10 +2886,10 @@ vip_op (optext, vopP)
|
||||
if (reg >= 0)
|
||||
{
|
||||
/*
|
||||
* SHIT! we saw #Rnn! Put the Rnn back into the expression.
|
||||
* By using oldq, we don't need to know how long Rnn was.
|
||||
* KLUDGE!
|
||||
*/
|
||||
* SHIT! we saw #Rnn! Put the Rnn back into the expression.
|
||||
* By using oldq, we don't need to know how long Rnn was.
|
||||
* KLUDGE!
|
||||
*/
|
||||
q = oldq;
|
||||
reg = -1; /* no register any more */
|
||||
}
|
||||
@ -2904,29 +2906,29 @@ vip_op (optext, vopP)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If !*err, then sign == 0
|
||||
* hash == 0
|
||||
*/
|
||||
* If !*err, then sign == 0
|
||||
* hash == 0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Case of Rn. We seperate this one because it has a few special
|
||||
* errors the remaining modes lack.
|
||||
*
|
||||
* in: at optional
|
||||
* len ' '
|
||||
* hash 0 by program logic
|
||||
* p:q empty
|
||||
* sign 0 by program logic
|
||||
* paren 0 by definition
|
||||
* reg present by definition
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 5+@
|
||||
* reg present
|
||||
* len ' ' enforce no length
|
||||
* exp "" enforce empty expression
|
||||
* ndx optional warn if same as reg
|
||||
*/
|
||||
* Case of Rn. We seperate this one because it has a few special
|
||||
* errors the remaining modes lack.
|
||||
*
|
||||
* in: at optional
|
||||
* len ' '
|
||||
* hash 0 by program logic
|
||||
* p:q empty
|
||||
* sign 0 by program logic
|
||||
* paren 0 by definition
|
||||
* reg present by definition
|
||||
* ndx optional
|
||||
*
|
||||
* out: mode 5+@
|
||||
* reg present
|
||||
* len ' ' enforce no length
|
||||
* exp "" enforce empty expression
|
||||
* ndx optional warn if same as reg
|
||||
*/
|
||||
if (!*err && !paren && reg >= 0)
|
||||
{
|
||||
if (len != ' ')
|
||||
@ -2943,12 +2945,12 @@ vip_op (optext, vopP)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Idea here is to detect from length of datum
|
||||
* and from register number if we will touch PC.
|
||||
* Warn if we do.
|
||||
* vop_nbytes is number of bytes in operand.
|
||||
* Compute highest byte affected, compare to PC0.
|
||||
*/
|
||||
* Idea here is to detect from length of datum
|
||||
* and from register number if we will touch PC.
|
||||
* Warn if we do.
|
||||
* vop_nbytes is number of bytes in operand.
|
||||
* Compute highest byte affected, compare to PC0.
|
||||
*/
|
||||
if ((vopP->vop_nbytes + reg * 4) > 60)
|
||||
wrn = "PC part of operand unpredictable";
|
||||
err = " "; /* win */
|
||||
@ -2996,12 +2998,12 @@ vip_op (optext, vopP)
|
||||
}
|
||||
|
||||
/*
|
||||
* here with completely specified mode
|
||||
* len
|
||||
* reg
|
||||
* expression p,q
|
||||
* ndx
|
||||
*/
|
||||
* here with completely specified mode
|
||||
* len
|
||||
* reg
|
||||
* expression p,q
|
||||
* ndx
|
||||
*/
|
||||
|
||||
if (*err == ' ')
|
||||
err = ""; /* " " is no longer an error */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Machine specific defines for the SCO Unix V.3.2 ODT */
|
||||
#define scounix
|
||||
|
||||
/* Return true if s (a non null string pointer), points to a local variable name. */
|
||||
#define LOCAL_LABEL(n) ((n)[0] == '.' && (n)[1] == 'L')
|
||||
/* Local labels start with a period. */
|
||||
#define DOT_LABEL_PREFIX
|
||||
|
||||
/* end of te-sco386.h */
|
||||
|
Reference in New Issue
Block a user