diff options
author | Jan Beulich <jbeulich@novell.com> | 2017-12-18 09:37:15 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2017-12-18 09:37:15 +0100 |
commit | 10c17abdd052c5f8f9c2bcdf8b01dffe5d06baf0 (patch) | |
tree | 12dbdd0363c5e815b4b589d3e7e85a95f56d10a4 /gas | |
parent | 1b54b8d7e4fc8055f9220a5287e8a94d8a65a88d (diff) | |
download | fsf-binutils-gdb-10c17abdd052c5f8f9c2bcdf8b01dffe5d06baf0.zip fsf-binutils-gdb-10c17abdd052c5f8f9c2bcdf8b01dffe5d06baf0.tar.gz fsf-binutils-gdb-10c17abdd052c5f8f9c2bcdf8b01dffe5d06baf0.tar.bz2 |
x86: fold certain AVX and AVX2 templates
Just like for instructions in GPRs, there's no need to have separate
templates for otherwise identical insns acting on XMM or YMM registers
(or memory of the same size).
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 9 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 81 |
2 files changed, 52 insertions, 38 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 447499f..d495548 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,14 @@ 2017-12-18 Jan Beulich <jbeulich@suse.com> + * config/tc-i386.c (regymm, regzmm): Delete. + (operand_type_register_match). Extend comment. Also handle some + memory operands here. Extend to cover .regsimd. + (build_vex_prefix): Derive vector_length from actual operand + size. + (process_operands, build_modrm_byte): Use .regsimd. + +2017-12-18 Jan Beulich <jbeulich@suse.com> + * config/tc-i386.c (match_simd_size): New. (match_mem_size): Use it. (operand_size_match): Likewise. Split .reg and .acc checks. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index ff42bab..775a371 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1747,8 +1747,6 @@ static const i386_operand_type disp16_32 = OPERAND_TYPE_DISP16_32; static const i386_operand_type anydisp = OPERAND_TYPE_ANYDISP; static const i386_operand_type regxmm = OPERAND_TYPE_REGXMM; -static const i386_operand_type regymm = OPERAND_TYPE_REGYMM; -static const i386_operand_type regzmm = OPERAND_TYPE_REGZMM; static const i386_operand_type regmask = OPERAND_TYPE_REGMASK; static const i386_operand_type imm8 = OPERAND_TYPE_IMM8; static const i386_operand_type imm8s = OPERAND_TYPE_IMM8S; @@ -1973,7 +1971,9 @@ mismatch: } /* If given types g0 and g1 are registers they must be of the same type - unless the expected operand type register overlap is null. */ + unless the expected operand type register overlap is null. + Memory operand size of certain SIMD instructions is also being checked + here. */ static INLINE int operand_type_register_match (i386_operand_type g0, @@ -1981,22 +1981,36 @@ operand_type_register_match (i386_operand_type g0, i386_operand_type g1, i386_operand_type t1) { - if (!operand_type_check (g0, reg)) + if (!g0.bitfield.reg + && !g0.bitfield.regsimd + && (!operand_type_check (g0, anymem) + || g0.bitfield.unspecified + || !t0.bitfield.regsimd)) return 1; - if (!operand_type_check (g1, reg)) + if (!g1.bitfield.reg + && !g1.bitfield.regsimd + && (!operand_type_check (g1, anymem) + || g1.bitfield.unspecified + || !t1.bitfield.regsimd)) return 1; if (g0.bitfield.byte == g1.bitfield.byte && g0.bitfield.word == g1.bitfield.word && g0.bitfield.dword == g1.bitfield.dword - && g0.bitfield.qword == g1.bitfield.qword) + && g0.bitfield.qword == g1.bitfield.qword + && g0.bitfield.xmmword == g1.bitfield.xmmword + && g0.bitfield.ymmword == g1.bitfield.ymmword + && g0.bitfield.zmmword == g1.bitfield.zmmword) return 1; if (!(t0.bitfield.byte & t1.bitfield.byte) && !(t0.bitfield.word & t1.bitfield.word) && !(t0.bitfield.dword & t1.bitfield.dword) - && !(t0.bitfield.qword & t1.bitfield.qword)) + && !(t0.bitfield.qword & t1.bitfield.qword) + && !(t0.bitfield.xmmword & t1.bitfield.xmmword) + && !(t0.bitfield.ymmword & t1.bitfield.ymmword) + && !(t0.bitfield.zmmword & t1.bitfield.zmmword)) return 1; i.error = register_type_mismatch; @@ -3240,8 +3254,22 @@ build_vex_prefix (const insn_template *t) if (i.tm.opcode_modifier.vex == VEXScalar) vector_length = avxscalar; + else if (i.tm.opcode_modifier.vex == VEX256) + vector_length = 1; else - vector_length = i.tm.opcode_modifier.vex == VEX256 ? 1 : 0; + { + unsigned int op; + + vector_length = 0; + for (op = 0; op < t->operands; ++op) + if (t->operand_types[op].bitfield.xmmword + && t->operand_types[op].bitfield.ymmword + && i.types[op].bitfield.ymmword) + { + vector_length = 1; + break; + } + } switch ((i.tm.base_opcode >> 8) & 0xff) { @@ -6066,10 +6094,7 @@ duplicate: else if (i.tm.opcode_modifier.implicitquadgroup) { /* The second operand must be {x,y,z}mmN, where N is a multiple of 4. */ - gas_assert (i.operands >= 2 - && (operand_type_equal (&i.types[1], ®xmm) - || operand_type_equal (&i.types[1], ®ymm) - || operand_type_equal (&i.types[1], ®zmm))); + gas_assert (i.operands >= 2 && i.types[1].bitfield.regsimd); unsigned int regnum = register_number (i.op[1].regs); unsigned int first_reg_in_group = regnum & ~3; unsigned int last_reg_in_group = first_reg_in_group + 3; @@ -6230,9 +6255,7 @@ build_modrm_byte (void) && i.types[0].bitfield.vec_imm4 && (i.tm.opcode_modifier.vexw == VEXW0 || i.tm.opcode_modifier.vexw == VEXW1) - && (operand_type_equal (&i.tm.operand_types[dest], ®xmm) - || operand_type_equal (&i.tm.operand_types[dest], ®ymm) - || operand_type_equal (&i.tm.operand_types[dest], ®zmm))))); + && i.tm.operand_types[dest].bitfield.regsimd))); if (i.imm_operands == 0) { @@ -6264,12 +6287,7 @@ build_modrm_byte (void) nds = tmp; } - gas_assert (operand_type_equal (&i.tm.operand_types[reg_slot], - ®xmm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®ymm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®zmm)); + gas_assert (i.tm.operand_types[reg_slot].bitfield.regsimd); exp->X_op = O_constant; exp->X_add_number = register_number (i.op[reg_slot].regs) << 4; gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); @@ -6311,22 +6329,13 @@ build_modrm_byte (void) i.types[imm_slot].bitfield.imm8 = 1; } - gas_assert (operand_type_equal (&i.tm.operand_types[reg_slot], - ®xmm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®ymm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®zmm)); + gas_assert (i.tm.operand_types[reg_slot].bitfield.regsimd); i.op[imm_slot].imms->X_add_number |= register_number (i.op[reg_slot].regs) << 4; gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); } - gas_assert (operand_type_equal (&i.tm.operand_types[nds], ®xmm) - || operand_type_equal (&i.tm.operand_types[nds], - ®ymm) - || operand_type_equal (&i.tm.operand_types[nds], - ®zmm)); + gas_assert (i.tm.operand_types[nds].bitfield.regsimd); i.vex.register_specifier = i.op[nds].regs; } else @@ -6450,9 +6459,7 @@ build_modrm_byte (void) if ((dest + 1) >= i.operands || ((!op.bitfield.reg || (!op.bitfield.dword && !op.bitfield.qword)) - && !operand_type_equal (&op, ®xmm) - && !operand_type_equal (&op, ®ymm) - && !operand_type_equal (&op, ®zmm) + && !op.bitfield.regsimd && !operand_type_equal (&op, ®mask))) abort (); i.vex.register_specifier = i.op[vvvv].regs; @@ -6879,9 +6886,7 @@ build_modrm_byte (void) if ((!type->bitfield.reg || (!type->bitfield.dword && !type->bitfield.qword)) - && !operand_type_equal (type, ®xmm) - && !operand_type_equal (type, ®ymm) - && !operand_type_equal (type, ®zmm) + && !type->bitfield.regsimd && !operand_type_equal (type, ®mask)) abort (); |