A second set of changes to get the Intel syntax handling closer to that of assemblers natively using that mode. This mainly means rejecting more invalid constructs (instead of silently generating ill code), but also allowing more freedom for how certain syntax elements can be used. Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu. Jan gas/ 2005-03-14 Jan Beulich * config/tc-i386.c (i386_scale): Beautify error message. (Intel syntax comments): Update. (struct intel_parser_s): Add fields in_offset, in_bracket, and next_operand. (intel_e04_1, intel_e05_1, intel_e05_1, intel_e09_1, intel_e10_1): Remove declarations. (intel_bracket_expr): Declare. (i386_intel_operand): Initialize new intel_parser fields. Wrap most of the function body in a loop allowing to split an operand into two. Replace calls to malloc and checks of it returning non-NULL with calls to xmalloc/xstrdup. (intel_expr): SHORT no longer handled here. Add comment indicating comparison ops need implementation. (intel_e04, intel_e04_1): Combine, replace recursion with loop. Check right operand of - does not specify a register when parsing the address of a memory reference. (intel_e05, intel_e05_1): Combine, replace recursion with loop. Check operands do not specify a register when parsing the address of a memory reference. (intel_e06, intel_e06_1): Likewise. (intel_e09, intel_e09_1): Combine, replace recursion with loop. Also handle SHORT as well as unary + and -. Don't accept : except for segment overrides or in direct far jump/call insns. (intel_brack_expr): New. (intel_e10, intel_e10_1): Combine, replace recursion with loop. Use intel_brack_expr. (intel_e11): Replace chain of if/else-if by switch, alloing fall- through in certain cases. Use intel_brack_expr. Add new diagnostics. Allow symbolic constants as register scale value. (intel_get_token): Replace call to malloc and check of return value with call to xmalloc. Change handling for FLAT to match MASM's. (intel_putback_token): Don't try to back up/free current token if that is T_NIL. gas/testsuite/ 2005-03-14 Jan Beulich * gas/i386/intel.d: Add stderr directive. * gas/i386/intel.e: New. * gas/i386/intel16.d: Add stderr directive. Adjust for changed source. * gas/i386/intel16.e: New. * gas/i386/intel16.s: Add instances of addressing forms with base and index specified in reverse order. * gas/i386/intelbad.l: Adjust for changed source. * gas/i386/intelbad.s * gas/i386/intelok.d: Remove -r from objdump options. Add stderr directive. Adjust for changed source. * gas/i386/intelok.e: New. * gas/i386/intelok.s: Define MASM constants byte, word, etc. Add more operand forms to check. * gas/i386/x86_64.d: Add stderr directive. * gas/i386/x86_64.e: New. * gas/i386/x86_64.s: Adjust for parser changes. --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/config/tc-i386.c 2005-03-04 15:51:43.000000000 +0100 +++ 2005-03-14/gas/config/tc-i386.c 2005-03-14 15:08:07.335144320 +0100 @@ -3965,10 +3965,16 @@ i386_scale (scale) i.log2_scale_factor = 3; break; default: - as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), - scale); - input_line_pointer = save; - return NULL; + { + char sep = *input_line_pointer; + + *input_line_pointer = '\0'; + as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), + scale); + *input_line_pointer = sep; + input_line_pointer = save; + return NULL; + } } if (i.log2_scale_factor != 0 && i.index_reg == 0) { @@ -5514,6 +5520,9 @@ tc_gen_reloc (section, fixp) | e09 e09 OFFSET e10 + | SHORT e10 + | + e10 + | - e10 | ~ e10 | NOT e10 | e09 PTR e10 @@ -5531,7 +5540,7 @@ tc_gen_reloc (section, fixp) | $ | register - => expr SHORT e04 + => expr expr cmpOp e04 | e04 gpRegister AX | EAX | BX | EBX | CX | ECX | DX | EDX @@ -5562,8 +5571,10 @@ tc_gen_reloc (section, fixp) done by calling parse_register) and eliminate immediate left recursion to implement a recursive-descent parser. - expr SHORT e04 - | e04 + expr e04 expr' + + expr' cmpOp e04 expr' + | Empty e04 e05 e04' @@ -5581,8 +5592,11 @@ tc_gen_reloc (section, fixp) | Empty e09 OFFSET e10 e09' - | ~ e10 - | NOT e10 + | SHORT e10' + | + e10' + | - e10' + | ~ e10' + | NOT e10' | e10 e09' e09' PTR e10 e09' @@ -5618,8 +5632,11 @@ struct intel_parser_s int got_a_float; /* Whether the operand is a float. */ int op_modifier; /* Operand modifier. */ int is_mem; /* 1 if operand is memory reference. */ + int in_offset; /* >=1 if parsing operand of offset. */ + int in_bracket; /* >=1 if parsing operand in brackets. */ const reg_entry *reg; /* Last register reference found. */ char *disp; /* Displacement string being built. */ + char *next_operand; /* Resume point when splitting operands. */ }; static struct intel_parser_s intel_parser; @@ -5660,15 +5677,11 @@ static void intel_get_token PARAMS ((voi static void intel_putback_token PARAMS ((void)); static int intel_expr PARAMS ((void)); static int intel_e04 PARAMS ((void)); -static int intel_e04_1 PARAMS ((void)); static int intel_e05 PARAMS ((void)); -static int intel_e05_1 PARAMS ((void)); static int intel_e06 PARAMS ((void)); -static int intel_e06_1 PARAMS ((void)); static int intel_e09 PARAMS ((void)); -static int intel_e09_1 PARAMS ((void)); +static int intel_bracket_expr PARAMS ((void)); static int intel_e10 PARAMS ((void)); -static int intel_e10_1 PARAMS ((void)); static int intel_e11 PARAMS ((void)); static int @@ -5679,31 +5692,33 @@ i386_intel_operand (operand_string, got_ int ret; char *p; - /* Initialize token holders. */ - cur_token.code = prev_token.code = T_NIL; - cur_token.reg = prev_token.reg = NULL; - cur_token.str = prev_token.str = NULL; - - /* Initialize parser structure. */ - p = intel_parser.op_string = (char *) malloc (strlen (operand_string) + 1); - if (p == NULL) - abort (); - strcpy (intel_parser.op_string, operand_string); - intel_parser.got_a_float = got_a_float; - intel_parser.op_modifier = -1; - intel_parser.is_mem = 0; - intel_parser.reg = NULL; - intel_parser.disp = (char *) malloc (strlen (operand_string) + 1); - if (intel_parser.disp == NULL) - abort (); - intel_parser.disp[0] = '\0'; - - /* Read the first token and start the parser. */ - intel_get_token (); - ret = intel_expr (); + p = intel_parser.op_string = xstrdup (operand_string); + intel_parser.disp = (char *) xmalloc (strlen (operand_string) + 1); - if (ret) + for (;;) { + /* Initialize token holders. */ + cur_token.code = prev_token.code = T_NIL; + cur_token.reg = prev_token.reg = NULL; + cur_token.str = prev_token.str = NULL; + + /* Initialize parser structure. */ + intel_parser.got_a_float = got_a_float; + intel_parser.op_modifier = 0; + intel_parser.is_mem = 0; + intel_parser.in_offset = 0; + intel_parser.in_bracket = 0; + intel_parser.reg = NULL; + intel_parser.disp[0] = '\0'; + intel_parser.next_operand = NULL; + + /* Read the first token and start the parser. */ + intel_get_token (); + ret = intel_expr (); + + if (!ret) + break; + if (cur_token.code != T_NIL) { as_bad (_("invalid operand for '%s' ('%s' unexpected)"), @@ -5727,18 +5742,46 @@ i386_intel_operand (operand_string, got_ char *s = intel_parser.disp; i.mem_operands++; + if (!quiet_warnings && intel_parser.is_mem < 0) + /* See the comments in intel_bracket_expr. */ + as_warn (_("Treating `%s' as memory reference"), operand_string); + /* Add the displacement expression. */ if (*s != '\0') ret = i386_displacement (s, s + strlen (s)); if (ret) - ret = i386_index_check (operand_string); + { + /* Swap base and index in 16-bit memory operands like + [si+bx]. Since i386_index_check is also used in AT&T + mode we have to do that here. */ + if (i.base_reg + && i.index_reg + && (i.base_reg->reg_type & Reg16) + && (i.index_reg->reg_type & Reg16) + && i.base_reg->reg_num >= 6 + && i.index_reg->reg_num < 6) + { + const reg_entry *base = i.index_reg; + + i.index_reg = i.base_reg; + i.base_reg = base; + } + ret = i386_index_check (operand_string); + } } } /* Constant and OFFSET expressions are handled by i386_immediate. */ - else if (intel_parser.op_modifier == T_OFFSET + else if ((intel_parser.op_modifier & (1 << T_OFFSET)) || intel_parser.reg == NULL) ret = i386_immediate (intel_parser.disp); + + if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1) + ret = 0; + if (!ret || !intel_parser.next_operand) + break; + intel_parser.op_string = intel_parser.next_operand; + this_operand = i.operands++; } free (p); @@ -5747,54 +5790,46 @@ i386_intel_operand (operand_string, got_ return ret; } -/* expr SHORT e04 - | e04 */ +#define NUM_ADDRESS_REGS (!!i.base_reg + !!i.index_reg) + +/* expr e04 expr' + + expr' cmpOp e04 expr' + | Empty */ static int intel_expr () { - /* expr SHORT e04 */ - if (cur_token.code == T_SHORT) - { - intel_parser.op_modifier = T_SHORT; - intel_match_token (T_SHORT); - - return (intel_e04 ()); - } - - /* expr e04 */ - else - return intel_e04 (); + /* XXX Implement the comparison operators. */ + return intel_e04 (); } -/* e04 e06 e04' +/* e04 e05 e04' - e04' addOp e06 e04' + e04' addOp e05 e04' | Empty */ static int intel_e04 () { - return (intel_e05 () && intel_e04_1 ()); -} + int nregs = -1; -static int -intel_e04_1 () -{ - /* e04' addOp e05 e04' */ - if (cur_token.code == '+' || cur_token.code == '-') + for (;;) { - char str[2]; + if (!intel_e05()) + return 0; - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); - intel_match_token (cur_token.code); + if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) + i.base_reg = i386_regtab + REGNAM_AL; /* al is invalid as base */ - return (intel_e05 () && intel_e04_1 ()); - } + if (cur_token.code == '+') + nregs = -1; + else if (cur_token.code == '-') + nregs = NUM_ADDRESS_REGS; + else + return 1; - /* e04' Empty */ - else - return 1; + strcat (intel_parser.disp, cur_token.str); + intel_match_token (cur_token.code); + } } /* e05 e06 e05' @@ -5804,28 +5839,32 @@ intel_e04_1 () static int intel_e05 () { - return (intel_e06 () && intel_e05_1 ()); -} + int nregs = ~NUM_ADDRESS_REGS; -static int -intel_e05_1 () -{ - /* e05' binOp e06 e05' */ - if (cur_token.code == '&' || cur_token.code == '|' || cur_token.code == '^') + for (;;) { - char str[2]; + if (!intel_e06()) + return 0; + + if (cur_token.code == '&' || cur_token.code == '|' || cur_token.code == '^') + { + char str[2]; + + str[0] = cur_token.code; + str[1] = 0; + strcat (intel_parser.disp, str); + } + else + break; - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); intel_match_token (cur_token.code); - return (intel_e06 () && intel_e05_1 ()); + if (nregs < 0) + nregs = ~nregs; } - - /* e05' Empty */ - else - return 1; + if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) + i.base_reg = i386_regtab + REGNAM_AL + 1; /* cl is invalid as base */ + return 1; } /* e06 e09 e06' @@ -5835,49 +5874,44 @@ intel_e05_1 () static int intel_e06 () { - return (intel_e09 () && intel_e06_1 ()); -} + int nregs = ~NUM_ADDRESS_REGS; -static int -intel_e06_1 () -{ - /* e06' mulOp e09 e06' */ - if (cur_token.code == '*' || cur_token.code == '/' || cur_token.code == '%') + for (;;) { - char str[2]; + if (!intel_e09()) + return 0; - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); - intel_match_token (cur_token.code); + if (cur_token.code == '*' || cur_token.code == '/' || cur_token.code == '%') + { + char str[2]; - return (intel_e09 () && intel_e06_1 ()); - } - else if (cur_token.code == T_SHL) - { - strcat (intel_parser.disp, "<<"); - intel_match_token (cur_token.code); + str[0] = cur_token.code; + str[1] = 0; + strcat (intel_parser.disp, str); + } + else if (cur_token.code == T_SHL) + strcat (intel_parser.disp, "<<"); + else if (cur_token.code == T_SHR) + strcat (intel_parser.disp, ">>"); + else + break; - return (intel_e09 () && intel_e06_1 ()); - } - else if (cur_token.code == T_SHR) - { - strcat (intel_parser.disp, ">>"); - intel_match_token (cur_token.code); + intel_match_token (cur_token.code); - return (intel_e09 () && intel_e06_1 ()); + if (nregs < 0) + nregs = ~nregs; } - - /* e06' Empty */ - else - return 1; + if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) + i.base_reg = i386_regtab + REGNAM_AL + 2; /* dl is invalid as base */ + return 1; } -/* e09 OFFSET e10 e09' - | e10 e09' - - e09 ~ e10 e09' - | NOT e10 e09' +/* e09 OFFSET e09 + | SHORT e09 + | + e09 + | - e09 + | ~ e09 + | NOT e09 | e10 e09' e09' PTR e10 e09' @@ -5886,146 +5920,277 @@ intel_e06_1 () static int intel_e09 () { - /* e09 OFFSET e10 e09' */ - if (cur_token.code == T_OFFSET) + int nregs = ~NUM_ADDRESS_REGS; + int in_offset = 0; + + for (;;) { - intel_parser.is_mem = 0; - intel_parser.op_modifier = T_OFFSET; - intel_match_token (T_OFFSET); + /* Don't consume constants here. */ + if (cur_token.code == '+' || cur_token.code == '-') + { + /* Need to look one token ahead - if the next token + is a constant, the current token is its sign. */ + int next_code; + + intel_match_token (cur_token.code); + next_code = cur_token.code; + intel_putback_token (); + if (next_code == T_CONST) + break; + } + + /* e09 OFFSET e09 */ + if (cur_token.code == T_OFFSET) + { + if (!in_offset++) + ++intel_parser.in_offset; + } + + /* e09 SHORT e09 */ + else if (cur_token.code == T_SHORT) + intel_parser.op_modifier |= 1 << T_SHORT; + + /* e09 + e09 */ + else if (cur_token.code == '+') + strcat (intel_parser.disp, "+"); + + /* e09 - e09 + | ~ e09 + | NOT e09 */ + else if (cur_token.code == '-' || cur_token.code == '~') + { + char str[2]; - return (intel_e10 () && intel_e09_1 ()); + if (nregs < 0) + nregs = ~nregs; + str[0] = cur_token.code; + str[1] = 0; + strcat (intel_parser.disp, str); + } + + /* e09 e10 e09' */ + else + break; + + intel_match_token (cur_token.code); } - /* e09 NOT e10 e09' */ - else if (cur_token.code == '~') + for (;;) { - char str[2]; + if (!intel_e10 ()) + return 0; - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); - intel_match_token (cur_token.code); + /* e09' PTR e10 e09' */ + if (cur_token.code == T_PTR) + { + char suffix; - return (intel_e10 () && intel_e09_1 ()); - } + if (prev_token.code == T_BYTE) + suffix = BYTE_MNEM_SUFFIX; - /* e09 e10 e09' */ - else - return (intel_e10 () && intel_e09_1 ()); -} + else if (prev_token.code == T_WORD) + { + if (current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + else if (intel_parser.got_a_float == 2) /* "fi..." */ + suffix = SHORT_MNEM_SUFFIX; + else + suffix = WORD_MNEM_SUFFIX; + } -static int -intel_e09_1 () -{ - /* e09' PTR e10 e09' */ - if (cur_token.code == T_PTR) - { - char suffix; + else if (prev_token.code == T_DWORD) + { + if (current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + suffix = WORD_MNEM_SUFFIX; + else if (flag_code == CODE_16BIT + && (current_templates->start->opcode_modifier + & (Jump|JumpDword|JumpInterSegment))) + suffix = LONG_DOUBLE_MNEM_SUFFIX; + else if (intel_parser.got_a_float == 1) /* "f..." */ + suffix = SHORT_MNEM_SUFFIX; + else + suffix = LONG_MNEM_SUFFIX; + } - if (prev_token.code == T_BYTE) - suffix = BYTE_MNEM_SUFFIX; + else if (prev_token.code == T_FWORD) + { + if (current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + suffix = LONG_MNEM_SUFFIX; + else if (!intel_parser.got_a_float) + { + if (flag_code == CODE_16BIT) + add_prefix (DATA_PREFIX_OPCODE); + suffix = LONG_DOUBLE_MNEM_SUFFIX; + } + else + suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + } - else if (prev_token.code == T_WORD) - { - if (current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ - else if (intel_parser.got_a_float == 2) /* "fi..." */ - suffix = SHORT_MNEM_SUFFIX; - else - suffix = WORD_MNEM_SUFFIX; - } + else if (prev_token.code == T_QWORD) + { + if (intel_parser.got_a_float == 1) /* "f..." */ + suffix = LONG_MNEM_SUFFIX; + else + suffix = QWORD_MNEM_SUFFIX; + } - else if (prev_token.code == T_DWORD) - { - if (current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) - suffix = WORD_MNEM_SUFFIX; - else if (flag_code == CODE_16BIT - && (current_templates->start->opcode_modifier - & (Jump|JumpDword|JumpInterSegment))) - suffix = LONG_DOUBLE_MNEM_SUFFIX; - else if (intel_parser.got_a_float == 1) /* "f..." */ - suffix = SHORT_MNEM_SUFFIX; - else - suffix = LONG_MNEM_SUFFIX; - } + else if (prev_token.code == T_TBYTE) + { + if (intel_parser.got_a_float == 1) + suffix = LONG_DOUBLE_MNEM_SUFFIX; + else + suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + } - else if (prev_token.code == T_FWORD) - { - if (current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) - suffix = LONG_MNEM_SUFFIX; - else if (!intel_parser.got_a_float) + else if (prev_token.code == T_XMMWORD) { - if (flag_code == CODE_16BIT) - add_prefix (DATA_PREFIX_OPCODE); - suffix = LONG_DOUBLE_MNEM_SUFFIX; + /* XXX ignored for now, but accepted since gcc uses it */ + suffix = 0; } - else - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ - } - else if (prev_token.code == T_QWORD) - { - if (intel_parser.got_a_float == 1) /* "f..." */ - suffix = LONG_MNEM_SUFFIX; else - suffix = QWORD_MNEM_SUFFIX; - } + { + as_bad (_("Unknown operand modifier `%s'"), prev_token.str); + return 0; + } + + if (current_templates->start->base_opcode == 0x8d /* lea */) + ; + else if (!i.suffix) + i.suffix = suffix; + else if (i.suffix != suffix) + { + as_bad (_("Conflicting operand modifiers")); + return 0; + } - else if (prev_token.code == T_TBYTE) - { - if (intel_parser.got_a_float == 1) - suffix = LONG_DOUBLE_MNEM_SUFFIX; - else - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ } - else if (prev_token.code == T_XMMWORD) + /* e09' : e10 e09' */ + else if (cur_token.code == ':') { - /* XXX ignored for now, but accepted since gcc uses it */ - suffix = 0; + if (prev_token.code != T_REG) + { + /* While {call,jmp} SSSS:OOOO is MASM syntax only when SSSS is a + segment/group identifier (which we don't have), using comma + as the operand separator there is even less consistent, since + there all branches only have a single operand. */ + if (this_operand != 0 + || intel_parser.in_offset + || intel_parser.in_bracket + || (!(current_templates->start->opcode_modifier + & (Jump|JumpDword|JumpInterSegment)) + && !(current_templates->start->operand_types[0] + & JumpAbsolute))) + return intel_match_token (T_NIL); + /* Remember the start of the 2nd operand and terminate 1st + operand here. + XXX This isn't right, yet (when SSSS:OOOO is right operand of + another expression), but it gets at least the simplest case + (a plain number or symbol on the left side) right. */ + intel_parser.next_operand = intel_parser.op_string; + *--intel_parser.op_string = '\0'; + return intel_match_token (':'); + } } + /* e09' Empty */ else - { - as_bad (_("Unknown operand modifier `%s'"), prev_token.str); - return 0; - } + break; - if (current_templates->start->base_opcode == 0x8d /* lea */) - ; - else if (!i.suffix) - i.suffix = suffix; - else if (i.suffix != suffix) + intel_match_token (cur_token.code); + + } + + if (in_offset) + { + --intel_parser.in_offset; + if (nregs < 0) + nregs = ~nregs; + if (NUM_ADDRESS_REGS > nregs) { - as_bad (_("Conflicting operand modifiers")); + as_bad (_("Invalid operand to `OFFSET'")); return 0; } + intel_parser.op_modifier |= 1 << T_OFFSET; + } - intel_match_token (T_PTR); + if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) + i.base_reg = i386_regtab + REGNAM_AL + 3; /* bl is invalid as base */ + return 1; +} - return (intel_e10 () && intel_e09_1 ()); +static int +intel_bracket_expr () +{ + int was_offset = intel_parser.op_modifier & (1 << T_OFFSET); + const char *start = intel_parser.op_string; + int len; + + if (i.op[this_operand].regs) + return intel_match_token (T_NIL); + + intel_match_token ('['); + + /* Mark as a memory operand only if it's not already known to be an + offset expression. If it's an offset expression, we need to keep + the brace in. */ + if (!intel_parser.in_offset) + { + ++intel_parser.in_bracket; + /* Unfortunately gas always diverged from MASM in a respect that can't + be easily fixed without risking to break code sequences likely to be + encountered (the testsuite even check for this): MASM doesn't consider + an expression inside brackets unconditionally as a memory reference. + When that is e.g. a constant, an offset expression, or the sum of the + two, this is still taken as a constant load. gas, however, always + treated these as memory references. As a compromise, we'll try to make + offset expressions inside brackets work the MASM way (since that's + less likely to be found in real world code), but make constants alone + continue to work the traditional gas way. In either case, issue a + warning. */ + intel_parser.op_modifier &= ~was_offset; } + else + strcat (intel_parser.disp, "["); - /* e09 : e10 e09' */ - else if (cur_token.code == ':') - { - /* Mark as a memory operand only if it's not already known to be an - offset expression. */ - if (intel_parser.op_modifier != T_OFFSET) - intel_parser.is_mem = 1; + /* Add a '+' to the displacement string if necessary. */ + if (*intel_parser.disp != '\0' + && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') + strcat (intel_parser.disp, "+"); + + if (intel_expr () + && (len = intel_parser.op_string - start - 1, + intel_match_token (']'))) + { + /* Preserve brackets when the operand is an offset expression. */ + if (intel_parser.in_offset) + strcat (intel_parser.disp, "]"); + else + { + --intel_parser.in_bracket; + if (i.base_reg || i.index_reg) + intel_parser.is_mem = 1; + if (!intel_parser.is_mem) + { + if (!(intel_parser.op_modifier & (1 << T_OFFSET))) + /* Defer the warning until all of the operand was parsed. */ + intel_parser.is_mem = -1; + else if (!quiet_warnings) + as_warn (_("`[%.*s]' taken to mean just `%.*s'"), len, start, len, start); + } + } + intel_parser.op_modifier |= was_offset; - return (intel_match_token (':') && intel_e10 () && intel_e09_1 ()); + return 1; } - - /* e09' Empty */ - else - return 1; + return 0; } /* e10 e11 e10' @@ -6035,45 +6200,16 @@ intel_e09_1 () static int intel_e10 () { - return (intel_e11 () && intel_e10_1 ()); -} + if (!intel_e11 ()) + return 0; -static int -intel_e10_1 () -{ - /* e10' [ expr ] e10' */ - if (cur_token.code == '[') + while (cur_token.code == '[') { - intel_match_token ('['); - - /* Mark as a memory operand only if it's not already known to be an - offset expression. If it's an offset expression, we need to keep - the brace in. */ - if (intel_parser.op_modifier != T_OFFSET) - intel_parser.is_mem = 1; - else - strcat (intel_parser.disp, "["); - - /* Add a '+' to the displacement string if necessary. */ - if (*intel_parser.disp != '\0' - && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') - strcat (intel_parser.disp, "+"); - - if (intel_expr () && intel_match_token (']')) - { - /* Preserve brackets when the operand is an offset expression. */ - if (intel_parser.op_modifier == T_OFFSET) - strcat (intel_parser.disp, "]"); - - return intel_e10_1 (); - } - else + if (!intel_bracket_expr ()) return 0; } - /* e10' Empty */ - else - return 1; + return 1; } /* e11 ( expr ) @@ -6094,9 +6230,10 @@ intel_e10_1 () static int intel_e11 () { - /* e11 ( expr ) */ - if (cur_token.code == '(') + switch (cur_token.code) { + /* e11 ( expr ) */ + case '(': intel_match_token ('('); strcat (intel_parser.disp, "("); @@ -6105,318 +6242,299 @@ intel_e11 () strcat (intel_parser.disp, ")"); return 1; } - else - return 0; - } - - /* e11 [ expr ] */ - else if (cur_token.code == '[') - { - intel_match_token ('['); - - /* Mark as a memory operand only if it's not already known to be an - offset expression. If it's an offset expression, we need to keep - the brace in. */ - if (intel_parser.op_modifier != T_OFFSET) - intel_parser.is_mem = 1; - else - strcat (intel_parser.disp, "["); + return 0; - /* Operands for jump/call inside brackets denote absolute addresses. */ + /* e11 [ expr ] */ + case '[': + /* Operands for jump/call inside brackets denote absolute addresses. + XXX This shouldn't be needed anymore (or if it should rather live + in intel_bracket_expr). */ if (current_templates->start->opcode_modifier & (Jump|JumpDword|JumpByte|JumpInterSegment)) i.types[this_operand] |= JumpAbsolute; - /* Add a '+' to the displacement string if necessary. */ - if (*intel_parser.disp != '\0' - && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') - strcat (intel_parser.disp, "+"); - - if (intel_expr () && intel_match_token (']')) - { - /* Preserve brackets when the operand is an offset expression. */ - if (intel_parser.op_modifier == T_OFFSET) - strcat (intel_parser.disp, "]"); + return intel_bracket_expr (); - return 1; - } - else - return 0; - } - - /* e11 BYTE - | WORD - | DWORD - | FWORD - | QWORD - | TBYTE - | OWORD - | XMMWORD */ - else if (cur_token.code == T_BYTE - || cur_token.code == T_WORD - || cur_token.code == T_DWORD - || cur_token.code == T_FWORD - || cur_token.code == T_QWORD - || cur_token.code == T_TBYTE - || cur_token.code == T_XMMWORD) - { - intel_match_token (cur_token.code); - - if (cur_token.code != T_PTR) - { - /* It must have been an identifier; add it to the displacement string. */ - strcat (intel_parser.disp, prev_token.str); - - /* The identifier represents a memory reference only if it's not - preceded by an offset modifier and if it's not an equate. */ - if (intel_parser.op_modifier != T_OFFSET) - { - symbolS *symbolP; - - symbolP = symbol_find(prev_token.str); - if (!symbolP || S_GET_SEGMENT(symbolP) != absolute_section) - intel_parser.is_mem = 1; - } - } - - return 1; - } - - /* e11 $ - | . */ - else if (cur_token.code == '.') - { + /* e11 $ + | . */ + case '.': strcat (intel_parser.disp, cur_token.str); intel_match_token (cur_token.code); /* Mark as a memory operand only if it's not already known to be an offset expression. */ - if (intel_parser.op_modifier != T_OFFSET) + if (!intel_parser.in_offset) intel_parser.is_mem = 1; return 1; - } - /* e11 register */ - else if (cur_token.code == T_REG) - { - const reg_entry *reg = intel_parser.reg = cur_token.reg; + /* e11 register */ + case T_REG: + { + const reg_entry *reg = intel_parser.reg = cur_token.reg; - intel_match_token (T_REG); + intel_match_token (T_REG); - /* Check for segment change. */ - if (cur_token.code == ':') - { - if (reg->reg_type & (SReg2 | SReg3)) - { - switch (reg->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; - } - } - else - { - as_bad (_("`%s' is not a valid segment register"), reg->reg_name); - return 0; - } - } + /* Check for segment change. */ + if (cur_token.code == ':') + { + if (!(reg->reg_type & (SReg2 | SReg3))) + { + as_bad (_("`%s' is not a valid segment register"), reg->reg_name); + return 0; + } + else if (i.seg[i.mem_operands]) + as_warn (_("Extra segment override ignored")); + else + { + if (!intel_parser.in_offset) + intel_parser.is_mem = 1; + switch (reg->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; + } + } + } - /* Not a segment register. Check for register scaling. */ - else if (cur_token.code == '*') - { - if (!intel_parser.is_mem) - { - as_bad (_("Register scaling only allowed in memory operands.")); - return 0; - } + /* Not a segment register. Check for register scaling. */ + else if (cur_token.code == '*') + { + if (!intel_parser.in_bracket) + { + as_bad (_("Register scaling only allowed in memory operands")); + return 0; + } - /* What follows must be a valid scale. */ - if (intel_match_token ('*') - && strchr ("01248", *cur_token.str)) - { - i.index_reg = reg; - i.types[this_operand] |= BaseIndex; + if (reg->reg_type & Reg16) /* Disallow things like [si*1]. */ + reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */ + else if (i.index_reg) + reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */ - /* Set the scale after setting the register (otherwise, - i386_scale will complain) */ - i386_scale (cur_token.str); - intel_match_token (T_CONST); - } - else - { - as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), - cur_token.str); - return 0; - } - } + /* What follows must be a valid scale. */ + intel_match_token ('*'); + i.index_reg = reg; + i.types[this_operand] |= BaseIndex; - /* No scaling. If this is a memory operand, the register is either a - base register (first occurrence) or an index register (second - occurrence). */ - else if (intel_parser.is_mem && !(reg->reg_type & (SReg2 | SReg3))) - { - if (i.base_reg && i.index_reg) - { - as_bad (_("Too many register references in memory operand.")); + /* Set the scale after setting the register (otherwise, + i386_scale will complain) */ + if (cur_token.code == '+' || cur_token.code == '-') + { + char *str, sign = cur_token.code; + intel_match_token (cur_token.code); + if (cur_token.code != T_CONST) + { + as_bad (_("Syntax error: Expecting a constant, got `%s'"), + cur_token.str); + return 0; + } + str = (char *) xmalloc (strlen (cur_token.str) + 2); + strcpy (str + 1, cur_token.str); + *str = sign; + if (!i386_scale (str)) + return 0; + free (str); + } + else if (!i386_scale (cur_token.str)) return 0; - } + intel_match_token (cur_token.code); + } - if (i.base_reg == NULL) - i.base_reg = reg; - else - i.index_reg = reg; + /* No scaling. If this is a memory operand, the register is either a + base register (first occurrence) or an index register (second + occurrence). */ + else if (intel_parser.in_bracket && !(reg->reg_type & (SReg2 | SReg3))) + { - i.types[this_operand] |= BaseIndex; - } + if (!i.base_reg) + i.base_reg = reg; + else if (!i.index_reg) + i.index_reg = reg; + else + { + as_bad (_("Too many register references in memory operand")); + return 0; + } - /* Offset modifier. Add the register to the displacement string to be - parsed as an immediate expression after we're done. */ - else if (intel_parser.op_modifier == T_OFFSET) - strcat (intel_parser.disp, reg->reg_name); + i.types[this_operand] |= BaseIndex; + } - /* It's neither base nor index nor offset. */ - else - { - i.types[this_operand] |= reg->reg_type & ~BaseIndex; - i.op[this_operand].regs = reg; - i.reg_operands++; - } + /* Offset modifier. Add the register to the displacement string to be + parsed as an immediate expression after we're done. */ + else if (intel_parser.in_offset) + { + as_warn (_("Using register names in OFFSET expressions is deprecated")); + strcat (intel_parser.disp, reg->reg_name); + } - /* Since registers are not part of the displacement string (except - when we're parsing offset operands), we may need to remove any - preceding '+' from the displacement string. */ - if (*intel_parser.disp != '\0' - && intel_parser.op_modifier != T_OFFSET) - { - char *s = intel_parser.disp; - s += strlen (s) - 1; - if (*s == '+') - *s = '\0'; - } + /* It's neither base nor index nor offset. */ + else if (!intel_parser.is_mem) + { + i.types[this_operand] |= reg->reg_type & ~BaseIndex; + i.op[this_operand].regs = reg; + i.reg_operands++; + } + else + { + as_bad (_("Invalid use of register")); + return 0; + } - return 1; - } + /* Since registers are not part of the displacement string (except + when we're parsing offset operands), we may need to remove any + preceding '+' from the displacement string. */ + if (*intel_parser.disp != '\0' + && !intel_parser.in_offset) + { + char *s = intel_parser.disp; + s += strlen (s) - 1; + if (*s == '+') + *s = '\0'; + } - /* e11 id */ - else if (cur_token.code == T_ID) - { - /* Add the identifier to the displacement string. */ - strcat (intel_parser.disp, cur_token.str); + return 1; + } + + /* e11 BYTE + | WORD + | DWORD + | FWORD + | QWORD + | TBYTE + | OWORD + | XMMWORD */ + case T_BYTE: + case T_WORD: + case T_DWORD: + case T_FWORD: + case T_QWORD: + case T_TBYTE: + case T_XMMWORD: + intel_match_token (cur_token.code); - /* The identifier represents a memory reference only if it's not - preceded by an offset modifier and if it's not an equate. */ - if (intel_parser.op_modifier != T_OFFSET) + if (cur_token.code == T_PTR) + return 1; + + /* It must have been an identifier. */ + intel_putback_token (); + cur_token.code = T_ID; + /* FALLTHRU */ + + /* e11 id + | constant */ + case T_ID: + if (!intel_parser.in_offset && intel_parser.is_mem <= 0) { symbolS *symbolP; + /* The identifier represents a memory reference only if it's not + preceded by an offset modifier and if it's not an equate. */ symbolP = symbol_find(cur_token.str); if (!symbolP || S_GET_SEGMENT(symbolP) != absolute_section) intel_parser.is_mem = 1; } + /* FALLTHRU */ - intel_match_token (T_ID); - return 1; - } - - /* e11 constant */ - else if (cur_token.code == T_CONST - || cur_token.code == '-' - || cur_token.code == '+') - { - char *save_str; + case T_CONST: + case '-': + case '+': + { + char *save_str, sign = 0; - /* Allow constants that start with `+' or `-'. */ - if (cur_token.code == '-' || cur_token.code == '+') - { - strcat (intel_parser.disp, cur_token.str); - intel_match_token (cur_token.code); - if (cur_token.code != T_CONST) - { - as_bad (_("Syntax error. Expecting a constant. Got `%s'."), - cur_token.str); - return 0; - } - } + /* Allow constants that start with `+' or `-'. */ + if (cur_token.code == '-' || cur_token.code == '+') + { + sign = cur_token.code; + intel_match_token (cur_token.code); + if (cur_token.code != T_CONST) + { + as_bad (_("Syntax error: Expecting a constant, got `%s'"), + cur_token.str); + return 0; + } + } - save_str = (char *) malloc (strlen (cur_token.str) + 1); - if (save_str == NULL) - abort (); - strcpy (save_str, cur_token.str); + save_str = (char *) xmalloc (strlen (cur_token.str) + 2); + strcpy (save_str + !!sign, cur_token.str); + if (sign) + *save_str = sign; - /* Get the next token to check for register scaling. */ - intel_match_token (cur_token.code); + /* Get the next token to check for register scaling. */ + intel_match_token (cur_token.code); - /* Check if this constant is a scaling factor for an index register. */ - if (cur_token.code == '*') - { - if (intel_match_token ('*') && cur_token.code == T_REG) - { - if (!intel_parser.is_mem) - { - as_bad (_("Register scaling only allowed in memory operands.")); + /* Check if this constant is a scaling factor for an index register. */ + if (cur_token.code == '*') + { + if (intel_match_token ('*') && cur_token.code == T_REG) + { + const reg_entry *reg = cur_token.reg; + + if (!intel_parser.in_bracket) + { + as_bad (_("Register scaling only allowed in memory operands")); + return 0; + } + + if (reg->reg_type & Reg16) /* Disallow things like [1*si]. */ + reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */ + else if (i.index_reg) + reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */ + + /* The constant is followed by `* reg', so it must be + a valid scale. */ + i.index_reg = reg; + i.types[this_operand] |= BaseIndex; + + /* Set the scale after setting the register (otherwise, + i386_scale will complain) */ + if (!i386_scale (save_str)) return 0; - } - - /* The constant is followed by `* reg', so it must be - a valid scale. */ - if (strchr ("01248", *save_str)) - { - i.index_reg = cur_token.reg; - i.types[this_operand] |= BaseIndex; + intel_match_token (T_REG); - /* Set the scale after setting the register (otherwise, - i386_scale will complain) */ - i386_scale (save_str); - intel_match_token (T_REG); - - /* Since registers are not part of the displacement - string, we may need to remove any preceding '+' from - the displacement string. */ - if (*intel_parser.disp != '\0') - { - char *s = intel_parser.disp; - s += strlen (s) - 1; - if (*s == '+') - *s = '\0'; - } - - free (save_str); - - return 1; - } - else - return 0; - } - - /* The constant was not used for register scaling. Since we have - already consumed the token following `*' we now need to put it - back in the stream. */ - else + /* Since registers are not part of the displacement + string, we may need to remove any preceding '+' from + the displacement string. */ + if (*intel_parser.disp != '\0') + { + char *s = intel_parser.disp; + s += strlen (s) - 1; + if (*s == '+') + *s = '\0'; + } + + free (save_str); + + return 1; + } + + /* The constant was not used for register scaling. Since we have + already consumed the token following `*' we now need to put it + back in the stream. */ intel_putback_token (); - } + } - /* Add the constant to the displacement string. */ - strcat (intel_parser.disp, save_str); - free (save_str); + /* Add the constant to the displacement string. */ + strcat (intel_parser.disp, save_str); + free (save_str); - return 1; + return 1; + } } as_bad (_("Unrecognized token '%s'"), cur_token.str); @@ -6473,9 +6591,7 @@ intel_get_token () /* The new token cannot be larger than the remainder of the operand string. */ - new_token.str = (char *) malloc (strlen (intel_parser.op_string) + 1); - if (new_token.str == NULL) - abort (); + new_token.str = (char *) xmalloc (strlen (intel_parser.op_string) + 1); new_token.str[0] = '\0'; if (strchr ("0123456789", *intel_parser.op_string)) @@ -6595,7 +6711,13 @@ intel_get_token () /* ??? This is not mentioned in the MASM grammar. */ else if (strcasecmp (new_token.str, "FLAT") == 0) - new_token.code = T_OFFSET; + { + new_token.code = T_OFFSET; + if (*q == ':') + strcat (new_token.str, ":"); + else + as_bad (_("`:' expected")); + } else new_token.code = T_ID; @@ -6630,8 +6752,11 @@ intel_get_token () static void intel_putback_token () { - intel_parser.op_string -= strlen (cur_token.str); - free (cur_token.str); + if (cur_token.code != T_NIL) + { + intel_parser.op_string -= strlen (cur_token.str); + free (cur_token.str); + } cur_token = prev_token; /* Forget prev_token. */ --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intel.d 2004-07-23 14:45:29.000000000 +0200 +++ 2005-03-14/gas/testsuite/gas/i386/intel.d 2005-03-14 13:52:53.129407904 +0100 @@ -1,6 +1,7 @@ #as: -J #objdump: -dw #name: i386 intel +#stderr: intel.e .*: +file format .* --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intel.e 1970-01-01 01:00:00.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/intel.e 2005-03-14 09:49:39.000000000 +0100 @@ -0,0 +1,8 @@ +.*: Assembler messages: +.*:154: Warning: Treating .\[0x90909090\]. as memory reference +.*:155: Warning: Treating .\[0x90909090\]. as memory reference +.*:156: Warning: Treating .\[0x90909090\]. as memory reference +.*:157: Warning: Treating .\[0x90909090\]. as memory reference +.*:492: Warning: Treating .\[0x90909090\]. as memory reference +.*:493: Warning: Treating .\[0x90909090\]. as memory reference +.*:580: Warning: Using register names in OFFSET expressions is deprecated --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intel16.d 2005-01-18 10:43:34.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/intel16.d 2005-03-11 17:33:40.000000000 +0100 @@ -1,5 +1,6 @@ #objdump: -dw -mi8086 #name: i386 intel16 +#stderr: intel16.e .*: +file format .* @@ -12,4 +13,12 @@ Disassembly of section .text: 11: 66 0f b7 06 00 00 [ ]*movzwl 0,%eax 17: 66 0f b6 06 00 00 [ ]*movzbl 0,%eax 1d: 0f b6 06 00 00 [ ]*movzbw 0,%ax -#pass + 22: 8d 00 [ ]*lea \(%bx,%si\),%ax + 24: 8d 02 [ ]*lea \(%bp,%si\),%ax + 26: 8d 01 [ ]*lea \(%bx,%di\),%ax + 28: 8d 03 [ ]*lea \(%bp,%di\),%ax + 2a: 8d 00 [ ]*lea \(%bx,%si\),%ax + 2c: 8d 02 [ ]*lea \(%bp,%si\),%ax + 2e: 8d 01 [ ]*lea \(%bx,%di\),%ax + 30: 8d 03 [ ]*lea \(%bp,%di\),%ax + ... --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intel16.e 1970-01-01 01:00:00.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/intel16.e 2005-03-11 17:04:36.000000000 +0100 @@ -0,0 +1,7 @@ +.*: Assembler messages: +.*:5: Warning: Treating .word ptr \[0\]. as memory reference +.*:6: Warning: Treating .byte ptr \[0\]. as memory reference +.*:7: Warning: Treating .byte ptr \[0\]. as memory reference +.*:8: Warning: Treating .word ptr \[0\]. as memory reference +.*:9: Warning: Treating .byte ptr \[0\]. as memory reference +.*:10: Warning: Treating .byte ptr \[0\]. as memory reference --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intel16.s 2002-07-08 12:40:37.000000000 +0200 +++ 2005-03-14/gas/testsuite/gas/i386/intel16.s 2005-03-11 17:09:30.000000000 +0100 @@ -8,4 +8,14 @@ movzx eax,word ptr [0] movzx eax,byte ptr [0] movzx ax,byte ptr [0] + + lea ax, [si+bx] + lea ax, [si+bp] + lea ax, [di+bx] + lea ax, [di+bp] + lea ax, [si][bx] + lea ax, [si][bp] + lea ax, [di][bx] + lea ax, [di][bp] + .p2align 4,0 --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intelbad.l 2004-07-23 13:46:36.000000000 +0200 +++ 2005-03-14/gas/testsuite/gas/i386/intelbad.l 2005-03-14 13:55:01.026964520 +0100 @@ -59,3 +59,53 @@ .*:89: Error: .* .*:90: Error: .* .*:91: Error: .* +.*:94: Error: .* +.*:95: Error: .* +.*:96: Error: .* +.*:97: Error: .* +.*:98: Error: .* +.*:99: Error: .* +.*:100: Error: .* +.*:101: Error: .* +.*:102: Error: .* +.*:103: Error: .* +.*:104: Error: .* +.*:105: Error: .* +.*:106: Error: .* +.*:107: Error: .* +.*:108: Error: .* +.*:109: Error: .* +.*:110: Error: .* +.*:111: Error: .* +.*:112: Error: .* +.*:113: Error: .* +.*:114: Error: .* +.*:115: Error: .* +.*:116: Error: .* +.*:117: Error: .* +.*:118: Error: .* +.*:119: Error: .* +.*:120: Error: .* +.*:121: Error: .* +.*:122: Error: .* +.*:123: Error: .* +.*:124: Error: .* +.*:125: Error: .* +.*:126: Error: .* +.*:127: Error: .* +.*:128: Error: .* +#... +.*:129: Error: .* +#... +.*:130: Error: .* +.*:131: Error: .* +.*:132: Error: .* +.*:133: Error: .* +.*:135: Warning: .* +.*:136: Warning: .* +.*:137: Warning: .* +.*:138: Warning: .* +.*:139: Warning: .* +.*:141: Error: .* +.*:142: Warning: .* +.*:142: Error: .* --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intelbad.s 2004-07-23 13:46:19.000000000 +0200 +++ 2005-03-14/gas/testsuite/gas/i386/intelbad.s 2005-03-14 13:54:45.989250600 +0100 @@ -89,3 +89,54 @@ start: push 1 1 push 1 + push 1 * * 1 + + # memory references + mov eax, [ecx*3] + mov eax, [3*ecx] + mov eax, [-1*ecx + 1] + mov eax, [esp + esp] + mov eax, [eax - 1*ecx + 1] + mov eax, [(eax-1) * (eax-1)] + mov eax, [eax-1 xor eax-1] + mov eax, [(eax-1) xor (eax-1)] + mov eax, [not eax + 1] + mov eax, [ecx*2 + edx*4] + mov eax, [2*ecx + 4*edx] + mov eax, [eax]1[ecx] # ugly diag + mov eax, [eax][ecx]1 # ugly diag + mov eax, eax[ecx] # ugly diag + mov eax, es[ecx] + mov eax, cr0[ecx] + mov eax, [eax]ecx + mov eax, [eax]+ecx + mov eax, [eax]+ecx*2 + mov eax, [eax]+2*ecx + mov eax, [[eax]ecx] + mov eax, eax:[ecx] + lea eax, [bx+si*1] + lea eax, [bp+si*2] + lea eax, [bx+di*4] + lea eax, [bp+di*8] + lea eax, [bx+1*si] + lea eax, [bp+2*si] + lea eax, [bx+4*di] + lea eax, [bp+8*di] + mov eax, [ah] + mov eax, [ax] + mov eax, [eax+bx] + mov eax, offset [1*eax] + mov eax, offset 1*eax + mov eax, offset x[eax] # ugly diag + mov eax, offset [x][eax] # ugly diag + mov eax, flat x + mov eax, flat [x] + mov eax, es:eax + + mov eax, offset [eax] + mov eax, offset eax + mov eax, offset offset eax + mov eax, es:ss:[eax] + mov eax, es:[eax]+ss:[eax] + + mov eax, 3:5 + call 3:[5] --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intelok.d 2005-03-01 09:38:13.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/intelok.d 2005-03-14 11:24:25.000000000 +0100 @@ -1,6 +1,7 @@ #as: -J -#objdump: -drwMintel +#objdump: -dwMintel #name: i386 intel-ok +#stderr: intelok.e .*: +file format .* @@ -93,20 +94,39 @@ Disassembly of section .text: [ ]*[0-9a-f]+: d7[ ]+xlat(b|[ ]+(BYTE PTR )?(ds:)?\[ebx\]) [ ]*[0-9a-f]+: d7[ ]+xlat(b|[ ]+(BYTE PTR )?(ds:)?\[ebx\]) [ ]*[0-9a-f]+: d7[ ]+xlat(b|[ ]+(BYTE PTR )?(ds:)?\[ebx\]) -[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+byte -[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+byte +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1\] +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1\] [ ]*[0-9a-f]+: 8b 40 04[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+4\] [ ]*[0-9a-f]+: 8b 40 04[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+4\] -[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+fword -[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+fword -[ ]*[0-9a-f]+: 8b 80 04 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+4\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+qword -[ ]*[0-9a-f]+: 8b 80 04 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+4\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+qword -[ ]*[0-9a-f]+: 8b 80 08 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+8\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+tbyte -[ ]*[0-9a-f]+: 8b 80 08 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+8\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+tbyte -#[ ]*[0-9a-f]+: 8b 04 85 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+word -#[ ]*[0-9a-f]+: 8b 04 85 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+word -#[ ]*[0-9a-f]+: 8b 04 85 04 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+4\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+xmmword -#[ ]*[0-9a-f]+: 8b 04 85 04 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+4\][ ]+[0-9a-f]+:[ ]+(R_386_|dir)?32[ ]+xmmword +[ ]*[0-9a-f]+: 8b 40 06[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+6\] +[ ]*[0-9a-f]+: 8b 40 06[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+6\] +[ ]*[0-9a-f]+: 8b 40 0c[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+12\] +[ ]*[0-9a-f]+: 8b 40 0c[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+12\] +[ ]*[0-9a-f]+: 8b 40 12[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+18\] +[ ]*[0-9a-f]+: 8b 40 12[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+18\] +[ ]*[0-9a-f]+: 8b 04 85 02 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+2\] +[ ]*[0-9a-f]+: 8b 04 85 02 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+2\] +[ ]*[0-9a-f]+: 8b 04 45 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*2\] +[ ]*[0-9a-f]+: 8b 04 45 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*2\] +[ ]*[0-9a-f]+: 8b 04 8d 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[ecx\*4\] +[ ]*[0-9a-f]+: 8b 04 8d 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[ecx\*4\] +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1\] +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1\] +[ ]*[0-9a-f]+: 8b 44 08 fb[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\-5\] +[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+1\] +[ ]*[0-9a-f]+: 8b 44 08 0f[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+15\] +[ ]*[0-9a-f]+: 8b 40 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+16\] +[ ]*[0-9a-f]+: 8b 40 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+16\] +[ ]*[0-9a-f]+: 8b 44 08 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+16\] +[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+1\] +[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+1\] +[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+1\] +[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+1\] +[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\+1\] +[ ]*[0-9a-f]+: 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\] +[ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\] +[ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\] +[ ]*[0-9a-f]+: 26 8b 00[ ]+mov[ ]+eax,es:(DWORD PTR )?\[eax\] [ ]*[0-9a-f]+: 6a 01[ ]+push[ ]+0x1 [ ]*[0-9a-f]+: 6a ff[ ]+push[ ]+0xffffffff [ ]*[0-9a-f]+: 6a fe[ ]+push[ ]+0xfffffffe @@ -120,4 +140,35 @@ Disassembly of section .text: [ ]*[0-9a-f]+: 6a 02[ ]+push[ ]+0x2 [ ]*[0-9a-f]+: 6a 03[ ]+push[ ]+0x3 [ ]*[0-9a-f]+: 6a 0d[ ]+push[ ]+0xd +[ ]*[0-9a-f]+: 6a 04[ ]+push[ ]+0x4 +[ ]*[0-9a-f]+: 6a fc[ ]+push[ ]+0xfffffffc +[ ]*[0-9a-f]+: 6a fb[ ]+push[ ]+0xfffffffb +[ ]*[0-9a-f]+: 6a fb[ ]+push[ ]+0xfffffffb +[ ]*[0-9a-f]+: 6a 03[ ]+push[ ]+0x3 +[ ]*[0-9a-f]+: 6a 04[ ]+push[ ]+0x4 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\] +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1] +[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\] +[ ]*[0-9a-f]+: 8b 80 01 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1\] +[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\] +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+1\] +[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:0x1 +[ ]*[0-9a-f]+: a1 ff ff ff ff[ ]+mov[ ]+eax,ds:0xffffffff +[ ]*[0-9a-f]+: 26 a1 02 00 00 00[ ]+mov[ ]+eax,es:0x2 +#... +[ ]*[0-9a-f]+: b8 03 00 00 00[ ]+mov[ ]+eax,0x3 +[ ]*[0-9a-f]+: a1 04 00 00 00[ ]+mov[ ]+eax,ds:0x4 +[ ]*[0-9a-f]+: a1 05 00 00 00[ ]+mov[ ]+eax,ds:0x5 +[ ]*[0-9a-f]+: 36 a1 06 00 00 00[ ]+mov[ ]+eax,ss:0x6 +[ ]*[0-9a-f]+: 36 a1 07 00 00 00[ ]+mov[ ]+eax,ss:0x7 +[ ]*[0-9a-f]+: a1 08 00 00 00[ ]+mov[ ]+eax,ds:0x8 +[ ]*[0-9a-f]+: 9a 05 00 00 00 03 00[ ]+l?call[ ]+0x3[,:]0x5 +[ ]*[0-9a-f]+: ea 03 00 00 00 05 00[ ]+l?jmp[ ]+0x5[,:]0x3 #pass --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intelok.e 1970-01-01 01:00:00.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/intelok.e 2005-03-11 17:30:54.000000000 +0100 @@ -0,0 +1,8 @@ +.*: Assembler messages: +.*:170: Warning: .* taken to mean just .* +.*:177: Warning: Treating .* as memory reference +.*:178: Warning: .* taken to mean just .* +.*:178: Warning: Treating .* as memory reference +.*:181: Warning: Treating .* as memory reference +.*:182: Warning: Treating .* as memory reference +.*:185: Warning: Treating .* as memory reference --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/intelok.s 2005-03-01 09:31:12.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/intelok.s 2005-03-14 11:22:05.000000000 +0100 @@ -1,5 +1,12 @@ .intel_syntax noprefix + .equiv byte, 1 + .equiv word, 2 .equiv dword, 4 + .equiv fword, 6 + .equiv qword, 8 + .equiv tbyte, 10 + .equiv oword, 16 + .equiv xmmword, 16 .text start: @@ -104,10 +111,30 @@ start: mov eax, qword[eax+dword] mov eax, [tbyte+eax+dword*2] mov eax, tbyte[eax+dword*2] -# mov eax, [word+eax*dword] -# mov eax, word[eax*dword] -# mov eax, [xmmword+(eax+1)*dword] -# mov eax, xmmword[(eax+1)*dword] + mov eax, [word+eax*dword] + mov eax, word[eax*dword] + + mov eax, [eax*+2] + mov eax, [+2*eax] + mov eax, [ecx*dword] + mov eax, [dword*ecx] + mov eax, 1[eax] + mov eax, [eax]+1 + mov eax, [eax - 5 + ecx] + mov eax, [eax + 5 and 3 + ecx] + mov eax, [eax + 5*3 + ecx] + mov eax, [oword][eax] + mov eax, [eax][oword] + mov eax, xmmword[eax][ecx] + mov eax, [eax]+1[ecx] + mov eax, [eax][ecx]+1 + mov eax, [1][eax][ecx] + mov eax, [eax][1][ecx] + mov eax, [eax][ecx][1] + mov eax, [[eax]] + mov eax, [eax[ecx]] + mov eax, [[eax][ecx]] + mov eax, es:[eax] # expressions @@ -125,5 +152,41 @@ start: push 7 xor 4 push 8 or 5 + push +dword + push -dword + push not dword + push not +dword + push not -dword + push not not dword + + # offset expressions + + mov eax, offset x + mov eax, offset flat:x + mov eax, flat:x + mov eax, offset [x] + mov eax, offset flat:[x] + mov eax, flat:[x] + mov eax, [offset x] + mov eax, [eax + offset x] + mov eax, [eax + offset 1] + mov eax, [offset x + eax] + mov eax, offset x+1[eax] + mov eax, [eax] + offset x + mov eax, [eax] + offset 1 + mov eax, offset x + [1] + mov eax, [offset x] - [1] + mov eax, offset x + es:[2] + mov eax, offset x + offset es:[3] + mov eax, [4] + offset x + mov eax, [5] + [offset x] + mov eax, ss:[6] + offset x + mov eax, ss:[7] + [offset x] + mov eax, dword ptr [8] + + # other operands + call 3:5 + jmp 5:3 + # Force a good alignment. .p2align 4,0 --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/x86_64.d 2005-01-18 10:43:35.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/x86_64.d 2005-03-14 13:50:35.506329792 +0100 @@ -1,6 +1,7 @@ #as: -J #objdump: -dw #name: i386 x86_64 +#stderr: x86_64.e .*: +file format .* Disassembly of section .text: --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/x86_64.e 1970-01-01 01:00:00.000000000 +0100 +++ 2005-03-14/gas/testsuite/gas/i386/x86_64.e 2005-03-14 11:39:16.000000000 +0100 @@ -0,0 +1,9 @@ +.*.s: Assembler messages: +.*:51: Warning: Treating .\[0x22222222\]. as memory reference +.*:89: Warning: Treating .DWORD PTR \[0x22222222\]. as memory reference +.*:91: Warning: Treating .\[0x8877665544332211\]. as memory reference +.*:92: Warning: Treating .\[0x8877665544332211\]. as memory reference +.*:93: Warning: Treating .\[0x8877665544332211\]. as memory reference +.*:94: Warning: Treating .\[0x8877665544332211\]. as memory reference +.*:95: Warning: Treating .\[0x8877665544332211\]. as memory reference +.*:96: Warning: Treating .\[0x8877665544332211\]. as memory reference --- /home/jbeulich/src/binutils/mainline/2005-03-14/gas/testsuite/gas/i386/x86_64.s 2004-06-01 10:59:08.000000000 +0200 +++ 2005-03-14/gas/testsuite/gas/i386/x86_64.s 2005-03-14 11:40:44.000000000 +0100 @@ -127,12 +127,12 @@ mov symbol(%rip), %eax .intel_syntax noprefix #immediates - various sizes: -mov al, flat symbol -mov ax, flat symbol -mov eax, flat symbol -mov rax, flat symbol +mov al, flat:symbol +mov ax, flat:symbol +mov eax, flat:symbol +mov rax, flat:symbol -#parts aren't supported by the parser +#parts aren't supported by the parser, yet (and not at all for symbol refs) #mov eax, high part symbol #mov eax, low part symbol