From 10c17abdd052c5f8f9c2bcdf8b01dffe5d06baf0 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 18 Dec 2017 09:37:15 +0100 Subject: 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). --- gas/config/tc-i386.c | 81 ++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 38 deletions(-) (limited to 'gas/config') 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 (); -- cgit v1.1