aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@cygnus>1995-02-06 08:53:05 +0000
committerKen Raeburn <raeburn@cygnus>1995-02-06 08:53:05 +0000
commitc54c7aaca32b90863494b8c3b7a02b3bb2f69f23 (patch)
tree3e682b89c42cb0eb7ffc01c5ef88548ad1c70ea3 /gas
parenta43022bd720336020cb7b8454504276fe9615b82 (diff)
downloadgdb-c54c7aaca32b90863494b8c3b7a02b3bb2f69f23.zip
gdb-c54c7aaca32b90863494b8c3b7a02b3bb2f69f23.tar.gz
gdb-c54c7aaca32b90863494b8c3b7a02b3bb2f69f23.tar.bz2
Bryan Ford's changes for 16-bit i386 support, and i386-msdos support.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog17
-rw-r--r--gas/config/tc-i386.c215
-rwxr-xr-xgas/configure35
-rw-r--r--gas/configure.in4
4 files changed, 206 insertions, 65 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 7e341f4..47ee337 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 8ccb17f..2dc4252 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -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
@@ -683,9 +689,15 @@ reloc (size, pcrel, other)
tc_i386_fix_adjustable(fixP)
fixS * fixP;
{
- /* Prevent all adjustments to global symbols. */
- if(!S_IS_LOCAL(fixP->fx_addsy)) return 0;
- return 1;
+ /* Prevent all adjustments to global symbols. */
+ 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;
}
/* This is the guts of the machine-dependent assembler. LINE points to a
@@ -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))
- section_symbol(exp->X_add_symbol->bsym->section);
+ 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
diff --git a/gas/configure b/gas/configure
index 5f64a00..f71ea7c 100755
--- a/gas/configure
+++ b/gas/configure
@@ -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
diff --git a/gas/configure.in b/gas/configure.in
index 2070e9c..9da3b1b 100644
--- a/gas/configure.in
+++ b/gas/configure.in
@@ -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*)