aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog24
-rw-r--r--gas/config/tc-i386.c73
-rw-r--r--gas/config/tc-i386.h23
-rw-r--r--gas/doc/c-i386.texi19
4 files changed, 99 insertions, 40 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 81b29b7..9d39904 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,27 @@
+1999-08-04 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (i386_operand): No need to change
+ operand_string pointer in segment reg case before goto
+ do_memory_reference. Initialise displacement_string_start and
+ displacement_string_end after do_memory_reference label.
+ (i386_index_check): Add operand_string param, and print error
+ message on failure here.
+ (i386_intel_memory_operand): Instead of here.
+ (i386_operand): And here.
+ (INFER_ADDR_PREFIX): Enable.
+
+ * doc/c-i386.texi (i386-16bit): Document .code16gcc.
+
+ * config/tc-i386.h (DefaultSize): Define. Renumber following
+ opcode_modifier defines.
+
+ From Etienne Lorrain <etienne.lorrain@ibm.net>
+ * config/tc-i386.c (stackop_size): New variable.
+ (set_16bit_code_flag): Clear it here.
+ (set_16bit_gcc_code_flag): New function.
+ (md_pseudo_table): Add "code16gcc" entry.
+ (md_assemble): Set i.suffix for insns with DefaultSize modifier.
+
1999-08-03 Ian Lance Taylor <ian@zembu.com>
* config/obj-coff.c (coff_frob_symbol): Always update set_end with
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 8fb0aa7..5d60b4b 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -41,7 +41,7 @@
#endif
#ifndef INFER_ADDR_PREFIX
-#define INFER_ADDR_PREFIX 0
+#define INFER_ADDR_PREFIX 1
#endif
#ifndef SCALE1_WHEN_NO_INDEX
@@ -63,6 +63,7 @@ static int fits_in_signed_word PARAMS ((long));
static int smallest_imm_type PARAMS ((long));
static int add_prefix PARAMS ((unsigned int));
static void set_16bit_code_flag PARAMS ((int));
+static void set_16bit_gcc_code_flag PARAMS((int));
static void set_intel_syntax PARAMS ((int));
#ifdef BFD_ASSEMBLER
@@ -229,6 +230,10 @@ static int intel_syntax = 0; /* 1 for intel syntax, 0 if att syntax */
static int allow_naked_reg = 0; /* 1 if register prefix % not required */
+static char stackop_size = '\0'; /* Used in 16 bit gcc mode to add an l
+ suffix to call, ret, enter, leave, push,
+ and pop instructions. */
+
/* 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
@@ -516,14 +521,23 @@ add_prefix (prefix)
static void
set_16bit_code_flag (new_16bit_code_flag)
- int new_16bit_code_flag;
+ int new_16bit_code_flag;
+{
+ flag_16bit_code = new_16bit_code_flag;
+ stackop_size = '\0';
+}
+
+static void
+set_16bit_gcc_code_flag (new_16bit_code_flag)
+ int new_16bit_code_flag;
{
flag_16bit_code = new_16bit_code_flag;
+ stackop_size = new_16bit_code_flag ? 'l' : '\0';
}
static void
set_intel_syntax (syntax_flag)
- int syntax_flag;
+ int syntax_flag;
{
/* Find out if register prefixing is specified. */
int ask_naked_reg = 0;
@@ -575,6 +589,7 @@ const pseudo_typeS md_pseudo_table[] =
{"value", cons, 2},
{"noopt", s_ignore, 0},
{"optim", s_ignore, 0},
+ {"code16gcc", set_16bit_gcc_code_flag, 1},
{"code16", set_16bit_code_flag, 1},
{"code32", set_16bit_code_flag, 0},
{"intel_syntax", set_intel_syntax, 1},
@@ -1632,6 +1647,10 @@ md_assemble (line)
else
abort();
}
+ else if ((i.tm.opcode_modifier & DefaultSize) && !i.suffix)
+ {
+ i.suffix = stackop_size;
+ }
/* Make still unresolved immediate matches conform to size of immediate
given in i.suffix. Note: overlap2 cannot be an immediate! */
@@ -3064,13 +3083,18 @@ i386_parse_seg (op_string)
}
-static int i386_index_check PARAMS((void));
+static int i386_index_check PARAMS((const char *));
+/* Make sure the memory operand we've been dealt is valid.
+ Returns 1 on success, 0 on a failure.
+*/
static int
-i386_index_check ()
+i386_index_check (operand_string)
+ const char *operand_string;
{
- /* Make sure the memory operand we've been dealt is valid. */
#if INFER_ADDR_PREFIX
+ int fudged = 0;
+
tryprefix:
#endif
if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0) ?
@@ -3093,15 +3117,22 @@ i386_index_check ()
!= (Reg32|BaseIndex)))))
{
#if INFER_ADDR_PREFIX
- if (i.prefix[ADDR_PREFIX] == 0)
+ if (i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0')
{
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
i.prefixes += 1;
+ fudged = 1;
goto tryprefix;
}
- else
#endif
- return 0;
+ if (fudged)
+ as_bad (_("`%s' is not a valid base/index expression"),
+ operand_string);
+ else
+ as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ operand_string,
+ flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0) ? "16" : "32");
+ return 0;
}
return 1;
}
@@ -3240,12 +3271,8 @@ i386_intel_memory_operand (operand_string)
}
}
- if (i386_index_check () == 0)
- {
- as_bad (_("`%s' is not a valid base/index expression"),
- operand_string);
- return 0;
- }
+ if (i386_index_check (operand_string) == 0)
+ return 0;
i.mem_operands++;
return 1;
@@ -3411,8 +3438,6 @@ i386_operand (operand_string)
if (is_space_char (*op_string))
++op_string;
- /* Pretend given string starts here. */
- operand_string = op_string;
if (!is_digit_char (*op_string)
&& !is_identifier_char (*op_string)
&& *op_string != '('
@@ -3461,10 +3486,12 @@ i386_operand (operand_string)
int found_base_index_form;
/* Start and end of displacement string expression (if found). */
- char *displacement_string_start = NULL;
- char *displacement_string_end = NULL;
+ char *displacement_string_start;
+ char *displacement_string_end;
do_memory_reference:
+ displacement_string_start = NULL;
+ displacement_string_end = NULL;
if ((i.mem_operands == 1
&& (current_templates->start->opcode_modifier & IsString) == 0)
@@ -3638,12 +3665,8 @@ i386_operand (operand_string)
return 1;
}
- if (i386_index_check () == 0)
- {
- as_bad (_("`%s' is not a valid base/index expression"),
- operand_string);
- return 0;
- }
+ if (i386_index_check (operand_string) == 0)
+ return 0;
i.mem_operands++;
}
else
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index ef778c1..41ebb86 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -344,17 +344,18 @@ typedef struct
#define Size16 0x2000 /* needs size prefix if in 32-bit mode */
#define Size32 0x4000 /* needs size prefix if in 16-bit mode */
#define IgnoreSize 0x8000 /* instruction ignores operand size prefix */
-#define No_bSuf 0x10000 /* b suffix on instruction illegal */
-#define No_wSuf 0x20000 /* w suffix on instruction illegal */
-#define No_lSuf 0x40000 /* l suffix on instruction illegal */
-#define No_sSuf 0x80000 /* s suffix on instruction illegal */
-#define No_dSuf 0x100000 /* d suffix on instruction illegal */
-#define No_xSuf 0x200000 /* x suffix on instruction illegal */
-#define FWait 0x400000 /* instruction needs FWAIT */
-#define IsString 0x800000 /* quick test for string instructions */
-#define regKludge 0x1000000 /* fake an extra reg operand for clr, imul */
-#define IsPrefix 0x2000000 /* opcode is a prefix */
-#define ImmExt 0x4000000 /* instruction has extension in 8 bit imm */
+#define DefaultSize 0x10000 /* default insn size depends on mode */
+#define No_bSuf 0x20000 /* b suffix on instruction illegal */
+#define No_wSuf 0x40000 /* w suffix on instruction illegal */
+#define No_lSuf 0x80000 /* l suffix on instruction illegal */
+#define No_sSuf 0x100000 /* s suffix on instruction illegal */
+#define No_dSuf 0x200000 /* d suffix on instruction illegal */
+#define No_xSuf 0x400000 /* x suffix on instruction illegal */
+#define FWait 0x800000 /* instruction needs FWAIT */
+#define IsString 0x1000000 /* quick test for string instructions */
+#define regKludge 0x2000000 /* fake an extra reg operand for clr, imul */
+#define IsPrefix 0x4000000 /* opcode is a prefix */
+#define ImmExt 0x8000000 /* instruction has extension in 8 bit imm */
#define Ugh 0x80000000 /* deprecated fp insn, gets a warning */
/* operand_types[i] describes the type of operand i. This is made
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index e27893b..8a9c85a 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -443,14 +443,25 @@ instructions is reversed from the Intel syntax.
@cindex i386 16-bit code
@cindex 16-bit code, i386
@cindex real-mode code, i386
+@cindex @code{code16gcc} directive, i386
@cindex @code{code16} directive, i386
@cindex @code{code32} directive, i386
While @code{@value{AS}} normally writes only ``pure'' 32-bit i386 code,
it also supports writing code to run in real mode or in 16-bit protected
-mode code segments. To do this, put a @samp{.code16} directive before
-the assembly language instructions to be run in 16-bit mode. You can
-switch @code{@value{AS}} back to writing normal 32-bit code with the
-@samp{.code32} directive.
+mode code segments. To do this, put a @samp{.code16} or
+@samp{.code16gcc} directive before the assembly language instructions to
+be run in 16-bit mode. You can switch @code{@value{AS}} back to writing
+normal 32-bit code with the @samp{.code32} directive.
+
+@samp{.code16gcc} provides experimental support for generating 16-bit
+code from gcc, and differs from @samp{.code16} in that @samp{call},
+@samp{ret}, @samp{enter}, @samp{leave}, @samp{push}, @samp{pop},
+@samp{pusha}, @samp{popa}, @samp{pushf}, and @samp{popf} instructions
+default to 32-bit size. This is so that the stack pointer is
+manipulated in the same way over function calls, allowing access to
+function parameters at the same stack offsets as in 32-bit mode.
+@samp{.code16gcc} also automatically adds address size prefixes where
+necessary to use the 32-bit addressing modes that gcc generates.
The code which @code{@value{AS}} generates in 16-bit mode will not
necessarily run on a 16-bit pre-80386 processor. To write code that