Bryan Ford's changes for 16-bit i386 support, and i386-msdos support.

This commit is contained in:
Ken Raeburn 1995-02-06 08:53:05 +00:00
parent a43022bd72
commit c54c7aaca3
4 changed files with 206 additions and 65 deletions

View File

@ -1,3 +1,20 @@
Mon Feb 6 03:37:00 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
Changes from Bryan Ford <baford@schirf.cs.utah.edu> for i386
16-bit and msdos support:
* config/tc-i386.c (flag_16bit_code): New variable.
(set_16bit_code_flag): New function.
(md_pseudo_table): Added entries "code16" and "code32".
(md_assemble): Ensure that correct data-size prefixes get emitted,
based on the current mode. Ensure that 32-bit addressing will
always be done. Move segment-prefix handling code. (Why?) Use
16-bit jumps for 16-bit code, 32-bit jumps for 32-bit code.
* config/tc-i386.h (MAX_PREFIXES): Bump to 5.
(Data16, Data32): Define.
* doc/as.texinfo (i386-16bit): New node.
* configure.in (i386-*-msdos*): New target, using a.out format.
* configure: Regenerated.
Thu Feb 2 15:21:24 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
* config/tc-m68k.c (cpu32_control_regs): New macro.

View File

@ -174,6 +174,8 @@ static int this_operand; /* current operand we are working on */
static int flag_do_long_jump; /* FIXME what does this do? */
static int flag_16bit_code; /* 1 if we're writing 16-bit code, 0 if 32-bit */
/* Interface to relax_segment.
There are 2 relax states for 386 jump insns: one for conditional &
one for unconditional jumps. This is because the these two types
@ -318,6 +320,12 @@ smallest_imm_type (num)
: (Imm32));
} /* smallest_imm_type() */
void set_16bit_code_flag(new_16bit_code_flag)
int new_16bit_code_flag;
{
flag_16bit_code = new_16bit_code_flag;
}
const pseudo_typeS md_pseudo_table[] =
{
#ifndef I386COFF
@ -334,6 +342,8 @@ const pseudo_typeS md_pseudo_table[] =
{"value", cons, 2},
{"noopt", s_ignore, 0},
{"optim", s_ignore, 0},
{"code16", set_16bit_code_flag, 1},
{"code32", set_16bit_code_flag, 0},
{0, 0, 0}
};
@ -645,24 +655,20 @@ reloc (size, pcrel, other)
if (pcrel)
switch (size)
{
#ifndef OBJ_ELF
case 1: return BFD_RELOC_8_PCREL;
case 2: return BFD_RELOC_16_PCREL;
#endif
case 4: return BFD_RELOC_32_PCREL;
}
else
switch (size)
{
#ifndef OBJ_ELF
case 1: return BFD_RELOC_8;
case 2: return BFD_RELOC_16;
#endif
case 4: return BFD_RELOC_32;
}
as_bad ("Can not do %d byte %srelocation", size,
pcrel ? "pc-relative" : "");
pcrel ? "pc-relative " : "");
return BFD_RELOC_NONE;
}
#else
@ -684,7 +690,13 @@ tc_i386_fix_adjustable(fixP)
fixS * fixP;
{
/* Prevent all adjustments to global symbols. */
if(!S_IS_LOCAL(fixP->fx_addsy)) return 0;
if (!S_IS_LOCAL (fixP->fx_addsy))
return 0;
#ifdef BFD_ASSEMBLER
/* adjust_reloc_syms doesn't know about the GOT */
if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF)
return 0;
#endif
return 1;
}
@ -1032,6 +1044,21 @@ md_assemble (line)
i.tm = *t;
t = &i.tm; /* alter new copy of template */
/* If the matched instruction specifies an explicit opcode suffix,
use it - and make sure none has already been specified. */
if (t->opcode_modifier & (Data16|Data32))
{
if (i.suffix)
{
as_bad ("extraneous opcode suffix given");
return;
}
if (t->opcode_modifier & Data16)
i.suffix = WORD_OPCODE_SUFFIX;
else
i.suffix = DWORD_OPCODE_SUFFIX;
}
/* If there's no opcode suffix we try to invent one based on register
operands. */
if (!i.suffix && i.reg_operands)
@ -1115,7 +1142,7 @@ md_assemble (line)
t->base_opcode |= W;
/* Now select between word & dword operations via the
operand size prefix. */
if (i.suffix == WORD_OPCODE_SUFFIX)
if ((i.suffix == WORD_OPCODE_SUFFIX) ^ flag_16bit_code)
{
if (i.prefixes == MAX_PREFIXES)
{
@ -1130,6 +1157,16 @@ md_assemble (line)
/* For insns with operands there are more diddles to do to the opcode. */
if (i.operands)
{
/* Default segment register this instruction will use
for memory accesses. 0 means unknown.
This is only for optimizing out unnecessary segment overrides. */
const seg_entry *default_seg = 0;
/* True if this instruction uses a memory addressing mode,
and therefore may need an address-size prefix. */
int uses_mem_addrmode = 0;
/* If we found a reverse match we must alter the opcode direction bit
found_reverse_match holds bit to set (different for int &
float insns). */
@ -1195,6 +1232,14 @@ md_assemble (line)
if (i.regs[0]->reg_num == 5)
t->base_opcode |= 0x08;
}
else if ((t->base_opcode & ~DW) == MOV_AX_DISP32)
{
/* This is a special non-modrm instruction
that addresses memory with a 32-bit displacement mode anyway,
and thus requires an address-size prefix if in 16-bit mode. */
uses_mem_addrmode = 1;
default_seg = &ds;
}
else if (t->opcode_modifier & Modrm)
{
/* The opcode is completed (modulo t->extension_opcode which must
@ -1323,11 +1368,11 @@ md_assemble (line)
exp->X_op_symbol = (symbolS *) 0;
}
/* Select the correct segment for the memory operand. */
/* Find the default segment for the memory operand.
Used to optimize out explicit segment specifications. */
if (i.seg)
{
unsigned int seg_index;
const seg_entry *default_seg;
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING)
{
@ -1339,18 +1384,6 @@ md_assemble (line)
seg_index = (i.rm.mode << 3) | i.rm.regmem;
default_seg = one_byte_segment_defaults[seg_index];
}
/* If the specified segment is not the default, use an
opcode prefix to select it */
if (i.seg != default_seg)
{
if (i.prefixes == MAX_PREFIXES)
{
as_bad ("%d prefixes given and %s segment override gives too many prefixes",
MAX_PREFIXES, i.seg->seg_name);
return;
}
i.prefix[i.prefixes++] = i.seg->seg_prefix;
}
}
}
@ -1381,6 +1414,40 @@ md_assemble (line)
if (t->extension_opcode != None)
i.rm.reg = t->extension_opcode;
}
if (i.rm.mode != 3)
uses_mem_addrmode = 1;
}
/* GAS currently doesn't support 16-bit memory addressing modes at all,
so if we're writing 16-bit code and using a memory addressing mode,
always spew out an address size prefix. */
if (uses_mem_addrmode && flag_16bit_code)
{
if (i.prefixes == MAX_PREFIXES)
{
as_bad ("%d prefixes given and address size override gives too many prefixes",
MAX_PREFIXES);
return;
}
i.prefix[i.prefixes++] = ADDR_PREFIX_OPCODE;
}
/* If a segment was explicitly specified,
and the specified segment is not the default,
use an opcode prefix to select it.
If we never figured out what the default segment is,
then default_seg will be zero at this point,
and the specified segment prefix will always be used. */
if ((i.seg) && (i.seg != default_seg))
{
if (i.prefixes == MAX_PREFIXES)
{
as_bad ("%d prefixes given and %s segment override gives too many prefixes",
MAX_PREFIXES, i.seg->seg_name);
return;
}
i.prefix[i.prefixes++] = i.seg->seg_prefix;
}
}
}
@ -1410,39 +1477,47 @@ md_assemble (line)
p[0] = t->base_opcode;
p[1] = n;
}
#if 0 /* leave out 16 bit jumps - pace */
else if (fits_in_signed_word (n))
{
p = frag_more (4);
insn_size += 4;
p[0] = WORD_PREFIX_OPCODE;
p[1] = t->base_opcode;
md_number_to_chars (&p[2], (valueT) n, 2);
}
#endif
else
{ /* It's an absolute dword displacement. */
{ /* It's an absolute word/dword displacement. */
/* Use only 16-bit jumps for 16-bit code,
because text segments are limited to 64K anyway;
use only 32-bit jumps for 32-bit code,
because they're faster. */
int jmp_size = flag_16bit_code ? 2 : 4;
if (flag_16bit_code && !fits_in_signed_word (n))
{
as_bad ("16-bit jump out of range");
return;
}
if (t->base_opcode == JUMP_PC_RELATIVE)
{ /* pace */
/* unconditional jump */
p = frag_more (5);
insn_size += 5;
p = frag_more (1 + jmp_size);
insn_size += 1 + jmp_size;
p[0] = (char) 0xe9;
md_number_to_chars (&p[1], (valueT) n, 4);
md_number_to_chars (&p[1], (valueT) n, jmp_size);
}
else
{
/* conditional jump */
p = frag_more (6);
insn_size += 6;
p = frag_more (2 + jmp_size);
insn_size += 2 + jmp_size;
p[0] = TWO_BYTE_OPCODE_ESCAPE;
p[1] = t->base_opcode + 0x10;
md_number_to_chars (&p[2], (valueT) n, 4);
md_number_to_chars (&p[2], (valueT) n, jmp_size);
}
}
}
else
{
if (flag_16bit_code)
{
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
insn_size += 1;
}
/* 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. */
@ -1468,6 +1543,24 @@ md_assemble (line)
{
int size = (t->opcode_modifier & JumpByte) ? 1 : 4;
unsigned long n = i.disps[0]->X_add_number;
unsigned char *q;
/* The jcx/jecx instruction might need a data size prefix. */
for (q = i.prefix; q < i.prefix + i.prefixes; q++)
{
if (*q == WORD_PREFIX_OPCODE)
{
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
insn_size += 1;
break;
}
}
if ((size == 4) && (flag_16bit_code))
{
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
insn_size += 1;
}
if (fits_in_unsigned_byte (t->base_opcode))
{
@ -1503,6 +1596,12 @@ md_assemble (line)
}
else if (t->opcode_modifier & JumpInterSegment)
{
if (flag_16bit_code)
{
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
insn_size += 1;
}
p = frag_more (1 + 2 + 4); /* 1 opcode; 2 segment; 4 offset */
insn_size += 1 + 2 + 4;
p[0] = t->base_opcode;
@ -1688,7 +1787,7 @@ md_assemble (line)
p = frag_more (size);
insn_size += size;
#ifdef BFD_ASSEMBLER
if (r_type = BFD_RELOC_32
if (r_type == BFD_RELOC_32
&& i.imms[n]->X_op == O_symbol
&& GOT_symbol
&& GOT_symbol == i.imms[n]->X_add_symbol)
@ -2095,9 +2194,16 @@ i386_operand (operand_string)
/* We do this to make sure that the section symbol is in
the symbol table. We will ultimately change the relocation
to be relative to the beginning of the section */
if(i.disp_reloc[this_operand] == BFD_RELOC_386_GOTOFF &&
S_IS_LOCAL(exp->X_add_symbol))
if (i.disp_reloc[this_operand] == BFD_RELOC_386_GOTOFF)
{
if (S_IS_LOCAL(exp->X_add_symbol)
&& S_GET_SEGMENT (exp->X_add_symbol) != undefined_section)
section_symbol(exp->X_add_symbol->bsym->section);
assert (exp->X_op == O_symbol);
exp->X_op = O_subtract;
exp->X_op_symbol = GOT_symbol;
i.disp_reloc[this_operand] = BFD_RELOC_32;
}
#endif
if (*input_line_pointer)
@ -2426,7 +2532,7 @@ md_apply_fix_1 (fixP, value)
/* Fix a few things - the dynamic linker expects certain values here,
and we must not dissappoint it. */
#ifdef OBJ_ELF
if(fixP->fx_addsy)
if (fixP->fx_addsy)
switch(fixP->fx_r_type) {
case BFD_RELOC_386_PLT32:
/* Make the jump instruction point to the address of the operand. At
@ -2472,13 +2578,14 @@ md_apply_fix_1 (fixP, value)
* the pcrel_adjust field was used to store the correction, but since the
* expression is not pcrel, I felt it would be confusing to do it this way.
*/
value += fixP->fx_where + fixP->fx_frag->fr_address - fixP->fx_offset;
value -= 1;
break;
case BFD_RELOC_386_GOT32:
value = 0; /* Fully resolved at runtime. No addend. */
break;
case BFD_RELOC_386_GOTOFF:
/* Here everything should be correct already. Just wanted to mention
this explicitly so no one things I forgot it. */
break;
default:
break;
}
@ -2726,6 +2833,18 @@ s_bss (ignore)
#ifdef BFD_ASSEMBLER
void
i386_validate_fix (fixp)
fixS *fixp;
{
if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol)
{
fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
fixp->fx_subsy = 0;
}
}
#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break

35
gas/configure vendored
View File

@ -616,6 +616,7 @@ case ${generic_target} in
i386-*-gnu*elf*) obj_format=elf ;;
i386-*-mach* | i386-*-gnu*)
obj_format=aout emulation=mach bfd_gas=yes ;;
i386-*-msdos*) obj_format=aout ;;
i960-*-bout) obj_format=bout ;;
i960-*-coff) obj_format=coff emulation=ic960 gas_target=ic960coff ;;
@ -922,7 +923,7 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 926 "configure"
#line 927 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
@ -936,7 +937,7 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 940 "configure"
#line 941 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
@ -967,7 +968,7 @@ if eval "test \"`echo '${'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 971 "configure"
#line 972 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
@ -1019,7 +1020,7 @@ else
ac_cv_cross=yes
else
cat > conftest.$ac_ext <<EOF
#line 1023 "configure"
#line 1024 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
@ -1042,7 +1043,7 @@ if eval "test \"`echo '${'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1046 "configure"
#line 1047 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() { return 0; }
@ -1073,7 +1074,7 @@ if eval "test \"`echo '${'ac_cv_func_alloca'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1077 "configure"
#line 1078 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@ -1131,7 +1132,7 @@ if eval "test \"`echo '${'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1135 "configure"
#line 1136 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@ -1158,7 +1159,7 @@ if eval "test \"`echo '${'ac_cv_func__getb67'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1162 "configure"
#line 1163 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error. */
@ -1201,7 +1202,7 @@ if eval "test \"`echo '${'ac_cv_func_GETB67'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1205 "configure"
#line 1206 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error. */
@ -1244,7 +1245,7 @@ if eval "test \"`echo '${'ac_cv_func_getb67'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1248 "configure"
#line 1249 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error. */
@ -1298,7 +1299,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
#line 1302 "configure"
#line 1303 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@ -1339,7 +1340,7 @@ if eval "test \"`echo '${'ac_cv_c_inline'+set}'`\" = set"; then
else
if test "$GCC" = yes; then
cat > conftest.$ac_ext <<EOF
#line 1343 "configure"
#line 1344 "configure"
#include "confdefs.h"
int main() { return 0; }
@ -1377,7 +1378,7 @@ if eval "test \"`echo '${'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1381 "configure"
#line 1382 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error. */
@ -1428,7 +1429,7 @@ if eval "test \"`echo '${'gas_cv_assert_ok'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1432 "configure"
#line 1433 "configure"
#include "confdefs.h"
#include <assert.h>
#include <stdio.h>
@ -1485,7 +1486,7 @@ if eval "test \"`echo '${'gas_cv_decl_needed_malloc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1489 "configure"
#line 1490 "configure"
#include "confdefs.h"
$gas_test_headers
int main() { return 0; }
@ -1521,7 +1522,7 @@ if eval "test \"`echo '${'gas_cv_decl_needed_free'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1525 "configure"
#line 1526 "configure"
#include "confdefs.h"
$gas_test_headers
int main() { return 0; }
@ -1560,7 +1561,7 @@ if eval "test \"`echo '${'gas_cv_decl_needed_errno'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4
else
cat > conftest.$ac_ext <<EOF
#line 1564 "configure"
#line 1565 "configure"
#include "confdefs.h"
#ifdef HAVE_ERRNO_H

View File

@ -102,8 +102,10 @@ case ${generic_target} in
obj_format=coff gas_target=i386coff ;;
i386-*-vsta) obj_format=aout ;;
i386-*-go32) obj_format=coff gas_target=i386coff ;;
i386-*-gnu*elf*) obj_format=elf ;;
i386-*-mach* | i386-*-gnu*)
obj_format=aout emulation=mach bfd_gas=yes ;;
i386-*-msdos*) obj_format=aout ;;
i960-*-bout) obj_format=bout ;;
i960-*-coff) obj_format=coff emulation=ic960 gas_target=ic960coff ;;
@ -186,6 +188,8 @@ case ${generic_target} in
z8k-*-coff | z8k-*-sim)
obj_format=coff ;;
w65-*-*) obj_format=coff ;;
*-*-aout | *-*-scout)
obj_format=aout ;;
*-*-nindy*)