x86: fix operand size checking
Currently mov to/from control, debug, and test register insns accept any size GPR operand (general pattern: templates with D set and both operands being registers in distinct register files). This is due to improper checking of the reverse case, including not informing the caller whether a straight and/or reverse match was successful. The helper functions need to be told two indexes: One to index the given operand types array, and the other to index the template one. The caller must attempt a further straight match only if the function reported a straight match (and respectively for reverse matches).
This commit is contained in:
parent
4ad422a635
commit
3ac21baa84
@ -1,3 +1,19 @@
|
|||||||
|
2018-07-16 Jan Beulich <jbeulich@suse.com>
|
||||||
|
|
||||||
|
* config/tc-i386.c (match_reg_size): Split second parameter
|
||||||
|
into two.
|
||||||
|
(match_simd_size): Likewise.
|
||||||
|
(match_mem_size): Likewise.
|
||||||
|
(MATCH_STRAIGHT, MATCH_REVERSE): Define.
|
||||||
|
(operand_size_match): Change return type. New local variable
|
||||||
|
"match". Always check for reverse match when opcode_modifier.d
|
||||||
|
is set.
|
||||||
|
(match_template) New local variable "size_match". Skip further
|
||||||
|
matching if operand_size_match() did not report a respective
|
||||||
|
match.
|
||||||
|
* testsuite/gas/i386/inval.s: Add control register reads/writes.
|
||||||
|
* testsuite/gas/i386/inval.l: Adjust expectations.
|
||||||
|
|
||||||
2018-07-13 Nick Clifton <nickc@redhat.com>
|
2018-07-13 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* testsuite/gas/elf/missing-build-notes.s: New test. Checks that
|
* testsuite/gas/elf/missing-build-notes.s: New test. Checks that
|
||||||
|
@ -1901,70 +1901,74 @@ operand_type_check (i386_operand_type t, enum operand_type c)
|
|||||||
operand J for instruction template T. */
|
operand J for instruction template T. */
|
||||||
|
|
||||||
static INLINE int
|
static INLINE int
|
||||||
match_reg_size (const insn_template *t, unsigned int j)
|
match_reg_size (const insn_template *t, unsigned int wanted, unsigned int given)
|
||||||
{
|
{
|
||||||
return !((i.types[j].bitfield.byte
|
return !((i.types[given].bitfield.byte
|
||||||
&& !t->operand_types[j].bitfield.byte)
|
&& !t->operand_types[wanted].bitfield.byte)
|
||||||
|| (i.types[j].bitfield.word
|
|| (i.types[given].bitfield.word
|
||||||
&& !t->operand_types[j].bitfield.word)
|
&& !t->operand_types[wanted].bitfield.word)
|
||||||
|| (i.types[j].bitfield.dword
|
|| (i.types[given].bitfield.dword
|
||||||
&& !t->operand_types[j].bitfield.dword)
|
&& !t->operand_types[wanted].bitfield.dword)
|
||||||
|| (i.types[j].bitfield.qword
|
|| (i.types[given].bitfield.qword
|
||||||
&& !t->operand_types[j].bitfield.qword)
|
&& !t->operand_types[wanted].bitfield.qword)
|
||||||
|| (i.types[j].bitfield.tbyte
|
|| (i.types[given].bitfield.tbyte
|
||||||
&& !t->operand_types[j].bitfield.tbyte));
|
&& !t->operand_types[wanted].bitfield.tbyte));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if there is no conflict in SIMD register on
|
/* Return 1 if there is no conflict in SIMD register on
|
||||||
operand J for instruction template T. */
|
operand J for instruction template T. */
|
||||||
|
|
||||||
static INLINE int
|
static INLINE int
|
||||||
match_simd_size (const insn_template *t, unsigned int j)
|
match_simd_size (const insn_template *t, unsigned int wanted, unsigned int given)
|
||||||
{
|
{
|
||||||
return !((i.types[j].bitfield.xmmword
|
return !((i.types[given].bitfield.xmmword
|
||||||
&& !t->operand_types[j].bitfield.xmmword)
|
&& !t->operand_types[wanted].bitfield.xmmword)
|
||||||
|| (i.types[j].bitfield.ymmword
|
|| (i.types[given].bitfield.ymmword
|
||||||
&& !t->operand_types[j].bitfield.ymmword)
|
&& !t->operand_types[wanted].bitfield.ymmword)
|
||||||
|| (i.types[j].bitfield.zmmword
|
|| (i.types[given].bitfield.zmmword
|
||||||
&& !t->operand_types[j].bitfield.zmmword));
|
&& !t->operand_types[wanted].bitfield.zmmword));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if there is no conflict in any size on operand J for
|
/* Return 1 if there is no conflict in any size on operand J for
|
||||||
instruction template T. */
|
instruction template T. */
|
||||||
|
|
||||||
static INLINE int
|
static INLINE int
|
||||||
match_mem_size (const insn_template *t, unsigned int j)
|
match_mem_size (const insn_template *t, unsigned int wanted, unsigned int given)
|
||||||
{
|
{
|
||||||
return (match_reg_size (t, j)
|
return (match_reg_size (t, wanted, given)
|
||||||
&& !((i.types[j].bitfield.unspecified
|
&& !((i.types[given].bitfield.unspecified
|
||||||
&& !i.broadcast
|
&& !i.broadcast
|
||||||
&& !t->operand_types[j].bitfield.unspecified)
|
&& !t->operand_types[wanted].bitfield.unspecified)
|
||||||
|| (i.types[j].bitfield.fword
|
|| (i.types[given].bitfield.fword
|
||||||
&& !t->operand_types[j].bitfield.fword)
|
&& !t->operand_types[wanted].bitfield.fword)
|
||||||
/* For scalar opcode templates to allow register and memory
|
/* For scalar opcode templates to allow register and memory
|
||||||
operands at the same time, some special casing is needed
|
operands at the same time, some special casing is needed
|
||||||
here. Also for v{,p}broadcast*, {,v}pmov{s,z}*, and
|
here. Also for v{,p}broadcast*, {,v}pmov{s,z}*, and
|
||||||
down-conversion vpmov*. */
|
down-conversion vpmov*. */
|
||||||
|| ((t->operand_types[j].bitfield.regsimd
|
|| ((t->operand_types[wanted].bitfield.regsimd
|
||||||
&& !t->opcode_modifier.broadcast
|
&& !t->opcode_modifier.broadcast
|
||||||
&& (t->operand_types[j].bitfield.byte
|
&& (t->operand_types[wanted].bitfield.byte
|
||||||
|| t->operand_types[j].bitfield.word
|
|| t->operand_types[wanted].bitfield.word
|
||||||
|| t->operand_types[j].bitfield.dword
|
|| t->operand_types[wanted].bitfield.dword
|
||||||
|| t->operand_types[j].bitfield.qword))
|
|| t->operand_types[wanted].bitfield.qword))
|
||||||
? (i.types[j].bitfield.xmmword
|
? (i.types[given].bitfield.xmmword
|
||||||
|| i.types[j].bitfield.ymmword
|
|| i.types[given].bitfield.ymmword
|
||||||
|| i.types[j].bitfield.zmmword)
|
|| i.types[given].bitfield.zmmword)
|
||||||
: !match_simd_size(t, j))));
|
: !match_simd_size(t, wanted, given))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if there is no size conflict on any operands for
|
/* Return value has MATCH_STRAIGHT set if there is no size conflict on any
|
||||||
instruction template T. */
|
operands for instruction template T, and it has MATCH_REVERSE set if there
|
||||||
|
is no size conflict on any operands for the template with operands reversed
|
||||||
|
(and the template allows for reversing in the first place). */
|
||||||
|
|
||||||
static INLINE int
|
#define MATCH_STRAIGHT 1
|
||||||
|
#define MATCH_REVERSE 2
|
||||||
|
|
||||||
|
static INLINE unsigned int
|
||||||
operand_size_match (const insn_template *t)
|
operand_size_match (const insn_template *t)
|
||||||
{
|
{
|
||||||
unsigned int j;
|
unsigned int j, match = MATCH_STRAIGHT;
|
||||||
int match = 1;
|
|
||||||
|
|
||||||
/* Don't check jump instructions. */
|
/* Don't check jump instructions. */
|
||||||
if (t->opcode_modifier.jump
|
if (t->opcode_modifier.jump
|
||||||
@ -1981,59 +1985,57 @@ operand_size_match (const insn_template *t)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (t->operand_types[j].bitfield.reg
|
if (t->operand_types[j].bitfield.reg
|
||||||
&& !match_reg_size (t, j))
|
&& !match_reg_size (t, j, j))
|
||||||
{
|
{
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->operand_types[j].bitfield.regsimd
|
if (t->operand_types[j].bitfield.regsimd
|
||||||
&& !match_simd_size (t, j))
|
&& !match_simd_size (t, j, j))
|
||||||
{
|
{
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->operand_types[j].bitfield.acc
|
if (t->operand_types[j].bitfield.acc
|
||||||
&& (!match_reg_size (t, j) || !match_simd_size (t, j)))
|
&& (!match_reg_size (t, j, j) || !match_simd_size (t, j, j)))
|
||||||
{
|
{
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.types[j].bitfield.mem && !match_mem_size (t, j))
|
if (i.types[j].bitfield.mem && !match_mem_size (t, j, j))
|
||||||
{
|
{
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match)
|
if (!t->opcode_modifier.d)
|
||||||
return match;
|
|
||||||
else if (!t->opcode_modifier.d)
|
|
||||||
{
|
{
|
||||||
mismatch:
|
mismatch:
|
||||||
i.error = operand_size_mismatch;
|
if (!match)
|
||||||
return 0;
|
i.error = operand_size_mismatch;
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check reverse. */
|
/* Check reverse. */
|
||||||
gas_assert (i.operands == 2);
|
gas_assert (i.operands == 2);
|
||||||
|
|
||||||
match = 1;
|
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
if ((t->operand_types[j].bitfield.reg
|
if ((t->operand_types[j].bitfield.reg
|
||||||
|| t->operand_types[j].bitfield.acc)
|
|| t->operand_types[j].bitfield.acc)
|
||||||
&& !match_reg_size (t, j ? 0 : 1))
|
&& !match_reg_size (t, j, !j))
|
||||||
goto mismatch;
|
goto mismatch;
|
||||||
|
|
||||||
if (i.types[j].bitfield.mem
|
if (i.types[!j].bitfield.mem
|
||||||
&& !match_mem_size (t, j ? 0 : 1))
|
&& !match_mem_size (t, j, !j))
|
||||||
goto mismatch;
|
goto mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return match | MATCH_REVERSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int
|
static INLINE int
|
||||||
@ -5286,7 +5288,7 @@ match_template (char mnem_suffix)
|
|||||||
i386_operand_type operand_types [MAX_OPERANDS];
|
i386_operand_type operand_types [MAX_OPERANDS];
|
||||||
int addr_prefix_disp;
|
int addr_prefix_disp;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
unsigned int found_cpu_match;
|
unsigned int found_cpu_match, size_match;
|
||||||
unsigned int check_register;
|
unsigned int check_register;
|
||||||
enum i386_error specific_error = 0;
|
enum i386_error specific_error = 0;
|
||||||
|
|
||||||
@ -5375,7 +5377,8 @@ match_template (char mnem_suffix)
|
|||||||
|| (t->opcode_modifier.no_ldsuf && mnemsuf_check.no_ldsuf))
|
|| (t->opcode_modifier.no_ldsuf && mnemsuf_check.no_ldsuf))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!operand_size_match (t))
|
size_match = operand_size_match (t);
|
||||||
|
if (!size_match)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j = 0; j < MAX_OPERANDS; j++)
|
for (j = 0; j < MAX_OPERANDS; j++)
|
||||||
@ -5502,6 +5505,8 @@ match_template (char mnem_suffix)
|
|||||||
&& i.types[0].bitfield.acc
|
&& i.types[0].bitfield.acc
|
||||||
&& operand_type_check (i.types[1], anymem))
|
&& operand_type_check (i.types[1], anymem))
|
||||||
continue;
|
continue;
|
||||||
|
if (!(size_match & MATCH_STRAIGHT))
|
||||||
|
goto check_reverse;
|
||||||
/* If we want store form, we reverse direction of operands. */
|
/* If we want store form, we reverse direction of operands. */
|
||||||
if (i.dir_encoding == dir_encoding_store
|
if (i.dir_encoding == dir_encoding_store
|
||||||
&& t->opcode_modifier.d)
|
&& t->opcode_modifier.d)
|
||||||
@ -5531,6 +5536,8 @@ match_template (char mnem_suffix)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
check_reverse:
|
check_reverse:
|
||||||
|
if (!(size_match & MATCH_REVERSE))
|
||||||
|
continue;
|
||||||
/* Try reversing direction of operands. */
|
/* Try reversing direction of operands. */
|
||||||
overlap0 = operand_type_and (i.types[0], operand_types[1]);
|
overlap0 = operand_type_and (i.types[0], operand_types[1]);
|
||||||
overlap1 = operand_type_and (i.types[1], operand_types[0]);
|
overlap1 = operand_type_and (i.types[1], operand_types[0]);
|
||||||
|
@ -59,11 +59,10 @@
|
|||||||
.*:63: Error: .*
|
.*:63: Error: .*
|
||||||
.*:64: Error: .*
|
.*:64: Error: .*
|
||||||
.*:65: Error: .*
|
.*:65: Error: .*
|
||||||
.*:68: Error: .*
|
.*:67: Error: .*mov.*
|
||||||
.*:69: Error: .*
|
.*:68: Error: .*mov.*
|
||||||
.*:70: Error: .*
|
.*:69: Error: .*mov.*
|
||||||
.*:71: Error: .*
|
.*:70: Error: .*mov.*
|
||||||
.*:72: Error: .*
|
|
||||||
.*:73: Error: .*
|
.*:73: Error: .*
|
||||||
.*:74: Error: .*
|
.*:74: Error: .*
|
||||||
.*:75: Error: .*
|
.*:75: Error: .*
|
||||||
@ -75,14 +74,19 @@
|
|||||||
.*:81: Error: .*
|
.*:81: Error: .*
|
||||||
.*:82: Error: .*
|
.*:82: Error: .*
|
||||||
.*:83: Error: .*
|
.*:83: Error: .*
|
||||||
|
.*:84: Error: .*
|
||||||
.*:85: Error: .*
|
.*:85: Error: .*
|
||||||
.*:86: Error: .*
|
.*:86: Error: .*
|
||||||
.*:87: Error: .*
|
.*:87: Error: .*
|
||||||
.*:88: Error: .*
|
.*:88: Error: .*
|
||||||
.*:90: Error: .*
|
.*:90: Error: .*
|
||||||
.*:92: Error: .*shl.*
|
.*:91: Error: .*
|
||||||
.*:93: Error: .*rol.*
|
.*:92: Error: .*
|
||||||
.*:94: Error: .*rcl.*
|
.*:93: Error: .*
|
||||||
|
.*:95: Error: .*
|
||||||
|
.*:97: Error: .*shl.*
|
||||||
|
.*:98: Error: .*rol.*
|
||||||
|
.*:99: Error: .*rcl.*
|
||||||
GAS LISTING .*
|
GAS LISTING .*
|
||||||
|
|
||||||
|
|
||||||
@ -155,30 +159,35 @@ GAS LISTING .*
|
|||||||
[ ]*64[ ]+add \(%eiz\), %eax
|
[ ]*64[ ]+add \(%eiz\), %eax
|
||||||
[ ]*65[ ]+add \(%eax\), %eiz
|
[ ]*65[ ]+add \(%eax\), %eiz
|
||||||
[ ]*66[ ]+
|
[ ]*66[ ]+
|
||||||
[ ]*67[ ]+\.intel_syntax noprefix
|
[ ]*[1-9][0-9]*[ ]+mov %cr0, %di
|
||||||
[ ]*68[ ]+cvtsi2ss xmm1,QWORD PTR \[eax\]
|
[ ]*[1-9][0-9]*[ ]+mov %ax, %cr7
|
||||||
[ ]*69[ ]+cvtsi2sd xmm1,QWORD PTR \[eax\]
|
[ ]*[1-9][0-9]*[ ]+mov %cr0, %bh
|
||||||
[ ]*70[ ]+cvtsi2ssq xmm1,QWORD PTR \[eax\]
|
[ ]*[1-9][0-9]*[ ]+mov %al, %cr7
|
||||||
[ ]*71[ ]+cvtsi2sdq xmm1,QWORD PTR \[eax\]
|
[ ]*[1-9][0-9]*[ ]+
|
||||||
[ ]*72[ ]+movq xmm1, XMMWORD PTR \[esp\]
|
[ ]*[1-9][0-9]*[ ]+\.intel_syntax noprefix
|
||||||
[ ]*73[ ]+movq xmm1, DWORD PTR \[esp\]
|
[ ]*[1-9][0-9]*[ ]+cvtsi2ss xmm1,QWORD PTR \[eax\]
|
||||||
[ ]*74[ ]+movq xmm1, WORD PTR \[esp\]
|
[ ]*[1-9][0-9]*[ ]+cvtsi2sd xmm1,QWORD PTR \[eax\]
|
||||||
[ ]*75[ ]+movq xmm1, BYTE PTR \[esp\]
|
[ ]*[1-9][0-9]*[ ]+cvtsi2ssq xmm1,QWORD PTR \[eax\]
|
||||||
[ ]*76[ ]+movq XMMWORD PTR \[esp\],xmm1
|
[ ]*[1-9][0-9]*[ ]+cvtsi2sdq xmm1,QWORD PTR \[eax\]
|
||||||
[ ]*77[ ]+movq DWORD PTR \[esp\],xmm1
|
[ ]*[1-9][0-9]*[ ]+movq xmm1, XMMWORD PTR \[esp\]
|
||||||
[ ]*78[ ]+movq WORD PTR \[esp\],xmm1
|
[ ]*[1-9][0-9]*[ ]+movq xmm1, DWORD PTR \[esp\]
|
||||||
[ ]*79[ ]+movq BYTE PTR \[esp\],xmm1
|
[ ]*[1-9][0-9]*[ ]+movq xmm1, WORD PTR \[esp\]
|
||||||
[ ]*80[ ]+fnstsw eax
|
[ ]*[1-9][0-9]*[ ]+movq xmm1, BYTE PTR \[esp\]
|
||||||
[ ]*81[ ]+fnstsw al
|
[ ]*[1-9][0-9]*[ ]+movq XMMWORD PTR \[esp\],xmm1
|
||||||
[ ]*82[ ]+fstsw eax
|
[ ]*[1-9][0-9]*[ ]+movq DWORD PTR \[esp\],xmm1
|
||||||
[ ]*83[ ]+fstsw al
|
[ ]*[1-9][0-9]*[ ]+movq WORD PTR \[esp\],xmm1
|
||||||
[ ]*84[ ]+
|
[ ]*[1-9][0-9]*[ ]+movq BYTE PTR \[esp\],xmm1
|
||||||
[ ]*85[ ]+movsx ax, \[eax\]
|
[ ]*[1-9][0-9]*[ ]+fnstsw eax
|
||||||
[ ]*86[ ]+movsx eax, \[eax\]
|
[ ]*[1-9][0-9]*[ ]+fnstsw al
|
||||||
[ ]*87[ ]+movzx ax, \[eax\]
|
[ ]*[1-9][0-9]*[ ]+fstsw eax
|
||||||
[ ]*88[ ]+movzx eax, \[eax\]
|
[ ]*[1-9][0-9]*[ ]+fstsw al
|
||||||
[ ]*89[ ]+
|
[ ]*[1-9][0-9]*[ ]+
|
||||||
[ ]*90[ ]+movnti word ptr \[eax\], ax
|
[ ]*[1-9][0-9]*[ ]+movsx ax, \[eax\]
|
||||||
|
[ ]*[1-9][0-9]*[ ]+movsx eax, \[eax\]
|
||||||
|
[ ]*[1-9][0-9]*[ ]+movzx ax, \[eax\]
|
||||||
|
[ ]*[1-9][0-9]*[ ]+movzx eax, \[eax\]
|
||||||
|
[ ]*[1-9][0-9]*[ ]+
|
||||||
|
[ ]*[1-9][0-9]*[ ]+movnti word ptr \[eax\], ax
|
||||||
[ ]*[1-9][0-9]*[ ]+
|
[ ]*[1-9][0-9]*[ ]+
|
||||||
[ ]*[1-9][0-9]*[ ]+shl \[eax\], 1
|
[ ]*[1-9][0-9]*[ ]+shl \[eax\], 1
|
||||||
[ ]*[1-9][0-9]*[ ]+rol \[ecx\], 2
|
[ ]*[1-9][0-9]*[ ]+rol \[ecx\], 2
|
||||||
|
@ -64,6 +64,11 @@ movntiw %ax, (%eax)
|
|||||||
add (%eiz), %eax
|
add (%eiz), %eax
|
||||||
add (%eax), %eiz
|
add (%eax), %eiz
|
||||||
|
|
||||||
|
mov %cr0, %di
|
||||||
|
mov %ax, %cr7
|
||||||
|
mov %cr0, %bh
|
||||||
|
mov %al, %cr7
|
||||||
|
|
||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
cvtsi2ss xmm1,QWORD PTR [eax]
|
cvtsi2ss xmm1,QWORD PTR [eax]
|
||||||
cvtsi2sd xmm1,QWORD PTR [eax]
|
cvtsi2sd xmm1,QWORD PTR [eax]
|
||||||
|
Loading…
Reference in New Issue
Block a user