[PATCH] Add x86 SSE5 instructions to the GNU binary utilities

H.J. Lu hjl@lucon.org
Thu Sep 13 20:30:00 GMT 2007


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;
+	}
+



More information about the Binutils mailing list