#endif
#ifndef INFER_ADDR_PREFIX
-#define INFER_ADDR_PREFIX 0
+#define INFER_ADDR_PREFIX 1
#endif
#ifndef SCALE1_WHEN_NO_INDEX
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
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
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;
{"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},
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! */
}
-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) ?
!= (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;
}
}
}
- 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;
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 != '('
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)
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
{"movzx", 2, 0x0fb6, X, b_Suf|Modrm, { Reg8|ByteMem, WordReg, 0} },
/* push instructions */
-{"push", 1, 0x50, X, wl_Suf|ShortForm, { WordReg, 0, 0 } },
-{"push", 1, 0xff, 6, wl_Suf|Modrm, { WordReg|WordMem, 0, 0 } },
-{"push", 1, 0x6a, X, wl_Suf, { Imm8S, 0, 0} },
-{"push", 1, 0x68, X, wl_Suf, { Imm16|Imm32, 0, 0} },
-{"push", 1, 0x06, X, wl_Suf|Seg2ShortForm, { SReg2, 0, 0 } },
-{"push", 1, 0x0fa0, X, wl_Suf|Seg3ShortForm, { SReg3, 0, 0 } },
+{"push", 1, 0x50, X, wl_Suf|ShortForm|DefaultSize, { WordReg, 0, 0 } },
+{"push", 1, 0xff, 6, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem, 0, 0 } },
+{"push", 1, 0x6a, X, wl_Suf|DefaultSize, { Imm8S, 0, 0} },
+{"push", 1, 0x68, X, wl_Suf|DefaultSize, { Imm16|Imm32, 0, 0} },
+{"push", 1, 0x06, X, wl_Suf|Seg2ShortForm|DefaultSize, { SReg2, 0, 0 } },
+{"push", 1, 0x0fa0, X, wl_Suf|Seg3ShortForm|DefaultSize, { SReg3, 0, 0 } },
/* push all */
-{"pusha", 0, 0x60, X, wl_Suf, { 0, 0, 0 } },
+{"pusha", 0, 0x60, X, wl_Suf|DefaultSize, { 0, 0, 0 } },
/* pop instructions */
-{"pop", 1, 0x58, X, wl_Suf|ShortForm, { WordReg, 0, 0 } },
-{"pop", 1, 0x8f, 0, wl_Suf|Modrm, { WordReg|WordMem, 0, 0 } },
+{"pop", 1, 0x58, X, wl_Suf|ShortForm|DefaultSize, { WordReg, 0, 0 } },
+{"pop", 1, 0x8f, 0, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem, 0, 0 } },
#define POP_SEG_SHORT 0x07
-{"pop", 1, 0x07, X, wl_Suf|Seg2ShortForm, { SReg2, 0, 0 } },
-{"pop", 1, 0x0fa1, X, wl_Suf|Seg3ShortForm, { SReg3, 0, 0 } },
+{"pop", 1, 0x07, X, wl_Suf|Seg2ShortForm|DefaultSize, { SReg2, 0, 0 } },
+{"pop", 1, 0x0fa1, X, wl_Suf|Seg3ShortForm|DefaultSize, { SReg3, 0, 0 } },
/* pop all */
-{"popa", 0, 0x61, X, wl_Suf, { 0, 0, 0 } },
+{"popa", 0, 0x61, X, wl_Suf|DefaultSize, { 0, 0, 0 } },
/* xchg exchange instructions
xchg commutes: we allow both operand orders */
{"cmc", 0, 0xf5, X, NoSuf, { 0, 0, 0} },
{"lahf", 0, 0x9f, X, NoSuf, { 0, 0, 0} },
{"sahf", 0, 0x9e, X, NoSuf, { 0, 0, 0} },
-{"pushf", 0, 0x9c, X, wl_Suf, { 0, 0, 0} },
-{"popf", 0, 0x9d, X, wl_Suf, { 0, 0, 0} },
+{"pushf", 0, 0x9c, X, wl_Suf|DefaultSize, { 0, 0, 0} },
+{"popf", 0, 0x9d, X, wl_Suf|DefaultSize, { 0, 0, 0} },
{"stc", 0, 0xf9, X, NoSuf, { 0, 0, 0} },
{"std", 0, 0xfd, X, NoSuf, { 0, 0, 0} },
{"sti", 0, 0xfb, X, NoSuf, { 0, 0, 0} },
{"sar", 1, 0xd0, 7, bwl_Suf|W|Modrm, { Reg|AnyMem, 0, 0} },
/* control transfer instructions */
-{"call", 1, 0xe8, X, wl_Suf|JumpDword, { Disp16|Disp32, 0, 0} },
-{"call", 1, 0xff, 2, wl_Suf|Modrm, { WordReg|WordMem|JumpAbsolute, 0, 0} },
+{"call", 1, 0xe8, X, wl_Suf|JumpDword|DefaultSize, { Disp16|Disp32, 0, 0} },
+{"call", 1, 0xff, 2, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem|JumpAbsolute, 0, 0} },
/* Intel Syntax */
-{"call", 2, 0x9a, X, wl_Suf|JumpInterSegment, { Imm16, Imm16|Imm32, 0} },
-{"lcall", 2, 0x9a, X, wl_Suf|JumpInterSegment, { Imm16, Imm16|Imm32, 0} },
-{"lcall", 1, 0xff, 3, wl_Suf|Modrm, { WordMem, 0, 0} },
+{"call", 2, 0x9a, X, wl_Suf|JumpInterSegment|DefaultSize, { Imm16, Imm16|Imm32, 0} },
+{"lcall", 2, 0x9a, X, wl_Suf|JumpInterSegment|DefaultSize, { Imm16, Imm16|Imm32, 0} },
+{"lcall", 1, 0xff, 3, wl_Suf|Modrm|DefaultSize, { WordMem, 0, 0} },
#define JUMP_PC_RELATIVE 0xeb
{"jmp", 1, 0xeb, X, NoSuf|Jump, { Disp, 0, 0} },
{"ljmp", 2, 0xea, X, wl_Suf|JumpInterSegment, { Imm16, Imm16|Imm32, 0} },
{"ljmp", 1, 0xff, 5, wl_Suf|Modrm, { WordMem, 0, 0} },
-{"ret", 0, 0xc3, X, wl_Suf, { 0, 0, 0} },
-{"ret", 1, 0xc2, X, wl_Suf, { Imm16, 0, 0} },
-{"lret", 0, 0xcb, X, wl_Suf, { 0, 0, 0} },
-{"lret", 1, 0xca, X, wl_Suf, { Imm16, 0, 0} },
-{"enter", 2, 0xc8, X, wl_Suf, { Imm16, Imm8, 0} },
-{"leave", 0, 0xc9, X, wl_Suf, { 0, 0, 0} },
+{"ret", 0, 0xc3, X, wl_Suf|DefaultSize, { 0, 0, 0} },
+{"ret", 1, 0xc2, X, wl_Suf|DefaultSize, { Imm16, 0, 0} },
+{"lret", 0, 0xcb, X, wl_Suf|DefaultSize, { 0, 0, 0} },
+{"lret", 1, 0xca, X, wl_Suf|DefaultSize, { Imm16, 0, 0} },
+{"enter", 2, 0xc8, X, wl_Suf|DefaultSize, { Imm16, Imm8, 0} },
+{"leave", 0, 0xc9, X, wl_Suf|DefaultSize, { 0, 0, 0} },
/* conditional jumps */
{"jo", 1, 0x70, X, NoSuf|Jump, { Disp, 0, 0} },
#undef b_Suf
#undef w_Suf
#undef l_Suf
+#undef d_Suf
+#undef x_Suf
#undef bw_Suf
#undef bl_Suf
#undef wl_Suf
#undef sl_Suf
+#undef sld_Suf
+#undef sldx_Suf
#undef bwl_Suf
+#undef bwld_Suf
#undef FP
#undef l_FP
+#undef d_FP
+#undef x_FP
#undef sl_FP
+#undef sld_FP
+#undef sldx_FP
#define MAX_MNEM_SIZE 16 /* for parsing insn mnemonics from input */