From: Ian Lance Taylor Date: Wed, 15 May 1996 16:26:20 +0000 (+0000) Subject: * config/tc-i386.c (md_assemble): Make sure the opcode suffix X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3ea36b5319fd97e0784f8caaa2180893c477b1b5;p=binutils-gdb.git * config/tc-i386.c (md_assemble): Make sure the opcode suffix matches the register size. PR 9700. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 81f8839bf76..115b3ea4676 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +Wed May 15 12:23:53 1996 Ian Lance Taylor + + * 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) * config/obj-coff.c (count_entries_in_chain): Ignore Fixups with diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 741a4ec5586..70622c253d9 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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 int i386_operand PARAMS ((char *operand_string)); static reg_entry *parse_register PARAMS ((char *reg_string)); @@ -495,6 +560,15 @@ md_begin () record_alignment (bss_section, 2); #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 @@ -1085,6 +1159,32 @@ md_assemble (line) 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 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. Make sure there are more than 6 chars left in the current frag; if not we'll have to start a new one. */ - if (obstack_room (&frags) <= 6) - { - frag_wane (frag_now); - frag_new (0); - } + frag_grow (7); p = frag_more (1); insn_size += 1; p[0] = t->base_opcode; @@ -2374,8 +2470,9 @@ md_estimate_size_before_relax (fragP, segment) */ #ifndef BFD_ASSEMBLER void -md_convert_frag (headers, fragP) +md_convert_frag (headers, sec, fragP) object_headers *headers; + segT sec; register fragS *fragP; #else 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 we are handling. */ -static void -md_apply_fix_1 (fixP, value) - fixS *fixP; /* The fix we're to put in */ - long value; /* The value of the bits. */ +int +md_apply_fix3 (fixP, valp, seg) + fixS *fixP; /* The fix we're to put in. */ + 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; + valueT value = *valp; #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; #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 bfd_perform_relocation subtracts them out again. I think @@ -2606,26 +2706,9 @@ md_apply_fix_1 (fixP, value) #endif 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; } -#else -void -md_apply_fix (fixP, val) - fixS *fixP; - long val; -{ - md_apply_fix_1 (fixP, val); -} -#endif #if 0 /* This is never used. */ @@ -2731,7 +2814,7 @@ parse_register (reg_string) } #ifdef OBJ_ELF -CONST char *md_shortopts = "mVQ:"; +CONST char *md_shortopts = "kmVQ:"; #else CONST char *md_shortopts = "m"; #endif @@ -2752,6 +2835,10 @@ md_parse_option (c, arg) break; #ifdef OBJ_ELF + /* -k: Ignore for FreeBSD compatibility. */ + case 'k': + break; + /* -V: SVR4 argument to print version ID. */ case 'V': print_version_id (); @@ -2881,7 +2968,7 @@ tc_gen_reloc (section, fixp) MAP (4, 1, BFD_RELOC_32_PCREL); default: as_bad ("Can not do %d byte %srelocation", fixp->fx_size, - fixp->fx_pcrel ? "pc-relative" : ""); + fixp->fx_pcrel ? "pc-relative " : ""); } } #undef MAP @@ -2960,6 +3047,9 @@ short tc_coff_fix2rtype (fixP) fixS *fixP; { + if (fixP->fx_r_type == R_IMAGEBASE) + return R_IMAGEBASE; + return (fixP->fx_pcrel ? (fixP->fx_size == 1 ? R_PCRBYTE : fixP->fx_size == 2 ? R_PCRWORD : @@ -2982,5 +3072,100 @@ tc_coff_sizemachdep (frag) #endif /* I386COFF */ #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 */