diff -pruw binutils-orig/gas/config/tc-i386.c binutils-061211/gas/config/tc-i386.c --- binutils-orig/gas/config/tc-i386.c 2006-11-08 13:56:02.000000000 -0600 +++ binutils-061211/gas/config/tc-i386.c 2006-12-13 09:52:53.091344000 -0600 @@ -2568,12 +2568,16 @@ match_template () { /* Points to template once we've found it. */ const template *t; - unsigned int overlap0, overlap1, overlap2; + unsigned int overlap0, overlap1, overlap2, overlap3; unsigned int found_reverse_match; int suffix_check; - unsigned int operand_types [3]; + unsigned int operand_types [MAX_OPERANDS]; int addr_prefix_disp; +#if MAX_OPERANDS >=5 +# error "MAX_OPERANDS must be less than 5." +#endif + #define MATCH(overlap, given, template) \ ((overlap & ~JumpAbsolute) \ && (((given) & (BaseIndex | JumpAbsolute)) \ @@ -2590,10 +2594,12 @@ match_template () overlap0 = 0; overlap1 = 0; overlap2 = 0; + overlap3 = 0; found_reverse_match = 0; operand_types [0] = 0; operand_types [1] = 0; operand_types [2] = 0; + operand_types [3] = 0; addr_prefix_disp = -1; suffix_check = (i.suffix == BYTE_MNEM_SUFFIX ? No_bSuf @@ -2625,6 +2631,7 @@ match_template () operand_types [0] = t->operand_types [0]; operand_types [1] = t->operand_types [1]; operand_types [2] = t->operand_types [2]; + operand_types [3] = t->operand_types [3]; /* In general, don't allow 64-bit operands in 32-bit mode. */ if (i.suffix == QWORD_MNEM_SUFFIX @@ -2670,7 +2677,7 @@ match_template () break; } - for (j = 0; j < 3; j++) + for (j = 0; j < MAX_OPERANDS; j++) { /* There should be only one Disp operand. */ if ((operand_types[j] & DispOff)) @@ -2692,6 +2699,7 @@ match_template () break; case 2: case 3: + case 4: overlap1 = i.types[1] & operand_types[1]; if (!MATCH (overlap0, i.types[0], operand_types[0]) || !MATCH (overlap1, i.types[1], operand_types[1]) @@ -2726,9 +2734,21 @@ match_template () we've found. */ found_reverse_match = t->opcode_modifier & (D | FloatDR); } + else + { /* Found a forward 2 operand match here. */ - else if (t->operands == 3) + switch (t->operands) { + case 4: + overlap2 = i.types[2] & operand_types[2]; + overlap3 = i.types[3] & operand_types[3]; + if (!MATCH (overlap3, i.types[3], operand_types[3]) + || !CONSISTENT_REGISTER_MATCH (overlap2, i.types[2], + operand_types[2], + overlap3, i.types[3], + operand_types[3])) + continue; + case 3: /* Here we make use of the fact that there are no reverse match 3 operand instructions, and all 3 operand instructions only need to be checked for @@ -2741,8 +2761,11 @@ match_template () operand_types[2])) continue; + break; + } } - /* Found either forward/reverse 2 or 3 operand match here: + /* Found either forward/reverse 2, 3 or 3\4 operand match here: slip through to break. */ } if (t->cpu_flags & ~cpu_arch_flags)