Index: gas/config/tc-i386.c =================================================================== RCS file: /cvs/src/src/gas/config/tc-i386.c,v retrieving revision 1.354 diff -u -r1.354 tc-i386.c --- gas/config/tc-i386.c 12 Oct 2008 12:37:09 -0000 1.354 +++ gas/config/tc-i386.c 26 Nov 2008 17:48:43 -0000 @@ -424,6 +424,8 @@ } sse_check; +static int prefer_direction_flag = 0; + /* Register prefix used for error message. */ static const char *register_prefix = "%"; @@ -1357,6 +1359,8 @@ static const i386_operand_type acc32 = OPERAND_TYPE_ACC32; static const i386_operand_type acc64 = OPERAND_TYPE_ACC64; +static const i386_operand_type reg32 = OPERAND_TYPE_REG32; +static const i386_operand_type reg64 = OPERAND_TYPE_REG64; static const i386_operand_type control = OPERAND_TYPE_CONTROL; static const i386_operand_type inoutportreg = OPERAND_TYPE_INOUTPORTREG; @@ -3543,6 +3547,7 @@ unsigned int j; unsigned int found_cpu_match; unsigned int check_register; + unsigned int op0 = 0, op1 = 1; #if MAX_OPERANDS != 5 # error "MAX_OPERANDS must be 5." @@ -3712,16 +3717,28 @@ && operand_type_equal (&i.types [0], &acc32) && operand_type_equal (&i.types [1], &acc32)) continue; + if(prefer_direction_flag && t->opcode_modifier.d + && ((operand_type_equal (&i.types [0], ®32) && operand_type_equal (&i.types [1], ®32)) + || (operand_type_equal (&i.types [0], ®64) && operand_type_equal (&i.types [1], ®64)))) { + found_reverse_match = Opcode_D; + op0 = 1; + op1 = 0; + } else { + found_reverse_match = 0; + op0 = 0; + op1 = 1; + } + case 3: case 4: case 5: - overlap1 = operand_type_and (i.types[1], operand_types[1]); - if (!operand_type_match (overlap0, i.types[0]) - || !operand_type_match (overlap1, i.types[1]) + overlap1 = operand_type_and (i.types[op1], operand_types[1]); + if (!operand_type_match (overlap0, i.types[op0]) + || !operand_type_match (overlap1, i.types[op1]) || (check_register - && !operand_type_register_match (overlap0, i.types[0], + && !operand_type_register_match (overlap0, i.types[op0], operand_types[0], - overlap1, i.types[1], + overlap1, i.types[op1], operand_types[1]))) { /* Check if other direction is valid ... */ @@ -3729,16 +3746,16 @@ continue; /* Try reversing direction of operands. */ - overlap0 = operand_type_and (i.types[0], operand_types[1]); - overlap1 = operand_type_and (i.types[1], operand_types[0]); - if (!operand_type_match (overlap0, i.types[0]) - || !operand_type_match (overlap1, i.types[1]) + overlap0 = operand_type_and (i.types[op0], operand_types[1]); + overlap1 = operand_type_and (i.types[op1], operand_types[0]); + if (!operand_type_match (overlap0, i.types[op0]) + || !operand_type_match (overlap1, i.types[op1]) || (check_register && !operand_type_register_match (overlap0, - i.types[0], + i.types[op0], operand_types[1], overlap1, - i.types[1], + i.types[op1], operand_types[0]))) { /* Does not match either direction. */ @@ -3747,7 +3764,7 @@ /* found_reverse_match holds which of D or FloatDR we've found. */ if (t->opcode_modifier.d) - found_reverse_match = Opcode_D; + found_reverse_match ^= Opcode_D; else if (t->opcode_modifier.floatd) found_reverse_match = Opcode_FloatD; else @@ -3801,7 +3818,7 @@ if (!operand_type_match (overlap2, i.types[2]) || (check_register && !operand_type_register_match (overlap1, - i.types[1], + i.types[op1], operand_types[1], overlap2, i.types[2], @@ -7988,6 +8005,7 @@ #define OPTION_MOLD_GCC (OPTION_MD_BASE + 9) #define OPTION_MSSE2AVX (OPTION_MD_BASE + 10) #define OPTION_MSSE_CHECK (OPTION_MD_BASE + 11) +#define OPTION_PREFER_DIRECTION_FLAG (OPTION_MD_BASE + 12) struct option md_longopts[] = { @@ -8005,6 +8023,7 @@ {"mold-gcc", no_argument, NULL, OPTION_MOLD_GCC}, {"msse2avx", no_argument, NULL, OPTION_MSSE2AVX}, {"msse-check", required_argument, NULL, OPTION_MSSE_CHECK}, + {"mprefer-direction-flag", no_argument, NULL, OPTION_PREFER_DIRECTION_FLAG}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -8209,6 +8228,9 @@ as_fatal (_("Invalid -msse-check= option: `%s'"), arg); break; + case OPTION_PREFER_DIRECTION_FLAG: + prefer_direction_flag = 1; + break; default: return 0; } @@ -8275,6 +8297,9 @@ -mnaked-reg don't require `%%' prefix for registers\n")); fprintf (stream, _("\ -mold-gcc support old (<= 2.8.1) versions of gcc\n")); + fprintf (stream, _("\ + -mprefer-direction-flag prefer direction inversed instructions in register\n\ + to register operations\n")); } #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ Index: gas/doc/c-i386.texi =================================================================== RCS file: /cvs/src/src/gas/doc/c-i386.texi,v retrieving revision 1.30 diff -u -r1.30 c-i386.texi --- gas/doc/c-i386.texi 3 Sep 2008 15:44:33 -0000 1.30 +++ gas/doc/c-i386.texi 26 Nov 2008 17:48:43 -0000 @@ -170,6 +170,13 @@ @option{-msse-check=@var{error}} will make the assembler issue an error for any SSE intruction. +@cindex @samp{-mprefer-direction-flag} option, i386 +@cindex @samp{-mprefer-direction-flag} option, x86-64 +@item -mprefer-direction-flag +This option instructs the assembler to prefer direction inversed instructions for +register to register operations. For example, this will assemble "mov %esp, %ebp" +to "8b ec" instead of "89 e5". + @cindex @samp{-mmnemonic=} option, i386 @cindex @samp{-mmnemonic=} option, x86-64 @item -mmnemonic=@var{att}