diff options
author | Alan Modra <amodra@gmail.com> | 1999-08-03 05:47:26 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 1999-08-03 05:47:26 +0000 |
commit | c3332e24e81df74a8f62966dfa4b5f475a20523e (patch) | |
tree | 8d54bb4048dbfa12051053d7c924ff3b666a77a8 | |
parent | a0b3c4fd32cf8336bf7b69f373ef86d5c54035f6 (diff) | |
download | fsf-binutils-gdb-c3332e24e81df74a8f62966dfa4b5f475a20523e.zip fsf-binutils-gdb-c3332e24e81df74a8f62966dfa4b5f475a20523e.tar.gz fsf-binutils-gdb-c3332e24e81df74a8f62966dfa4b5f475a20523e.tar.bz2 |
* config/tc-i386.c: Add INFER_ADDR_PREFIX code. Fix 16 bit mode nop.
-rw-r--r-- | gas/ChangeLog | 9 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 822 |
2 files changed, 436 insertions, 395 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 244750c..d9e3666 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +1999-08-03 Etienne Lorrain <etienne.lorrain@ibm.net> + + * config/tc-i386.c (f16_3): New. Fixes 16 bit 3 byte nop. + +1999-08-03 Alan Modra <alan@spri.levels.unisa.edu.au> + + * config/tc-i386.c (i386_operand): Add INFER_ADDR_PREFIX code, but + don't enable it by default. White space changes. + 1999-07-30 Jakub Jelinek <jj@ultra.linux.cz> * config/tc-sparc.c (md_longopts): Add --no-undeclared-regs option. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 524819e..941b4bc 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -40,6 +40,10 @@ #define REGISTER_WARNINGS 1 #endif +#ifndef INFER_ADDR_PREFIX +#define INFER_ADDR_PREFIX 0 +#endif + #ifndef SCALE1_WHEN_NO_INDEX /* Specifying a scale factor besides 1 when there is no index is futile. eg. `mov (%ebx,2),%al' does exactly the same as @@ -343,6 +347,8 @@ i386_align_code (fragP, count) static const char f32_15[] = {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; + static const char f16_3[] = + {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ static const char f16_4[] = {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ static const char f16_5[] = @@ -362,7 +368,7 @@ i386_align_code (fragP, count) 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_1, f32_2, f16_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 }; @@ -537,14 +543,14 @@ set_intel_syntax (syntax_flag) *input_line_pointer = e; } demand_empty_rest_of_line (); - + intel_syntax = syntax_flag; if (ask_naked_reg == 0) { #ifdef BFD_ASSEMBLER allow_naked_reg = (intel_syntax - && (bfd_get_symbol_leading_char (stdoutput) != '\0')); + && (bfd_get_symbol_leading_char (stdoutput) != '\0')); #else allow_naked_reg = 0; /* conservative default */ #endif @@ -1286,7 +1292,7 @@ md_assemble (line) temp_imm = i.imms[xchg2]; else if (temp_type & Disp) temp_disp = i.disps[xchg2]; - + i.types[xchg2] = i.types[xchg1]; if (i.types[xchg1] & (Reg | FloatReg)) @@ -1330,7 +1336,7 @@ md_assemble (line) || !strcmp (mnemonic, "call")) if ((i.types[0] & Reg) || i.types[0] & BaseIndex) i.types[0] |= JumpAbsolute; - + } overlap0 = 0; overlap1 = 0; @@ -1343,9 +1349,9 @@ md_assemble (line) : (i.suffix == SHORT_MNEM_SUFFIX ? No_sSuf : (i.suffix == LONG_MNEM_SUFFIX - ? No_lSuf - : (i.suffix == INTEL_DWORD_MNEM_SUFFIX - ? No_dSuf + ? No_lSuf + : (i.suffix == INTEL_DWORD_MNEM_SUFFIX + ? No_dSuf : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX ? No_xSuf : 0)))))); for (t = current_templates->start; @@ -1364,7 +1370,7 @@ md_assemble (line) && (t->opcode_modifier & suffix_check)) continue; } - /* Must not have disallowed suffix. */ + /* Must not have disallowed suffix. */ else if ((t->opcode_modifier & suffix_check)) continue; @@ -2511,7 +2517,7 @@ i386_is_reg (reg_string) else return 1; } - + static int i386_immediate PARAMS ((char *)); static int @@ -2935,7 +2941,7 @@ i386_operand_modifier (op_string, got_a_float) } else return NONE_FOUND; -} +} static char * build_displacement_string PARAMS ((int, char *)); @@ -2964,7 +2970,7 @@ build_displacement_string (initial_disp, op_string) temp_string[end_of_operand_string - op_string] = '\0'; temp_disp = tc; } - else + else temp_disp = op_string; while (*temp_disp != '\0') @@ -3058,8 +3064,8 @@ i386_parse_seg (op_string) return 0; } - return 1; - + return 1; + } static int i386_intel_memory_operand PARAMS ((char *)); @@ -3166,7 +3172,7 @@ i386_intel_memory_operand (op_string) if (!i386_displacement (temp_string, temp_string + strlen (temp_string))) return 0; - + ++op_string; end_of_operand_string = op_string; while (*end_of_operand_string != ']' @@ -3241,71 +3247,71 @@ i386_intel_operand (operand_string, got_a_float) case SHORT: case NONE_FOUND: - /* Should be register or immediate */ - if (is_digit_char (*op_string) - && strchr (op_string, '[') == 0) - { - if (!i386_immediate (op_string)) - return 0; - } - else if (*op_string == REGISTER_PREFIX - || (allow_naked_reg - && i386_is_reg (op_string))) - { + /* Should be register or immediate */ + if (is_digit_char (*op_string) + && strchr (op_string, '[') == 0) + { + if (!i386_immediate (op_string)) + return 0; + } + else if (*op_string == REGISTER_PREFIX + || (allow_naked_reg + && i386_is_reg (op_string))) + { - register const reg_entry * r; - char *end_op; + register const reg_entry * r; + char *end_op; - r = parse_register (op_string, &end_op); - if (r == NULL) - return 0; + r = parse_register (op_string, &end_op); + if (r == NULL) + return 0; - /* Check for a segment override by searching for ':' after a - segment register. */ - op_string = end_op; - if (is_space_char (*op_string)) - ++op_string; - if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3))) - { - switch (r->reg_num) - { - case 0: - i.seg[i.mem_operands] = &es; - break; - case 1: - i.seg[i.mem_operands] = &cs; - break; - case 2: - i.seg[i.mem_operands] = &ss; - break; - case 3: - i.seg[i.mem_operands] = &ds; - break; - case 4: - i.seg[i.mem_operands] = &fs; - break; - case 5: - i.seg[i.mem_operands] = &gs; - break; - } + /* Check for a segment override by searching for ':' after a + segment register. */ + op_string = end_op; + if (is_space_char (*op_string)) + ++op_string; + if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3))) + { + switch (r->reg_num) + { + case 0: + i.seg[i.mem_operands] = &es; + break; + case 1: + i.seg[i.mem_operands] = &cs; + break; + case 2: + i.seg[i.mem_operands] = &ss; + break; + case 3: + i.seg[i.mem_operands] = &ds; + break; + case 4: + i.seg[i.mem_operands] = &fs; + break; + case 5: + i.seg[i.mem_operands] = &gs; + break; + } - } - i.types[this_operand] |= r->reg_type & ~BaseIndex; - i.regs[this_operand] = r; - i.reg_operands++; - } + } + i.types[this_operand] |= r->reg_type & ~BaseIndex; + i.regs[this_operand] = r; + i.reg_operands++; + } - else - { + else + { - if (!i386_intel_memory_operand (op_string)) - return 0; + if (!i386_intel_memory_operand (op_string)) + return 0; - i.mem_operands++; - } - break; + i.mem_operands++; + } + break; - } /* end switch */ + } /* end switch */ /* Special case for (%dx) while doing input/output op. */ if (i.base_reg && i.base_reg->reg_type == (Reg16 | InOutPortReg) @@ -3313,42 +3319,42 @@ i386_intel_operand (operand_string, got_a_float) && i.log2_scale_factor == 0 && i.seg[i.mem_operands] == 0 && (i.types[this_operand] & Disp) == 0) - { - i.types[this_operand] = InOutPortReg; - return 1; - } + { + i.types[this_operand] = InOutPortReg; + return 1; + } /* Make sure the memory operand we've been dealt is valid. */ if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0)) { if ((i.base_reg && ((i.base_reg->reg_type & (Reg16|BaseIndex)) - != (Reg16|BaseIndex))) - || (i.index_reg - && (((i.index_reg->reg_type & (Reg16|BaseIndex)) - != (Reg16|BaseIndex)) - || ! (i.base_reg - && i.base_reg->reg_num < 6 - && i.index_reg->reg_num >= 6 - && i.log2_scale_factor == 0)))) - { - as_bad (_("`%s' is not a valid %s bit base/index expression"), - operand_string, "16"); - return 0; - } + != (Reg16|BaseIndex))) + || (i.index_reg + && (((i.index_reg->reg_type & (Reg16|BaseIndex)) + != (Reg16|BaseIndex)) + || ! (i.base_reg + && i.base_reg->reg_num < 6 + && i.index_reg->reg_num >= 6 + && i.log2_scale_factor == 0)))) + { + as_bad (_("`%s' is not a valid %s bit base/index expression"), + operand_string, "16"); + return 0; + } } - else + else + { + if ((i.base_reg + && (i.base_reg->reg_type & Reg32) == 0) + || (i.index_reg + && ((i.index_reg->reg_type & (Reg32|BaseIndex)) + != (Reg32|BaseIndex)))) { - if ((i.base_reg - && (i.base_reg->reg_type & Reg32) == 0) - || (i.index_reg - && ((i.index_reg->reg_type & (Reg32|BaseIndex)) - != (Reg32|BaseIndex)))) - { - as_bad (_("`%s' is not a valid %s bit base/index expression"), - operand_string, "32"); - return 0; - } + as_bad (_("`%s' is not a valid %s bit base/index expression"), + operand_string, "32"); + return 0; } + } return 1; } @@ -3361,335 +3367,361 @@ static int i386_operand (operand_string) char *operand_string; { - char *op_string = operand_string; + char *op_string = operand_string; - if (is_space_char (*op_string)) + if (is_space_char (*op_string)) ++op_string; - /* We check for an absolute prefix (differentiating, - for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ - if (*op_string == ABSOLUTE_PREFIX) - { - ++op_string; - if (is_space_char (*op_string)) - ++op_string; - i.types[this_operand] |= JumpAbsolute; - } - - /* Check if operand is a register. */ - if (*op_string == REGISTER_PREFIX - || (allow_naked_reg && i386_is_reg (op_string))) - { - register const reg_entry *r; - char *end_op; + /* We check for an absolute prefix (differentiating, + for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ + if (*op_string == ABSOLUTE_PREFIX) + { + ++op_string; + if (is_space_char (*op_string)) + ++op_string; + i.types[this_operand] |= JumpAbsolute; + } + + /* Check if operand is a register. */ + if (*op_string == REGISTER_PREFIX + || (allow_naked_reg && i386_is_reg (op_string))) + { + register const reg_entry *r; + char *end_op; + + r = parse_register (op_string, &end_op); + if (r == NULL) + return 0; - r = parse_register (op_string, &end_op); - if (r == NULL) - return 0; + /* Check for a segment override by searching for ':' after a + segment register. */ + op_string = end_op; + if (is_space_char (*op_string)) + ++op_string; + if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3))) + { + switch (r->reg_num) + { + case 0: + i.seg[i.mem_operands] = &es; + break; + case 1: + i.seg[i.mem_operands] = &cs; + break; + case 2: + i.seg[i.mem_operands] = &ss; + break; + case 3: + i.seg[i.mem_operands] = &ds; + break; + case 4: + i.seg[i.mem_operands] = &fs; + break; + case 5: + i.seg[i.mem_operands] = &gs; + break; + } - /* Check for a segment override by searching for ':' after a - segment register. */ - op_string = end_op; - if (is_space_char (*op_string)) - ++op_string; - if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3))) - { - switch (r->reg_num) - { - case 0: - i.seg[i.mem_operands] = &es; - break; - case 1: - i.seg[i.mem_operands] = &cs; - break; - case 2: - i.seg[i.mem_operands] = &ss; - break; - case 3: - i.seg[i.mem_operands] = &ds; - break; - case 4: - i.seg[i.mem_operands] = &fs; - break; - case 5: - i.seg[i.mem_operands] = &gs; - break; - } + /* Skip the ':' and whitespace. */ + ++op_string; + if (is_space_char (*op_string)) + ++op_string; - /* Skip the ':' and whitespace. */ + /* Pretend given string starts here. */ + operand_string = op_string; + if (!is_digit_char (*op_string) + && !is_identifier_char (*op_string) + && *op_string != '(' + && *op_string != ABSOLUTE_PREFIX) + { + as_bad (_("bad memory operand `%s'"), op_string); + return 0; + } + /* Handle case of %es:*foo. */ + if (*op_string == ABSOLUTE_PREFIX) + { ++op_string; if (is_space_char (*op_string)) - ++op_string; + ++op_string; + i.types[this_operand] |= JumpAbsolute; + } + goto do_memory_reference; + } + if (*op_string) + { + as_bad (_("Junk `%s' after register"), op_string); + return 0; + } + i.types[this_operand] |= r->reg_type & ~BaseIndex; + i.regs[this_operand] = r; + i.reg_operands++; + } + else if (*op_string == IMMEDIATE_PREFIX) + { /* ... or an immediate */ + ++op_string; + if (i.types[this_operand] & JumpAbsolute) + { + as_bad (_("Immediate operand illegal with absolute jump")); + return 0; + } + if (!i386_immediate (op_string)) + return 0; + } + else if (is_digit_char (*op_string) + || is_identifier_char (*op_string) + || *op_string == '(' ) + { + /* This is a memory reference of some sort. */ + char *end_of_operand_string; + register char *base_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; + + do_memory_reference: + + if ((i.mem_operands == 1 + && (current_templates->start->opcode_modifier & IsString) == 0) + || i.mem_operands == 2) + { + as_bad (_("too many memory references for `%s'"), + current_templates->start->name); + return 0; + } - /* Pretend given string starts here. */ - operand_string = op_string; - if (!is_digit_char (*op_string) - && !is_identifier_char (*op_string) - && *op_string != '(' - && *op_string != ABSOLUTE_PREFIX) - { - as_bad (_("bad memory operand `%s'"), op_string); - return 0; - } - /* Handle case of %es:*foo. */ - if (*op_string == ABSOLUTE_PREFIX) - { - ++op_string; - if (is_space_char (*op_string)) - ++op_string; - i.types[this_operand] |= JumpAbsolute; - } - goto do_memory_reference; - } - if (*op_string) - { - as_bad (_("Junk `%s' after register"), op_string); - return 0; - } - i.types[this_operand] |= r->reg_type & ~BaseIndex; - i.regs[this_operand] = r; - i.reg_operands++; - } - else if (*op_string == IMMEDIATE_PREFIX) - { /* ... or an immediate */ - ++op_string; - if (i.types[this_operand] & JumpAbsolute) - { - as_bad (_("Immediate operand illegal with absolute jump")); - return 0; - } - if (!i386_immediate (op_string)) - return 0; - } - else if (is_digit_char (*op_string) - || is_identifier_char (*op_string) - || *op_string == '(' ) - { - /* This is a memory reference of some sort. */ - char *end_of_operand_string; - register char *base_string; - int found_base_index_form; + /* Check for base index form. We detect the base index form by + looking for an ')' at the end of the operand, searching + for the '(' matching it, and finding a REGISTER_PREFIX or ',' + after the '('. */ + found_base_index_form = 0; + end_of_operand_string = op_string + strlen (op_string); - /* Start and end of displacement string expression (if found). */ - char *displacement_string_start = NULL; - char *displacement_string_end = NULL; + --end_of_operand_string; + if (is_space_char (*end_of_operand_string)) + --end_of_operand_string; - do_memory_reference: + base_string = end_of_operand_string; - if ((i.mem_operands == 1 - && (current_templates->start->opcode_modifier & IsString) == 0) - || i.mem_operands == 2) - { - as_bad (_("too many memory references for `%s'"), - current_templates->start->name); - return 0; - } + if (*base_string == ')') + { + unsigned int parens_balanced = 1; + /* We've already checked that the number of left & right ()'s are + equal, so this loop will not be infinite. */ + do + { + base_string--; + if (*base_string == ')') + parens_balanced++; + if (*base_string == '(') + parens_balanced--; + } + while (parens_balanced); - /* Check for base index form. We detect the base index form by - looking for an ')' at the end of the operand, searching - for the '(' matching it, and finding a REGISTER_PREFIX or ',' - after the '('. */ - found_base_index_form = 0; - end_of_operand_string = op_string + strlen (op_string); + /* If there is a displacement set-up for it to be parsed later. */ + displacement_string_start = op_string; + displacement_string_end = base_string; - --end_of_operand_string; - if (is_space_char (*end_of_operand_string)) - --end_of_operand_string; + /* Skip past '(' and whitespace. */ + ++base_string; + if (is_space_char (*base_string)) + ++base_string; - base_string = end_of_operand_string; + if (*base_string == REGISTER_PREFIX + || (allow_naked_reg && i386_is_reg (base_string)) + || *base_string == ',') + found_base_index_form = 1; + } - if (*base_string == ')') - { - unsigned int parens_balanced = 1; - /* We've already checked that the number of left & right ()'s are - equal, so this loop will not be infinite. */ - do - { - base_string--; - if (*base_string == ')') - parens_balanced++; - if (*base_string == '(') - parens_balanced--; - } - while (parens_balanced); + /* If we can't parse a base index register expression, we've found + a pure displacement expression. We set up displacement_string_start + and displacement_string_end for the code below. */ + if (!found_base_index_form) + { + displacement_string_start = op_string; + displacement_string_end = end_of_operand_string + 1; + } + else + { + i.types[this_operand] |= BaseIndex; + + /* Find base register (if any). */ + if (*base_string != ',') + { + char *end_op; - /* If there is a displacement set-up for it to be parsed later. */ - displacement_string_start = op_string; - displacement_string_end = base_string; + /* Trim off the closing ')' so that parse_register won't + see it. */ + END_STRING_AND_SAVE (end_of_operand_string); + i.base_reg = parse_register (base_string, &end_op); + RESTORE_END_STRING (end_of_operand_string); - /* Skip past '(' and whitespace. */ + if (i.base_reg == NULL) + return 0; + + base_string = end_op; + if (is_space_char (*base_string)) + ++base_string; + } + + /* There may be an index reg or scale factor here. */ + if (*base_string == ',') + { ++base_string; if (is_space_char (*base_string)) - ++base_string; + ++base_string; if (*base_string == REGISTER_PREFIX - || (allow_naked_reg && i386_is_reg (base_string)) - || *base_string == ',') - found_base_index_form = 1; - } - - /* If we can't parse a base index register expression, we've found - a pure displacement expression. We set up displacement_string_start - and displacement_string_end for the code below. */ - if (!found_base_index_form) - { - displacement_string_start = op_string; - displacement_string_end = end_of_operand_string + 1; - } - else - { - i.types[this_operand] |= BaseIndex; - - /* Find base register (if any). */ - if (*base_string != ',') + || (allow_naked_reg && i386_is_reg (base_string))) { - char *end_op; + char *end_op; - /* Trim off the closing ')' so that parse_register won't - see it. */ - END_STRING_AND_SAVE (end_of_operand_string); - i.base_reg = parse_register (base_string, &end_op); - RESTORE_END_STRING (end_of_operand_string); + END_STRING_AND_SAVE (end_of_operand_string); + i.index_reg = parse_register (base_string, &end_op); + RESTORE_END_STRING (end_of_operand_string); - if (i.base_reg == NULL) + if (i.index_reg == NULL) return 0; - base_string = end_op; - if (is_space_char (*base_string)) + base_string = end_op; + if (is_space_char (*base_string)) + ++base_string; + if (*base_string == ',') + { ++base_string; + if (is_space_char (*base_string)) + ++base_string; + } + else if (*base_string != ')' ) + { + as_bad (_("expecting `,' or `)' after index register in `%s'"), + operand_string); + return 0; + } } - /* There may be an index reg or scale factor here. */ - if (*base_string == ',') + /* Check for scale factor. */ + if (isdigit ((unsigned char) *base_string)) { - ++base_string; - if (is_space_char (*base_string)) - ++base_string; - - if (*base_string == REGISTER_PREFIX - || (allow_naked_reg && i386_is_reg (base_string))) - { - char *end_op; - - END_STRING_AND_SAVE (end_of_operand_string); - i.index_reg = parse_register (base_string, &end_op); - RESTORE_END_STRING (end_of_operand_string); - - if (i.index_reg == NULL) - return 0; - - base_string = end_op; - if (is_space_char (*base_string)) - ++base_string; - if (*base_string == ',') - { - ++base_string; - if (is_space_char (*base_string)) - ++base_string; - } - else if (*base_string != ')' ) - { - as_bad (_("expecting `,' or `)' after index register in `%s'"), - operand_string); - return 0; - } - } + if (!i386_scale (base_string)) + return 0; - /* Check for scale factor. */ - if (isdigit ((unsigned char) *base_string)) - { - if (!i386_scale (base_string)) - return 0; - - ++base_string; - if (is_space_char (*base_string)) - ++base_string; - if (*base_string != ')') - { - as_bad (_("expecting `)' after scale factor in `%s'"), - operand_string); - return 0; - } - } - else if (!i.index_reg) - { - as_bad (_("expecting index register or scale factor after `,'; got '%c'"), - *base_string); - return 0; - } + ++base_string; + if (is_space_char (*base_string)) + ++base_string; + if (*base_string != ')') + { + as_bad (_("expecting `)' after scale factor in `%s'"), + operand_string); + return 0; + } } - else if (*base_string != ')') + else if (!i.index_reg) { - as_bad (_("expecting `,' or `)' after base register in `%s'"), - operand_string); - return 0; + as_bad (_("expecting index register or scale factor after `,'; got '%c'"), + *base_string); + return 0; } - } + } + else if (*base_string != ')') + { + as_bad (_("expecting `,' or `)' after base register in `%s'"), + operand_string); + return 0; + } + } - /* If there's an expression beginning the operand, parse it, - assuming displacement_string_start and - displacement_string_end are meaningful. */ - if (displacement_string_start != displacement_string_end) - { - if (!i386_displacement (displacement_string_start, - displacement_string_end)) - return 0; - } + /* If there's an expression beginning the operand, parse it, + assuming displacement_string_start and + displacement_string_end are meaningful. */ + if (displacement_string_start != displacement_string_end) + { + if (!i386_displacement (displacement_string_start, + displacement_string_end)) + return 0; + } - /* Special case for (%dx) while doing input/output op. */ - if (i.base_reg - && i.base_reg->reg_type == (Reg16 | InOutPortReg) - && i.index_reg == 0 - && i.log2_scale_factor == 0 - && i.seg[i.mem_operands] == 0 - && (i.types[this_operand] & Disp) == 0) - { - i.types[this_operand] = InOutPortReg; - return 1; - } - /* Make sure the memory operand we've been dealt is valid. */ - if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0)) - { - if ((i.base_reg - && ((i.base_reg->reg_type & (Reg16|BaseIndex)) - != (Reg16|BaseIndex))) - || (i.index_reg - && (((i.index_reg->reg_type & (Reg16|BaseIndex)) - != (Reg16|BaseIndex)) - || ! (i.base_reg - && i.base_reg->reg_num < 6 - && i.index_reg->reg_num >= 6 - && i.log2_scale_factor == 0)))) + /* Special case for (%dx) while doing input/output op. */ + if (i.base_reg + && i.base_reg->reg_type == (Reg16 | InOutPortReg) + && i.index_reg == 0 + && i.log2_scale_factor == 0 + && i.seg[i.mem_operands] == 0 + && (i.types[this_operand] & Disp) == 0) + { + i.types[this_operand] = InOutPortReg; + return 1; + } + /* Make sure the memory operand we've been dealt is valid. */ + if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0)) + { +#if INFER_ADDR_PREFIX + try16: +#endif + if ((i.base_reg + && ((i.base_reg->reg_type & (Reg16|BaseIndex)) + != (Reg16|BaseIndex))) + || (i.index_reg + && (((i.index_reg->reg_type & (Reg16|BaseIndex)) + != (Reg16|BaseIndex)) + || ! (i.base_reg + && i.base_reg->reg_num < 6 + && i.index_reg->reg_num >= 6 + && i.log2_scale_factor == 0)))) + { +#if INFER_ADDR_PREFIX + if (i.prefix[ADDR_PREFIX] == 0) { - as_bad (_("`%s' is not a valid %s bit base/index expression"), - operand_string, "16"); - return 0; + i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; + goto try32; } - } - else - { - if ((i.base_reg - && (i.base_reg->reg_type & Reg32) == 0) - || (i.index_reg - && ((i.index_reg->reg_type & (Reg32|BaseIndex)) - != (Reg32|BaseIndex)))) + else +#endif { - as_bad (_("`%s' is not a valid %s bit base/index expression"), - operand_string, "32"); - return 0; + as_bad (_("`%s' is not a valid %s bit base/index expression"), + operand_string, "16"); + return 0; } - } - i.mem_operands++; - } - else - { /* it's not a memory operand; argh! */ - as_bad (_("invalid char %s beginning operand %d `%s'"), - output_invalid (*op_string), - this_operand + 1, - op_string); - return 0; - } - return 1; /* normal return */ + } + } + else + { +#if INFER_ADDR_PREFIX + try32: +#endif + if ((i.base_reg + && (i.base_reg->reg_type & Reg32) == 0) + || (i.index_reg + && ((i.index_reg->reg_type & (Reg32|BaseIndex)) + != (Reg32|BaseIndex)))) + { +#if INFER_ADDR_PREFIX + if (i.prefix[ADDR_PREFIX] == 0) + { + i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; + goto try16; + } + else +#endif + { + as_bad (_("`%s' is not a valid %s bit base/index expression"), + operand_string, "32"); + return 0; + } + } + } + i.mem_operands++; + } + else + { /* it's not a memory operand; argh! */ + as_bad (_("invalid char %s beginning operand %d `%s'"), + output_invalid (*op_string), + this_operand + 1, + op_string); + return 0; + } + return 1; /* normal return */ } /* @@ -3995,14 +4027,14 @@ md_apply_fix3 (fixP, valp, seg) * operands that look like "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal * here is to obtain the absolute address of the GOT, and it is strongly * preferable from a performance point of view to avoid using a runtime - * relocation for this. The actual sequence of instructions often look + * relocation for this. The actual sequence of instructions often look * something like: - * + * * call .L66 * .L66: * popl %ebx * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx - * + * * The call and pop essentially return the absolute address of * the label .L66 and store it in %ebx. The linker itself will * ultimately change the first operand of the addl so that %ebx points to @@ -4012,17 +4044,17 @@ md_apply_fix3 (fixP, valp, seg) * treat a GOTPC relocation as asking for a pcrel offset to the GOT to be * added in, and the addend of the relocation is stored in the operand * field for the instruction itself. - * + * * Our job here is to fix the operand so that it would add the correct * offset so that %ebx would point to itself. The thing that is tricky is * that .-.L66 will point to the beginning of the instruction, so we need * to further modify the operand so that it will point to itself. * There are other cases where you have something like: - * + * * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66] - * + * * and here no correction would be required. Internally in the assembler - * we treat operands of this form as not being pcrel since the '.' is + * we treat operands of this form as not being pcrel since the '.' is * explicitly mentioned, and I wonder whether it would simplify matters * to do it this way. Who knows. In earlier versions of the PIC patches, * the pcrel_adjust field was used to store the correction, but since the |