This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] Add x86 SSE5 instructions to the GNU binary utilities
- From: "H.J. Lu" <hjl at lucon dot org>
- To: "rajagopal, dwarak" <dwarak dot rajagopal at amd dot com>
- Cc: binutils at sourceware dot org, "Meissner, Michael" <michael dot meissner at amd dot com>, "Harle, Christophe" <christophe dot harle at amd dot com>
- Date: Thu, 13 Sep 2007 13:30:26 -0700
- Subject: Re: [PATCH] Add x86 SSE5 instructions to the GNU binary utilities
- References: <20070831175452.GA17876@mmeissner-gold.amd.com> <9E1304B144EBEB4C97F4162BFAC478863D2AED@SAUSEXMB2.amd.com>
On Thu, Sep 13, 2007 at 03:08:54PM -0500, rajagopal, dwarak wrote:
> The enclosed patch adds support for the SSE5 instructions to the
> assembler and disassembler.
>
> I have made changes to the original patch so that it uses bitfields (the
> new infrastructure changes which H.J had checked in last week) for
> cpu_flag, opcode_modifier and operand_types for the new instructions.
>
> Is this ok?
>
Here are my comments on assembler. I will take a look at disassembler
later.
H.J.
---
diff -purwN --exclude=autom4te.cache --exclude=po --exclude=intl src/binutils/NEWS src-sse5/binutils/NEWS
--- src/binutils/NEWS 2007-08-30 08:47:35.000000000 -0500
+ assert (i.imm_operands == 0
+ && (i.operands <= 2
+ || ((i.tm.cpu_flags.bitfield.cpusse5) != 0
+ && i.operands <= 3)));
Please use
|| (i.tm.cpu_flags.bitfield.cpusse5
&& i.operands <= 3)
exp = &im_expressions[i.imm_operands++];
i.op[i.operands].imms = exp;
@@ -2338,7 +2349,14 @@ md_assemble (line)
}
}
- if (i.rex != 0)
+ /* If the instruction has the DREX attribute (aka SSE5), don't emit a
+ REX prefix. */
+ if ((i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexc) != 0)
Please use
if (i.tm.opcode_modifier.drex || i.tm.opcode_modifier.drexc)
+ /* Case 2: 4 operand insn, dest = src1, src3 = memory. */
+ else if (i.types[0].bitfield.regxmm != 0
+ && i.types[1].bitfield.regxmm != 0
+ && (i.types[2].bitfield.regxmm | operand_type_check (i.types[2], anymem)) != 0
Did you mean
(i.types[2].bitfield.regxmm
|| operand_type_check (i.types[2], anymem))
+ /* Case 3: 4 operand insn, dest = src1, src2 = memory. */
+ else if (i.types[0].bitfield.regxmm != 0
+ && (operand_type_check (i.types[1], anymem)) != 0
Need for () on operand_type_check.
+ /* Case 5: 4 operand insn, dest = src3, src2 = memory. */
+ else if (i.types[0].bitfield.regxmm != 0
+ && (i.types[1].bitfield.regxmm | operand_type_check (i.types[1], anymem)) != 0
See above
+ else if ((i.tm.opcode_modifier.drex) && !(i.tm.opcode_modifier.drexv)
No need for ().
+ && i.operands == 4)
+ {
+ /* Case 1: 4 operand insn, dest = src1, src3 = reg/mem. */
+ if ((i.types[0].bitfield.regxmm) != 0
+ && (i.types[1].bitfield.regxmm | operand_type_check(i.types[1], anymem)) != 0
See above.
+ && i.types[2].bitfield.regxmm != 0
+ && i.types[3].bitfield.regxmm != 0
+ && i.op[0].regs->reg_num == i.op[3].regs->reg_num
+ && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
+ {
+ /* clear the arguments that are stored in drex */
+ UINTS_CLEAR (i.types[0]);
+ UINTS_CLEAR (i.types[3]);
+ i.reg_operands -= 2;
+
+ /* Specify the modrm encoding and remember the register including the
+ high bit normally stored in the REX byte. */
+ i.drex.modrm_reg = 2;
+ i.drex.modrm_regmem = 1;
+ i.drex.reg = (i.op[3].regs->reg_num
+ + ((i.op[3].regs->reg_flags & RegRex) ? 8 : 0));
+ }
+
+ else
+ as_bad (_("Incorrect operands for the '%s' instruction"), i.tm.name);
+ }
+
+ /* SSE5 3 operand instructions that the result is a register, being either
+ operand can be a memory operand, using OC0 to note which one is the
+ memory. */
+ else if (i.tm.opcode_modifier.drex && i.tm.opcode_modifier.drexv
Use a separate line for i.tm.opcode_modifier.drexv
+ else if ((i.tm.opcode_modifier.drexc) != 0 && i.operands == 4)
No need for ().
+ {
+ /* Case 1: 4 operand insn, src1 = reg/memory. */
+ if (operand_type_check (i.types[0], imm) != 0
+ && (i.types[1].bitfield.regxmm
+ | operand_type_check (i.types[1], anymem)) != 0
See above.
+ instruction. */
+ else if ((i.types[0].bitfield.regxmm
+ | operand_type_check (i.types[0], anymem)) != 0
See above
const seg_entry *default_seg = 0;
+ /* Handle all of the DREX munging that SSE5 needs. */
+ if (i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexv
+ | i.tm.opcode_modifier.drexc)
Use || and one line for each condition.
+ GAS as if this is a 2 operand instruction. */
+ if ((i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexv
+ | i.tm.opcode_modifier.drexc) != 0 && i.reg_operands == 2)
See above
+ /* This has been precalculated for SSE5 instructions that have a DREX
+ field earlier in process_drex. */
+ if ((i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexv
+ | i.tm.opcode_modifier.drexc) != 0)
See above.
unsigned int op;
+ /* This has been precalculated for SSE5 instructions that have a DREX
This line is too lone.
+ field earlier in process_drex. */
+ if ((i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexv
+ | i.tm.opcode_modifier.drexc) != 0)
+ {
See above.
- if (i.tm.extension_opcode != None)
+ if (i.tm.extension_opcode != None
+ && (i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexv
+ | i.tm.opcode_modifier.drexc) == 0)
See above.
i.rm.reg = i.tm.extension_opcode;
}
return default_seg;
@@ -4569,10 +4947,11 @@ output_insn (void)
int opc_3b;
/* All opcodes on i386 have either 1 or 2 bytes. SSSE3 and
- SSE4 instructions have 3 bytes. We may use one more higher
+ SSE4 and SSE5 instructions have 3 bytes. We may use one more higher
This line is too long.
+ multiple formats. */
+ if (i.tm.opcode_modifier.drex && i.tm.opcode_modifier.drexv
One line for each condition.
+ /* Write the DREX byte if needed. */
+ if (i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexc)
See above.
+ /* Encode the OC0 bit if this encoding has multiple formats. */
+ if ((i.tm.opcode_modifier.drex | i.tm.opcode_modifier.drexv)
+ && DREX_OC0 (i.tm.extension_opcode))
See above
+ *p |= DREX_OC0_MASK;
+ }
+