mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2026-08-27 00:26:02 -04:00
x86: improve matching diagnostics when %st is involved
Diagnosing operand size vs operand type mismatches doesn't work very well when GPRs and FPRs are in the same register class, distinguished just by size. Introduce a separate RegFP class.
This commit is contained in:
parent
a7148a799b
commit
101b4bb8f4
8 changed files with 7476 additions and 7440 deletions
|
|
@ -2497,8 +2497,8 @@ operand_type_check (i386_operand_type t, enum operand_type c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 if there is no conflict in 8bit/16bit/32bit/64bit/80bit size
|
||||
between operand GIVEN and opeand WANTED for instruction template T. */
|
||||
/* Return 1 if there is no conflict in 8bit/16bit/32bit/64bit size
|
||||
between operand GIVEN and operand WANTED for instruction template T. */
|
||||
|
||||
static INLINE int
|
||||
match_operand_size (const insn_template *t, unsigned int wanted,
|
||||
|
|
@ -2518,13 +2518,22 @@ match_operand_size (const insn_template *t, unsigned int wanted,
|
|||
|| (intel_syntax
|
||||
&& flag_code != CODE_64BIT
|
||||
&& (t->operand_types[wanted].bitfield.class == Reg
|
||||
|| t->opcode_modifier.isstring))))
|
||||
|| (i.types[given].bitfield.tbyte
|
||||
&& !t->operand_types[wanted].bitfield.tbyte));
|
||||
|| t->opcode_modifier.isstring)))));
|
||||
}
|
||||
|
||||
/* Return 1 if there is no conflict in 80bit size
|
||||
between operand GIVEN and operand WANTED for instruction template T. */
|
||||
|
||||
static INLINE int
|
||||
match_fp_size (const insn_template *t, unsigned int wanted,
|
||||
unsigned int given)
|
||||
{
|
||||
return !i.types[given].bitfield.tbyte
|
||||
|| t->operand_types[wanted].bitfield.tbyte;
|
||||
}
|
||||
|
||||
/* Return 1 if there is no conflict in SIMD register between operand
|
||||
GIVEN and opeand WANTED for instruction template T. */
|
||||
GIVEN and operand WANTED for instruction template T. */
|
||||
|
||||
static INLINE int
|
||||
match_simd_size (const insn_template *t, unsigned int wanted,
|
||||
|
|
@ -2541,13 +2550,15 @@ match_simd_size (const insn_template *t, unsigned int wanted,
|
|||
}
|
||||
|
||||
/* Return 1 if there is no conflict in any size between operand GIVEN
|
||||
and opeand WANTED for instruction template T. */
|
||||
and operand WANTED for instruction template T. */
|
||||
|
||||
static INLINE int
|
||||
match_mem_size (const insn_template *t, unsigned int wanted,
|
||||
unsigned int given)
|
||||
{
|
||||
return (match_operand_size (t, wanted, given)
|
||||
&& (!i.types[given].bitfield.tbyte
|
||||
|| t->operand_types[wanted].bitfield.tbyte)
|
||||
&& !((i.types[given].bitfield.unspecified
|
||||
&& !i.broadcast.type
|
||||
&& !i.broadcast.bytes
|
||||
|
|
@ -2610,14 +2621,23 @@ operand_size_match (const insn_template *t)
|
|||
&& (t->operand_types[j].bitfield.byte
|
||||
|| t->operand_types[j].bitfield.word
|
||||
|| t->operand_types[j].bitfield.dword
|
||||
|| t->operand_types[j].bitfield.qword
|
||||
|| t->operand_types[j].bitfield.tbyte)))
|
||||
|| t->operand_types[j].bitfield.qword)))
|
||||
&& !match_operand_size (t, j, j))
|
||||
{
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i.types[j].bitfield.class == RegFP
|
||||
&& (t->operand_types[j].bitfield.class == RegFP
|
||||
|| (t->operand_types[j].bitfield.instance == Accum
|
||||
&& t->operand_types[j].bitfield.tbyte))
|
||||
&& !match_fp_size (t, j, j))
|
||||
{
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i.types[j].bitfield.class == RegSIMD
|
||||
&& (t->operand_types[j].bitfield.class == RegSIMD
|
||||
|| (t->operand_types[j].bitfield.instance == Accum
|
||||
|
|
@ -2667,6 +2687,13 @@ operand_size_match (const insn_template *t)
|
|||
&& !match_operand_size (t, j, given))
|
||||
return match;
|
||||
|
||||
if (i.types[given].bitfield.class == RegFP
|
||||
&& (t->operand_types[j].bitfield.class == RegFP
|
||||
|| (t->operand_types[j].bitfield.instance == Accum
|
||||
&& t->operand_types[j].bitfield.tbyte))
|
||||
&& !match_fp_size (t, j, given))
|
||||
return match;
|
||||
|
||||
/* No need to check for Accum here: There are no such templates with D
|
||||
set. */
|
||||
if (i.types[given].bitfield.class == RegSIMD
|
||||
|
|
@ -3602,14 +3629,14 @@ md_begin (void)
|
|||
if (regtab->reg_type.bitfield.instance == Accum)
|
||||
reg_eax = regtab;
|
||||
}
|
||||
else if (regtab->reg_type.bitfield.tbyte)
|
||||
{
|
||||
/* There's no point inserting st(<N>) in the hash table, as
|
||||
parentheses aren't included in register_chars[] anyway. */
|
||||
if (regtab->reg_type.bitfield.instance != Accum)
|
||||
continue;
|
||||
reg_st0 = regtab;
|
||||
}
|
||||
break;
|
||||
|
||||
case RegFP:
|
||||
/* There's no point inserting st(<N>) in the hash table, as
|
||||
parentheses aren't included in register_chars[] anyway. */
|
||||
if (regtab->reg_type.bitfield.instance != Accum)
|
||||
continue;
|
||||
reg_st0 = regtab;
|
||||
break;
|
||||
|
||||
case SReg:
|
||||
|
|
@ -3744,6 +3771,7 @@ pi (const char *line, i386_insn *x)
|
|||
pt (x->types[j]);
|
||||
fprintf (stdout, "\n");
|
||||
if (x->types[j].bitfield.class == Reg
|
||||
|| x->types[j].bitfield.class == RegFP
|
||||
|| x->types[j].bitfield.class == RegMMX
|
||||
|| x->types[j].bitfield.class == RegSIMD
|
||||
|| x->types[j].bitfield.class == RegMask
|
||||
|
|
@ -3852,7 +3880,7 @@ const type_names[] =
|
|||
{ { .bitfield = { .class = RegCR } }, "control reg" },
|
||||
{ { .bitfield = { .class = RegTR } }, "test reg" },
|
||||
{ { .bitfield = { .class = RegDR } }, "debug reg" },
|
||||
{ { .bitfield = { .class = Reg, .tbyte = 1 } }, "FReg" },
|
||||
{ { .bitfield = { .class = RegFP, .tbyte = 1 } }, "FReg" },
|
||||
{ { .bitfield = { .instance = Accum, .tbyte = 1 } }, "FAcc" },
|
||||
{ { .bitfield = { .class = SReg } }, "SReg" },
|
||||
{ { .bitfield = { .class = RegMMX } }, "rMMX" },
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
.*: Error: operand type mismatch for .bsf.
|
||||
.*: Error: operand type mismatch for .bswap.
|
||||
.*: Error: operand type mismatch for .bswap.
|
||||
.*: Error: operand type mismatch for .bswap.
|
||||
.*: Error: operand type mismatch for .fcomi.
|
||||
.*: Error: operand type mismatch for .fcomi.
|
||||
.*: Error: operand type mismatch for .in.
|
||||
.*: Error: operand type mismatch for .in.
|
||||
.*: Error: operand type mismatch for .movntdqa.
|
||||
.*: Error: operand type mismatch for .movntdq.
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@
|
|||
blendvps %eax, %xmm1, %xmm2
|
||||
blendvps %st, %xmm1, %xmm2
|
||||
bsf %eax, (%eax)
|
||||
bswap %st
|
||||
bswap %mm0
|
||||
bswapl %xmm0
|
||||
fcomi %st(1), %eax
|
||||
fcomi %st(1), %xmm0
|
||||
inl $0, %st
|
||||
inl $0, %xmm0
|
||||
movntdqa %xmm0, (%eax)
|
||||
movntdq (%eax), %xmm0
|
||||
|
|
|
|||
|
|
@ -540,6 +540,7 @@ static const struct {
|
|||
} operand_classes[] = {
|
||||
CLASS (Reg),
|
||||
CLASS (SReg),
|
||||
CLASS (RegFP),
|
||||
CLASS (RegCR),
|
||||
CLASS (RegDR),
|
||||
CLASS (RegTR),
|
||||
|
|
|
|||
|
|
@ -863,8 +863,9 @@ typedef struct i386_opcode_modifier
|
|||
enum operand_class
|
||||
{
|
||||
ClassNone,
|
||||
Reg, /* GPRs and FP regs, distinguished by operand size */
|
||||
Reg, /* GPRs, distinguished by operand size */
|
||||
SReg, /* Segment register */
|
||||
RegFP, /* FP regs */
|
||||
RegCR, /* Control register */
|
||||
RegDR, /* Debug register */
|
||||
RegTR, /* Test register */
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#define InOutPortReg RegD|Word
|
||||
|
||||
#define FloatAcc Acc|Tbyte
|
||||
#define FloatReg Class=Reg|Tbyte
|
||||
#define FloatReg Class=RegFP|Tbyte
|
||||
|
||||
#define SReg Class=SReg
|
||||
|
||||
|
|
|
|||
|
|
@ -367,14 +367,14 @@ eip, Dword, RegRex64, RegIP, 8, Dw2Inval
|
|||
riz, Qword|BaseIndex, RegRex64, RegIZ, Dw2Inval, Dw2Inval
|
||||
eiz, Dword|BaseIndex, 0, RegIZ, Dw2Inval, Dw2Inval
|
||||
// fp regs. No need for an explicit st(0) here.
|
||||
st, Class=Reg|Instance=Accum|Tbyte, 0, 0, 11, 33
|
||||
st(1), Class=Reg|Tbyte, 0, 1, 12, 34
|
||||
st(2), Class=Reg|Tbyte, 0, 2, 13, 35
|
||||
st(3), Class=Reg|Tbyte, 0, 3, 14, 36
|
||||
st(4), Class=Reg|Tbyte, 0, 4, 15, 37
|
||||
st(5), Class=Reg|Tbyte, 0, 5, 16, 38
|
||||
st(6), Class=Reg|Tbyte, 0, 6, 17, 39
|
||||
st(7), Class=Reg|Tbyte, 0, 7, 18, 40
|
||||
st, Class=RegFP|Instance=Accum|Tbyte, 0, 0, 11, 33
|
||||
st(1), Class=RegFP|Tbyte, 0, 1, 12, 34
|
||||
st(2), Class=RegFP|Tbyte, 0, 2, 13, 35
|
||||
st(3), Class=RegFP|Tbyte, 0, 3, 14, 36
|
||||
st(4), Class=RegFP|Tbyte, 0, 4, 15, 37
|
||||
st(5), Class=RegFP|Tbyte, 0, 5, 16, 38
|
||||
st(6), Class=RegFP|Tbyte, 0, 6, 17, 39
|
||||
st(7), Class=RegFP|Tbyte, 0, 7, 18, 40
|
||||
// Pseudo-register names only used in .cfi_* directives
|
||||
eflags, 0, 0, 0, 9, 49
|
||||
rflags, 0, 0, 0, Dw2Inval, 49
|
||||
|
|
|
|||
14824
opcodes/i386-tbl.h
14824
opcodes/i386-tbl.h
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue