broadcast factor. */
struct Broadcast_Operation
{
- /* Type of broadcast: no broadcast, {1to8}, or {1to16}. */
+ /* Type of broadcast: {1to2}, {1to4}, {1to8}, or {1to16}. */
int type;
/* Index of broadcasted operand. */
&& !defined (TE_GNU) \
&& !defined (TE_LINUX) \
&& !defined (TE_NACL) \
- && !defined (TE_NETWARE) \
&& !defined (TE_FreeBSD) \
&& !defined (TE_DragonFly) \
&& !defined (TE_NetBSD)))
CPU_WBNOINVD_FLAGS, 0 },
{ STRING_COMMA_LEN (".pconfig"), PROCESSOR_UNKNOWN,
CPU_PCONFIG_FLAGS, 0 },
+ { STRING_COMMA_LEN (".waitpkg"), PROCESSOR_UNKNOWN,
+ CPU_WAITPKG_FLAGS, 0 },
+ { STRING_COMMA_LEN (".cldemote"), PROCESSOR_UNKNOWN,
+ CPU_CLDEMOTE_FLAGS, 0 },
};
static const noarch_entry cpu_noarch[] =
&& !t->operand_types[j].bitfield.fword)
/* For scalar opcode templates to allow register and memory
operands at the same time, some special casing is needed
- here. */
+ here. Also for v{,p}broadcast*, {,v}pmov{s,z}*, and
+ down-conversion vpmov*. */
|| ((t->operand_types[j].bitfield.regsimd
&& !t->opcode_modifier.broadcast
- && (t->operand_types[j].bitfield.dword
+ && (t->operand_types[j].bitfield.byte
+ || t->operand_types[j].bitfield.word
+ || t->operand_types[j].bitfield.dword
|| t->operand_types[j].bitfield.qword))
? (i.types[j].bitfield.xmmword
|| i.types[j].bitfield.ymmword
cpu_arch_flags = flags;
cpu_arch_isa_flags = flags;
}
+ else
+ cpu_arch_isa_flags
+ = cpu_flags_or (cpu_arch_isa_flags,
+ cpu_arch[j].flags);
(void) restore_line_pointer (e);
demand_empty_rest_of_line ();
return;
|| (!i.mask
&& !i.rounding
&& is_evex_encoding (&i.tm)
- && cpu_arch_flags.bitfield.cpuavx512vl))
+ && (i.vec_encoding != vex_encoding_evex
+ || i.tm.cpu_flags.bitfield.cpuavx512vl
+ || cpu_arch_isa_flags.bitfield.cpuavx512vl)))
&& ((i.tm.base_opcode == 0x55
|| i.tm.base_opcode == 0x6655
|| i.tm.base_opcode == 0x66df
*/
if (is_evex_encoding (&i.tm))
{
- /* If only lower 16 vector registers are used, we can use
- VEX encoding. */
- for (j = 0; j < 3; j++)
- if (register_number (i.op[j].regs) > 15)
- break;
-
- if (j < 3)
+ if (i.vec_encoding == vex_encoding_evex)
i.tm.opcode_modifier.evex = EVEX128;
else
{
to the memory operand. */
if (i.broadcast)
{
- int broadcasted_opnd_size;
+ i386_operand_type type, overlap;
/* Check if specified broadcast is supported in this instruction,
- and it's applied to memory operand of DWORD or QWORD type,
- depending on VecESize. */
- if (i.broadcast->type != t->opcode_modifier.broadcast
- || !i.types[i.broadcast->operand].bitfield.mem
- || (t->opcode_modifier.vecesize == 0
- && !i.types[i.broadcast->operand].bitfield.dword
- && !i.types[i.broadcast->operand].bitfield.unspecified)
- || (t->opcode_modifier.vecesize == 1
- && !i.types[i.broadcast->operand].bitfield.qword
- && !i.types[i.broadcast->operand].bitfield.unspecified))
- goto bad_broadcast;
-
- broadcasted_opnd_size = t->opcode_modifier.vecesize ? 64 : 32;
- if (i.broadcast->type == BROADCAST_1TO16)
- broadcasted_opnd_size <<= 4; /* Broadcast 1to16. */
- else if (i.broadcast->type == BROADCAST_1TO8)
- broadcasted_opnd_size <<= 3; /* Broadcast 1to8. */
- else if (i.broadcast->type == BROADCAST_1TO4)
- broadcasted_opnd_size <<= 2; /* Broadcast 1to4. */
- else if (i.broadcast->type == BROADCAST_1TO2)
- broadcasted_opnd_size <<= 1; /* Broadcast 1to2. */
- else
- goto bad_broadcast;
-
- if ((broadcasted_opnd_size == 256
- && !t->operand_types[i.broadcast->operand].bitfield.ymmword)
- || (broadcasted_opnd_size == 512
- && !t->operand_types[i.broadcast->operand].bitfield.zmmword))
+ and it's applied to memory operand of DWORD or QWORD type. */
+ op = i.broadcast->operand;
+ if (!t->opcode_modifier.broadcast
+ || !i.types[op].bitfield.mem
+ || (!i.types[op].bitfield.unspecified
+ && (t->operand_types[op].bitfield.dword
+ ? !i.types[op].bitfield.dword
+ : !i.types[op].bitfield.qword)))
{
bad_broadcast:
i.error = unsupported_broadcast;
return 1;
}
+
+ operand_type_set (&type, 0);
+ switch ((t->operand_types[op].bitfield.dword ? 4 : 8) * i.broadcast->type)
+ {
+ case 8:
+ type.bitfield.qword = 1;
+ break;
+ case 16:
+ type.bitfield.xmmword = 1;
+ break;
+ case 32:
+ type.bitfield.ymmword = 1;
+ break;
+ case 64:
+ type.bitfield.zmmword = 1;
+ break;
+ default:
+ goto bad_broadcast;
+ }
+
+ overlap = operand_type_and (type, t->operand_types[op]);
+ if (operand_type_all_zero (&overlap))
+ goto bad_broadcast;
+
+ if (t->opcode_modifier.checkregsize)
+ {
+ unsigned int j;
+
+ for (j = 0; j < i.operands; ++j)
+ {
+ if (j != op
+ && !operand_type_register_match(i.types[j],
+ t->operand_types[j],
+ type,
+ t->operand_types[op]))
+ goto bad_broadcast;
+ }
+ }
}
/* If broadcast is supported in this instruction, we need to check if
operand of one-element size isn't specified without broadcast. */
break;
gas_assert (op < i.operands);
/* Check size of the memory operand. */
- if ((t->opcode_modifier.vecesize == 0
- && i.types[op].bitfield.dword)
- || (t->opcode_modifier.vecesize == 1
- && i.types[op].bitfield.qword))
+ if (t->operand_types[op].bitfield.dword
+ ? i.types[op].bitfield.dword
+ : i.types[op].bitfield.qword)
{
i.error = broadcast_needed;
return 1;
}
}
+ else
+ op = MAX_OPERANDS - 1; /* Avoid uninitialized variable warning. */
/* Check if requested masking is supported. */
if (i.mask
&& i.disp_encoding != disp_encoding_32bit)
{
if (i.broadcast)
- i.memshift = t->opcode_modifier.vecesize ? 3 : 2;
+ i.memshift = t->operand_types[op].bitfield.dword ? 2 : 3;
else
i.memshift = t->opcode_modifier.disp8memshift;
&& operand_type_equal (&i.types [0], &acc32)
&& operand_type_equal (&i.types [1], &acc32))
continue;
+ /* xrelease mov %eax, <disp> is another special case. It must not
+ match the accumulator-only encoding of mov. */
+ if (flag_code != CODE_64BIT
+ && i.hle_prefix
+ && t->base_opcode == 0xa0
+ && i.types[0].bitfield.acc
+ && operand_type_check (i.types[1], anymem))
+ continue;
/* If we want store form, we reverse direction of operands. */
if (i.dir_encoding == dir_encoding_store
&& t->opcode_modifier.d)
case 4:
if (!operand_type_match (overlap3, i.types[3])
|| (check_register
- && !operand_type_register_match (i.types[2],
- operand_types[2],
- i.types[3],
- operand_types[3])))
+ && (!operand_type_register_match (i.types[1],
+ operand_types[1],
+ i.types[3],
+ operand_types[3])
+ || !operand_type_register_match (i.types[2],
+ operand_types[2],
+ i.types[3],
+ operand_types[3]))))
continue;
/* Fall through. */
case 3:
{
if (intel_syntax
&& i.tm.opcode_modifier.ignoresize
- && i.tm.opcode_modifier.no_lsuf)
+ && i.tm.opcode_modifier.no_lsuf
+ && !i.tm.opcode_modifier.todword
+ && !i.tm.opcode_modifier.toqword)
i.suffix = 0;
else if (!check_long_reg ())
return 0;
{
if (intel_syntax
&& i.tm.opcode_modifier.ignoresize
- && i.tm.opcode_modifier.no_qsuf)
+ && i.tm.opcode_modifier.no_qsuf
+ && !i.tm.opcode_modifier.todword
+ && !i.tm.opcode_modifier.toqword)
i.suffix = 0;
else if (!check_qword_reg ())
return 0;
unsigned int source, dest;
int vex_3_sources;
- /* The first operand of instructions with VEX prefix and 3 sources
- must be VEX_Imm4. */
vex_3_sources = i.tm.opcode_modifier.vexsources == VEX3SOURCES;
if (vex_3_sources)
{
unsigned int nds, reg_slot;
expressionS *exp;
- if (i.tm.opcode_modifier.veximmext
- && i.tm.opcode_modifier.immext)
- {
- dest = i.operands - 2;
- gas_assert (dest == 3);
- }
- else
- dest = i.operands - 1;
+ dest = i.operands - 1;
nds = dest - 1;
/* There are 2 kinds of instructions:
- 1. 5 operands: 4 register operands or 3 register operands
- plus 1 memory operand plus one Vec_Imm4 operand, VexXDS, and
- VexW0 or VexW1. The destination must be either XMM, YMM or
+ 1. 5 operands: 4 register operands or 3 register operands
+ plus 1 memory operand plus one Vec_Imm4 operand, VexXDS, and
+ VexW0 or VexW1. The destination must be either XMM, YMM or
ZMM register.
- 2. 4 operands: 4 register operands or 3 register operands
- plus 1 memory operand, VexXDS, and VexImmExt */
+ 2. 4 operands: 4 register operands or 3 register operands
+ plus 1 memory operand, with VexXDS. */
gas_assert ((i.reg_operands == 4
- || (i.reg_operands == 3 && i.mem_operands == 1))
- && i.tm.opcode_modifier.vexvvvv == VEXXDS
- && (i.tm.opcode_modifier.veximmext
- || (i.imm_operands == 1
- && i.types[0].bitfield.vec_imm4
- && (i.tm.opcode_modifier.vexw == VEXW0
- || i.tm.opcode_modifier.vexw == VEXW1)
- && i.tm.operand_types[dest].bitfield.regsimd)));
+ || (i.reg_operands == 3 && i.mem_operands == 1))
+ && i.tm.opcode_modifier.vexvvvv == VEXXDS
+ && i.tm.opcode_modifier.vexw
+ && i.tm.operand_types[dest].bitfield.regsimd);
+
+ /* If VexW1 is set, the first non-immediate operand is the source and
+ the second non-immediate one is encoded in the immediate operand. */
+ if (i.tm.opcode_modifier.vexw == VEXW1)
+ {
+ source = i.imm_operands;
+ reg_slot = i.imm_operands + 1;
+ }
+ else
+ {
+ source = i.imm_operands + 1;
+ reg_slot = i.imm_operands;
+ }
if (i.imm_operands == 0)
- {
- /* When there is no immediate operand, generate an 8bit
- immediate operand to encode the first operand. */
- exp = &im_expressions[i.imm_operands++];
- 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.vexw == VEXW1)
- {
- source = 0;
- reg_slot = 1;
- }
- else
- {
- source = 1;
- reg_slot = 0;
- }
-
- /* FMA swaps REG and NDS. */
- if (i.tm.cpu_flags.bitfield.cpufma)
- {
- unsigned int tmp;
- tmp = reg_slot;
- reg_slot = nds;
- nds = tmp;
- }
-
- 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;
+ {
+ /* When there is no immediate operand, generate an 8bit
+ immediate operand to encode the first operand. */
+ exp = &im_expressions[i.imm_operands++];
+ i.op[i.operands].imms = exp;
+ i.types[i.operands] = imm8;
+ i.operands++;
+
+ 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);
}
else
- {
- unsigned int imm_slot;
-
- if (i.tm.opcode_modifier.vexw == VEXW0)
- {
- /* If VexW0 is set, the third operand is the source and
- the second operand is encoded in the immediate
- operand. */
- source = 2;
- reg_slot = 1;
- }
- else
- {
- /* VexW1 is set, the second operand is the source and
- the third operand is encoded in the immediate
- operand. */
- source = 1;
- reg_slot = 2;
- }
-
- if (i.tm.opcode_modifier.immext)
- {
- /* When ImmExt is set, the immediate byte is the last
- operand. */
- imm_slot = i.operands - 1;
- source--;
- reg_slot--;
- }
- else
- {
- imm_slot = 0;
-
- /* Turn on Imm8 so that output_imm will generate it. */
- i.types[imm_slot].bitfield.imm8 = 1;
- }
-
- 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;
+ {
+ unsigned int imm_slot;
+
+ gas_assert (i.imm_operands == 1 && i.types[0].bitfield.vec_imm4);
+
+ if (i.tm.opcode_modifier.immext)
+ {
+ /* When ImmExt is set, the immediate byte is the last
+ operand. */
+ imm_slot = i.operands - 1;
+ source--;
+ reg_slot--;
+ }
+ else
+ {
+ imm_slot = 0;
+
+ /* Turn on Imm8 so that output_imm will generate it. */
+ i.types[imm_slot].bitfield.imm8 = 1;
+ }
+
+ 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 (i.tm.operand_types[nds].bitfield.regsimd);
i.vex.register_specifier = i.op[nds].regs;
op_string += 3;
if (*op_string == '8')
- bcst_type = BROADCAST_1TO8;
+ bcst_type = 8;
else if (*op_string == '4')
- bcst_type = BROADCAST_1TO4;
+ bcst_type = 4;
else if (*op_string == '2')
- bcst_type = BROADCAST_1TO2;
+ bcst_type = 2;
else if (*op_string == '1'
&& *(op_string+1) == '6')
{
- bcst_type = BROADCAST_1TO16;
+ bcst_type = 16;
op_string++;
}
else
return NULL;
}
op_string++;
+
+ /* Strip whitespace since the addition of pseudo prefixes
+ changed how the scrubber treats '{'. */
+ if (is_space_char (*op_string))
+ ++op_string;
+
continue;
}
unknown_vec_op:
cpu_arch_flags = flags;
cpu_arch_isa_flags = flags;
}
+ else
+ cpu_arch_isa_flags
+ = cpu_flags_or (cpu_arch_isa_flags,
+ cpu_arch[j].flags);
break;
}
}