diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-i386.c | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 1a15d1d..7d170f4 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -623,6 +623,8 @@ static const arch_entry cpu_arch[] = CPU_PCLMUL_FLAGS }, { ".fma", PROCESSOR_UNKNOWN, CPU_FMA_FLAGS }, + { ".fma4", PROCESSOR_UNKNOWN, + CPU_FMA4_FLAGS }, { ".movbe", PROCESSOR_UNKNOWN, CPU_MOVBE_FLAGS }, { ".ept", PROCESSOR_UNKNOWN, @@ -4757,31 +4759,25 @@ build_modrm_byte (void) { unsigned int nds, reg; + if (i.tm.opcode_modifier.veximmext + && i.tm.opcode_modifier.immext) + { + dest = i.operands - 2; + gas_assert (dest == 3); + } + else dest = i.operands - 1; nds = dest - 1; - source = 1; - reg = 0; - - /* This instruction must have 4 operands: 4 register operands - or 3 register operands plus 1 memory operand. It must have - VexNDS and VexImmExt. */ - gas_assert (i.operands == 4 - && (i.reg_operands == 4 + + /* This instruction must have 4 register operands + or 3 register operands plus 1 memory operand. + It must have VexNDS and VexImmExt. */ + gas_assert ((i.reg_operands == 4 || (i.reg_operands == 3 && i.mem_operands == 1)) && i.tm.opcode_modifier.vexnds && i.tm.opcode_modifier.veximmext - && (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[nds], - ®xmm) - || operand_type_equal (&i.tm.operand_types[nds], - ®ymm)) - && (operand_type_equal (&i.tm.operand_types[reg], - ®xmm) - || operand_type_equal (&i.tm.operand_types[reg], - ®ymm))); + && (operand_type_equal (&i.tm.operand_types[dest], ®xmm) + || operand_type_equal (&i.tm.operand_types[dest], ®ymm))); /* Generate an 8bit immediate operand to encode the register operand. */ @@ -4789,11 +4785,36 @@ build_modrm_byte (void) i.op[i.operands].imms = exp; i.types[i.operands] = imm8; i.operands++; + /* If VexW1 is set, the first operand is the source and + the second operand is encoded in the immediate operand. */ + if (i.tm.opcode_modifier.vexw1) + { + source = 0; + reg = 1; + } + else + { + source = 1; + reg = 0; + } + /* FMA4 swaps REG and NDS. */ + if (i.tm.cpu_flags.bitfield.cpufma4) + { + unsigned int tmp; + tmp = reg; + reg = nds; + nds = tmp; + } + gas_assert ((operand_type_equal (&i.tm.operand_types[reg], ®xmm) + || operand_type_equal (&i.tm.operand_types[reg], + ®ymm)) + && (operand_type_equal (&i.tm.operand_types[nds], ®xmm) + || operand_type_equal (&i.tm.operand_types[nds], + ®ymm))); exp->X_op = O_constant; exp->X_add_number - = ((i.op[0].regs->reg_num - + ((i.op[0].regs->reg_flags & RegRex) ? 8 : 0)) << 4); - + = ((i.op[reg].regs->reg_num + + ((i.op[reg].regs->reg_flags & RegRex) ? 8 : 0)) << 4); i.vex.register_specifier = i.op[nds].regs; } else @@ -4931,7 +4952,6 @@ build_modrm_byte (void) for (op = 0; op < i.operands; op++) if (operand_type_check (i.types[op], anymem)) break; - gas_assert (op < i.operands); default_seg = &ds; @@ -7855,7 +7875,7 @@ md_show_usage (stream) mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, sse4,\n\ avx, vmx, smx, xsave, movbe, ept, aes, pclmul, fma,\n\ clflush, syscall, rdtscp, 3dnow, 3dnowa, sse4a,\n\ - svme, abm, padlock\n")); + svme, abm, padlock, fma4\n")); fprintf (stream, _("\ -mtune=CPU optimize for CPU, CPU is one of:\n\ i8086, i186, i286, i386, i486, pentium, pentiumpro,\n\ |