mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 19:50:13 +08:00
* config/tc-i386.c (md_assemble): Make sure the opcode suffix
matches the register size. PR 9700.
This commit is contained in:
@ -1,3 +1,8 @@
|
|||||||
|
Wed May 15 12:23:53 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
|
* config/tc-i386.c (md_assemble): Make sure the opcode suffix
|
||||||
|
matches the register size.
|
||||||
|
|
||||||
Wed May 15 08:33:37 1996 Jeffrey A Law (law@cygnus.com)
|
Wed May 15 08:33:37 1996 Jeffrey A Law (law@cygnus.com)
|
||||||
|
|
||||||
* config/obj-coff.c (count_entries_in_chain): Ignore Fixups with
|
* config/obj-coff.c (count_entries_in_chain): Ignore Fixups with
|
||||||
|
@ -240,6 +240,71 @@ const relax_typeS md_relax_table[] =
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
i386_align_code (fragP, count)
|
||||||
|
fragS *fragP;
|
||||||
|
int count;
|
||||||
|
{
|
||||||
|
/* Various efficient no-op patterns for aligning code labels. */
|
||||||
|
static const char f32_1[] = {0x90};
|
||||||
|
static const char f32_2[] = {0x8d,0x36};
|
||||||
|
static const char f32_3[] = {0x8d,0x76,0x00};
|
||||||
|
static const char f32_4[] = {0x8d,0x74,0x26,0x00};
|
||||||
|
static const char f32_5[] = {0x90,
|
||||||
|
0x8d,0x74,0x26,0x00};
|
||||||
|
static const char f32_6[] = {0x8d,0xb6,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_7[] = {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_8[] = {0x90,
|
||||||
|
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_9[] = {0x8d,0x36,
|
||||||
|
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_10[] = {0x8d,0x76,0x00,
|
||||||
|
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_11[] = {0x8d,0x74,0x26,0x00,
|
||||||
|
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_12[] = {0x8d,0xb6,0x00,0x00,0x00,0x00,
|
||||||
|
0x8d,0xb6,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_13[] = {0x8d,0xb6,0x00,0x00,0x00,0x00,
|
||||||
|
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_14[] = {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00,
|
||||||
|
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};
|
||||||
|
static const char f32_15[] = {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90,
|
||||||
|
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
|
||||||
|
static const char f16_4[] = {0x8d,0xb6,0x00,0x00};
|
||||||
|
static const char f16_5[] = {0x90,
|
||||||
|
0x8d,0xb6,0x00,0x00};
|
||||||
|
static const char f16_6[] = {0x8d,0x36,
|
||||||
|
0x8d,0xb6,0x00,0x00};
|
||||||
|
static const char f16_7[] = {0x8d,0x76,0x00,
|
||||||
|
0x8d,0xb6,0x00,0x00};
|
||||||
|
static const char f16_8[] = {0x8d,0xb6,0x00,0x00,
|
||||||
|
0x8d,0xb6,0x00,0x00};
|
||||||
|
static const char *const f32_patt[] = {
|
||||||
|
f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
|
||||||
|
f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
|
||||||
|
};
|
||||||
|
static const char *const f16_patt[] = {
|
||||||
|
f32_1, f32_2, f32_3, f16_4, f16_5, f16_6, f16_7, f16_8,
|
||||||
|
f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
|
||||||
|
};
|
||||||
|
|
||||||
|
if (count > 0 && count <= 15)
|
||||||
|
{
|
||||||
|
if (flag_16bit_code)
|
||||||
|
{
|
||||||
|
memcpy(fragP->fr_literal + fragP->fr_fix,
|
||||||
|
f16_patt[count - 1], count);
|
||||||
|
if (count > 8) /* adjust jump offset */
|
||||||
|
fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy(fragP->fr_literal + fragP->fr_fix,
|
||||||
|
f32_patt[count - 1], count);
|
||||||
|
fragP->fr_var = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static char *output_invalid PARAMS ((int c));
|
static char *output_invalid PARAMS ((int c));
|
||||||
static int i386_operand PARAMS ((char *operand_string));
|
static int i386_operand PARAMS ((char *operand_string));
|
||||||
static reg_entry *parse_register PARAMS ((char *reg_string));
|
static reg_entry *parse_register PARAMS ((char *reg_string));
|
||||||
@ -495,6 +560,15 @@ md_begin ()
|
|||||||
record_alignment (bss_section, 2);
|
record_alignment (bss_section, 2);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
i386_print_statistics (file)
|
||||||
|
FILE *file;
|
||||||
|
{
|
||||||
|
hash_print_statistics (file, "i386 opcode", op_hash);
|
||||||
|
hash_print_statistics (file, "i386 register", reg_hash);
|
||||||
|
hash_print_statistics (file, "i386 prefix", prefix_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG386
|
#ifdef DEBUG386
|
||||||
@ -1085,6 +1159,32 @@ md_assemble (line)
|
|||||||
DWORD_OPCODE_SUFFIX);
|
DWORD_OPCODE_SUFFIX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (i.suffix != 0
|
||||||
|
&& i.reg_operands != 0
|
||||||
|
&& (i.types[i.operands - 1] & Reg) != 0)
|
||||||
|
{
|
||||||
|
int want;
|
||||||
|
|
||||||
|
/* If the last operand is a register, make sure it is
|
||||||
|
compatible with the suffix. */
|
||||||
|
|
||||||
|
switch (i.suffix)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
case BYTE_OPCODE_SUFFIX:
|
||||||
|
want = Reg8;
|
||||||
|
break;
|
||||||
|
case WORD_OPCODE_SUFFIX:
|
||||||
|
want = Reg16;
|
||||||
|
break;
|
||||||
|
case DWORD_OPCODE_SUFFIX:
|
||||||
|
want = Reg32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((i.types[i.operands - 1] & want) == 0)
|
||||||
|
as_bad ("register does not match opcode suffix");
|
||||||
|
}
|
||||||
|
|
||||||
/* Make still unresolved immediate matches conform to size of immediate
|
/* Make still unresolved immediate matches conform to size of immediate
|
||||||
given in i.suffix. Note: overlap2 cannot be an immediate!
|
given in i.suffix. Note: overlap2 cannot be an immediate!
|
||||||
@ -1531,11 +1631,7 @@ md_assemble (line)
|
|||||||
/* It's a symbol; end frag & setup for relax.
|
/* It's a symbol; end frag & setup for relax.
|
||||||
Make sure there are more than 6 chars left in the current frag;
|
Make sure there are more than 6 chars left in the current frag;
|
||||||
if not we'll have to start a new one. */
|
if not we'll have to start a new one. */
|
||||||
if (obstack_room (&frags) <= 6)
|
frag_grow (7);
|
||||||
{
|
|
||||||
frag_wane (frag_now);
|
|
||||||
frag_new (0);
|
|
||||||
}
|
|
||||||
p = frag_more (1);
|
p = frag_more (1);
|
||||||
insn_size += 1;
|
insn_size += 1;
|
||||||
p[0] = t->base_opcode;
|
p[0] = t->base_opcode;
|
||||||
@ -2374,8 +2470,9 @@ md_estimate_size_before_relax (fragP, segment)
|
|||||||
*/
|
*/
|
||||||
#ifndef BFD_ASSEMBLER
|
#ifndef BFD_ASSEMBLER
|
||||||
void
|
void
|
||||||
md_convert_frag (headers, fragP)
|
md_convert_frag (headers, sec, fragP)
|
||||||
object_headers *headers;
|
object_headers *headers;
|
||||||
|
segT sec;
|
||||||
register fragS *fragP;
|
register fragS *fragP;
|
||||||
#else
|
#else
|
||||||
void
|
void
|
||||||
@ -2515,12 +2612,14 @@ md_number_to_chars (con, value, nbytes)
|
|||||||
the same (little-endian) format, so we don't need to care about which
|
the same (little-endian) format, so we don't need to care about which
|
||||||
we are handling. */
|
we are handling. */
|
||||||
|
|
||||||
static void
|
int
|
||||||
md_apply_fix_1 (fixP, value)
|
md_apply_fix3 (fixP, valp, seg)
|
||||||
fixS *fixP; /* The fix we're to put in */
|
fixS *fixP; /* The fix we're to put in. */
|
||||||
long value; /* The value of the bits. */
|
valueT *valp; /* Pointer to the value of the bits. */
|
||||||
|
segT seg; /* Segment fix is from. */
|
||||||
{
|
{
|
||||||
register char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
|
register char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
|
||||||
|
valueT value = *valp;
|
||||||
|
|
||||||
#if defined (BFD_ASSEMBLER) && !defined (TE_Mach)
|
#if defined (BFD_ASSEMBLER) && !defined (TE_Mach)
|
||||||
/*
|
/*
|
||||||
@ -2531,7 +2630,8 @@ md_apply_fix_1 (fixP, value)
|
|||||||
{
|
{
|
||||||
value += fixP->fx_where + fixP->fx_frag->fr_address;
|
value += fixP->fx_where + fixP->fx_frag->fr_address;
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
if (S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
|
if (S_GET_SEGMENT (fixP->fx_addsy) == seg
|
||||||
|
|| (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
|
||||||
{
|
{
|
||||||
/* Yes, we add the values in twice. This is because
|
/* Yes, we add the values in twice. This is because
|
||||||
bfd_perform_relocation subtracts them out again. I think
|
bfd_perform_relocation subtracts them out again. I think
|
||||||
@ -2606,26 +2706,9 @@ md_apply_fix_1 (fixP, value)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
md_number_to_chars (p, value, fixP->fx_size);
|
md_number_to_chars (p, value, fixP->fx_size);
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BFD_ASSEMBLER
|
|
||||||
int
|
|
||||||
md_apply_fix (fixP, valp)
|
|
||||||
fixS *fixP;
|
|
||||||
valueT *valp;
|
|
||||||
{
|
|
||||||
md_apply_fix_1 (fixP, *valp);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void
|
|
||||||
md_apply_fix (fixP, val)
|
|
||||||
fixS *fixP;
|
|
||||||
long val;
|
|
||||||
{
|
|
||||||
md_apply_fix_1 (fixP, val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* This is never used. */
|
/* This is never used. */
|
||||||
@ -2731,7 +2814,7 @@ parse_register (reg_string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
CONST char *md_shortopts = "mVQ:";
|
CONST char *md_shortopts = "kmVQ:";
|
||||||
#else
|
#else
|
||||||
CONST char *md_shortopts = "m";
|
CONST char *md_shortopts = "m";
|
||||||
#endif
|
#endif
|
||||||
@ -2752,6 +2835,10 @@ md_parse_option (c, arg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
|
/* -k: Ignore for FreeBSD compatibility. */
|
||||||
|
case 'k':
|
||||||
|
break;
|
||||||
|
|
||||||
/* -V: SVR4 argument to print version ID. */
|
/* -V: SVR4 argument to print version ID. */
|
||||||
case 'V':
|
case 'V':
|
||||||
print_version_id ();
|
print_version_id ();
|
||||||
@ -2960,6 +3047,9 @@ short
|
|||||||
tc_coff_fix2rtype (fixP)
|
tc_coff_fix2rtype (fixP)
|
||||||
fixS *fixP;
|
fixS *fixP;
|
||||||
{
|
{
|
||||||
|
if (fixP->fx_r_type == R_IMAGEBASE)
|
||||||
|
return R_IMAGEBASE;
|
||||||
|
|
||||||
return (fixP->fx_pcrel ?
|
return (fixP->fx_pcrel ?
|
||||||
(fixP->fx_size == 1 ? R_PCRBYTE :
|
(fixP->fx_size == 1 ? R_PCRBYTE :
|
||||||
fixP->fx_size == 2 ? R_PCRWORD :
|
fixP->fx_size == 2 ? R_PCRWORD :
|
||||||
@ -2982,5 +3072,100 @@ tc_coff_sizemachdep (frag)
|
|||||||
#endif /* I386COFF */
|
#endif /* I386COFF */
|
||||||
|
|
||||||
#endif /* BFD_ASSEMBLER? */
|
#endif /* BFD_ASSEMBLER? */
|
||||||
|
|
||||||
|
#ifdef SCO_ELF
|
||||||
|
|
||||||
|
/* Heavily plagarized from obj_elf_version. The idea is to emit the
|
||||||
|
SCO specific identifier in the .notes section to satisfy the SCO
|
||||||
|
linker.
|
||||||
|
|
||||||
|
This looks more complicated than it really is. As opposed to the
|
||||||
|
"obvious" solution, this should handle the cross dev cases
|
||||||
|
correctly. (i.e, hosting on a 64 bit big endian processor, but
|
||||||
|
generating SCO Elf code) Efficiency isn't a concern, as there
|
||||||
|
should be exactly one of these sections per object module.
|
||||||
|
|
||||||
|
SCO OpenServer 5 identifies it's ELF modules with a standard ELF
|
||||||
|
.note section.
|
||||||
|
|
||||||
|
int_32 namesz = 4 ; Name size
|
||||||
|
int_32 descsz = 12 ; Descriptive information
|
||||||
|
int_32 type = 1 ;
|
||||||
|
char name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
|
||||||
|
int_32 version = (major ver # << 16) | version of tools ;
|
||||||
|
int_32 source = (tool_id << 16 ) | 1 ;
|
||||||
|
int_32 info = 0 ; These are set by the SCO tools, but we
|
||||||
|
don't know enough about the source
|
||||||
|
environment to set them. SCO ld currently
|
||||||
|
ignores them, and recommends we set them
|
||||||
|
to zero. */
|
||||||
|
|
||||||
|
#define SCO_MAJOR_VERSION 0x1
|
||||||
|
#define SCO_MINOR_VERSION 0x1
|
||||||
|
|
||||||
|
void
|
||||||
|
sco_id ()
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
unsigned int c;
|
||||||
|
char ch;
|
||||||
|
char *p;
|
||||||
|
asection *seg = now_seg;
|
||||||
|
subsegT subseg = now_subseg;
|
||||||
|
Elf_Internal_Note i_note;
|
||||||
|
Elf_External_Note e_note;
|
||||||
|
asection *note_secp = (asection *) NULL;
|
||||||
|
int i, len;
|
||||||
|
|
||||||
|
/* create the .note section */
|
||||||
|
|
||||||
|
note_secp = subseg_new (".note", 0);
|
||||||
|
bfd_set_section_flags (stdoutput,
|
||||||
|
note_secp,
|
||||||
|
SEC_HAS_CONTENTS | SEC_READONLY);
|
||||||
|
|
||||||
|
/* process the version string */
|
||||||
|
|
||||||
|
i_note.namesz = 4;
|
||||||
|
i_note.descsz = 12; /* 12 descriptive bytes */
|
||||||
|
i_note.type = NT_VERSION; /* Contains a version string */
|
||||||
|
|
||||||
|
p = frag_more (sizeof (i_note.namesz));
|
||||||
|
md_number_to_chars (p, (valueT) i_note.namesz, 4);
|
||||||
|
|
||||||
|
p = frag_more (sizeof (i_note.descsz));
|
||||||
|
md_number_to_chars (p, (valueT) i_note.descsz, 4);
|
||||||
|
|
||||||
|
p = frag_more (sizeof (i_note.type));
|
||||||
|
md_number_to_chars (p, (valueT) i_note.type, 4);
|
||||||
|
|
||||||
|
p = frag_more (4);
|
||||||
|
strcpy (p, "SCO");
|
||||||
|
|
||||||
|
/* Note: this is the version number of the ELF we're representing */
|
||||||
|
p = frag_more (4);
|
||||||
|
md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
|
||||||
|
|
||||||
|
/* Here, we pick a magic number for ourselves (yes, I "registered"
|
||||||
|
it with SCO. The bottom bit shows that we are compat with the
|
||||||
|
SCO ABI. */
|
||||||
|
p = frag_more (4);
|
||||||
|
md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
|
||||||
|
|
||||||
|
/* If we knew (or cared) what the source language options were, we'd
|
||||||
|
fill them in here. SCO has given us permission to ignore these
|
||||||
|
and just set them to zero. */
|
||||||
|
p = frag_more (4);
|
||||||
|
md_number_to_chars (p, 0x0000, 4);
|
||||||
|
|
||||||
|
frag_align (2, 0);
|
||||||
|
|
||||||
|
/* We probably can't restore the current segment, for there likely
|
||||||
|
isn't one yet... */
|
||||||
|
if (seg && subseg)
|
||||||
|
subseg_set (seg, subseg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SCO_ELF */
|
||||||
|
|
||||||
/* end of tc-i386.c */
|
/* end of tc-i386.c */
|
||||||
|
Reference in New Issue
Block a user