This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

VIA PadLock support


Hi all,
this patch adds support for (dis)assembling VIA Nehemiah PadLock instructions. These insns are 3 bytes long and except for 'xstore' must have a 'rep' prefix. I modified add_prefix() to accept 'xcrypt' insns both with and without explicitly mentioned 'rep' (although it is always emitted exacly once without complains).


OK to commit?

Michal Ludvig
--
SUSE Labs                    mludvig@suse.cz | Cray is the only computer
(+420) 296.545.373        http://www.suse.cz | that runs an endless loop
Personal homepage http://www.logix.cz/michal | in just four hours.
2004-03-11  Michal Ludvig  <mludvig@suse.cz>

	* gas/config/tc-i386.c (add_prefix): New parameter 'mayfail'.
	(output_insn): Handle PadLock instructions.
	* gas/config/tc-i386.h (CpuPadLock): New define.
	(CpuUnknownFlags): Added CpuPadLock.
	* include/opcode/i386.h (i386_optab): Added xstore/xcrypt insns.
	* opcodes/i386-dis.c (PADLOCK_SPECIAL, PADLOCK_0): New defines.
	(dis386_twobyte): Opcode 0xa7 is PADLOCK_0.
	(padlock_table): New struct with PadLock instructions.
	(print_insn): Handle PADLOCK_SPECIAL.

Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.149
diff -u -p -r1.149 tc-i386.c
--- gas/config/tc-i386.c	22 Nov 2003 02:35:30 -0000	1.149
+++ gas/config/tc-i386.c	11 Mar 2004 12:41:54 -0000
@@ -70,7 +70,7 @@ static INLINE int fits_in_unsigned_long 
 static INLINE int fits_in_signed_long PARAMS ((offsetT));
 static int smallest_imm_type PARAMS ((offsetT));
 static offsetT offset_in_range PARAMS ((offsetT, int));
-static int add_prefix PARAMS ((unsigned int));
+static int add_prefix PARAMS ((unsigned int, int));
 static void set_code_flag PARAMS ((int));
 static void set_16bit_gcc_code_flag PARAMS ((int));
 static void set_intel_syntax PARAMS ((int));
@@ -689,8 +689,9 @@ offset_in_range (val, size)
    class already exists, 1 if non rep/repne added, 2 if rep/repne
    added.  */
 static int
-add_prefix (prefix)
+add_prefix (prefix, mayfail)
      unsigned int prefix;
+     int mayfail;
 {
   int ret = 1;
   int q;
@@ -734,7 +735,7 @@ add_prefix (prefix)
 	break;
       }
 
-  if (i.prefix[q] != 0)
+  if (!mayfail && i.prefix[q] != 0)
     {
       as_bad (_("same type of prefix used twice"));
       return 0;
@@ -1346,7 +1347,7 @@ md_assemble (line)
     }
 
   if (i.tm.opcode_modifier & FWait)
-    if (!add_prefix (FWAIT_OPCODE))
+    if (!add_prefix (FWAIT_OPCODE, 0))
       return;
 
   /* Check string instruction segment overrides.  */
@@ -1474,7 +1475,7 @@ md_assemble (line)
     }
 
   if (i.rex != 0)
-    add_prefix (REX_OPCODE | i.rex);
+    add_prefix (REX_OPCODE | i.rex, 0);
 
   /* We are ready to output the insn.  */
   output_insn ();
@@ -1543,7 +1544,7 @@ parse_insn (line, mnemonic)
 	      return NULL;
 	    }
 	  /* Add prefix, checking for repeated prefixes.  */
-	  switch (add_prefix (current_templates->start->base_opcode))
+	  switch (add_prefix (current_templates->start->base_opcode, 0))
 	    {
 	    case 0:
 	      return NULL;
@@ -1612,13 +1613,13 @@ parse_insn (line, mnemonic)
 	{
 	  if (l[2] == 't')
 	    {
-	      if (!add_prefix (DS_PREFIX_OPCODE))
+	      if (!add_prefix (DS_PREFIX_OPCODE, 0))
 		return NULL;
 	      l += 3;
 	    }
 	  else if (l[2] == 'n')
 	    {
-	      if (!add_prefix (CS_PREFIX_OPCODE))
+	      if (!add_prefix (CS_PREFIX_OPCODE, 0))
 		return NULL;
 	      l += 3;
 	    }
@@ -2270,7 +2271,7 @@ process_suffix ()
 	  if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
 	    prefix = ADDR_PREFIX_OPCODE;
 
-	  if (!add_prefix (prefix))
+	  if (!add_prefix (prefix, 0))
 	    return 0;
 	}
 
@@ -2650,7 +2651,7 @@ process_operands ()
      always be used.  */
   if ((i.seg[0]) && (i.seg[0] != default_seg))
     {
-      if (!add_prefix (i.seg[0]->seg_prefix))
+      if (!add_prefix (i.seg[0]->seg_prefix, 0))
 	return 0;
     }
   return 1;
@@ -3123,7 +3124,6 @@ output_interseg_jump ()
   md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
 }
 
-
 static void
 output_insn ()
 {
@@ -3153,8 +3153,13 @@ output_insn ()
 
       /* All opcodes on i386 have either 1 or 2 bytes.  We may use third
 	 byte for the SSE instructions to specify a prefix they require.  */
-      if (i.tm.base_opcode & 0xff0000)
-	add_prefix ((i.tm.base_opcode >> 16) & 0xff);
+      if (i.tm.cpu_flags & CpuPadLock) {
+	if (i.tm.base_opcode & 0xff000000)
+	  add_prefix ((i.tm.base_opcode >> 24) & 0xff, 1);
+      }	else {
+	if (i.tm.base_opcode & 0xff0000)
+	  add_prefix ((i.tm.base_opcode >> 16) & 0xff, 0);
+      }
 
       /* The prefix bytes.  */
       for (q = i.prefix;
@@ -3175,7 +3180,12 @@ output_insn ()
 	}
       else
 	{
-	  p = frag_more (2);
+	  if (i.tm.cpu_flags & CpuPadLock) {
+	    p = frag_more (3);
+	    *p++ = (i.tm.base_opcode >> 16) & 0xff;
+	  } else
+	    p = frag_more (2);
+
 	  /* Put out high byte first: can't use md_number_to_chars!  */
 	  *p++ = (i.tm.base_opcode >> 8) & 0xff;
 	  *p = i.tm.base_opcode & 0xff;
Index: gas/config/tc-i386.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.h,v
retrieving revision 1.45
diff -u -p -r1.45 tc-i386.h
--- gas/config/tc-i386.h	21 Nov 2003 14:38:06 -0000	1.45
+++ gas/config/tc-i386.h	11 Mar 2004 12:41:54 -0000
@@ -194,13 +194,14 @@ typedef struct
 #define CpuSSE2	       0x2000	/* Streaming SIMD extensions 2 required */
 #define Cpu3dnow       0x4000	/* 3dnow! support required */
 #define CpuPNI	       0x8000	/* Prescott New Instructions required */
+#define CpuPadLock    0x10000	/* VIA PadLock required */
 
   /* These flags are set by gas depending on the flag_code.  */
 #define Cpu64	     0x4000000   /* 64bit support required  */
 #define CpuNo64      0x8000000   /* Not supported in the 64bit mode  */
 
   /* The default value for unknown CPUs - enable all features to avoid problems.  */
-#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuSledgehammer|CpuMMX|CpuSSE|CpuSSE2|CpuPNI|Cpu3dnow|CpuK6|CpuAthlon)
+#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuSledgehammer|CpuMMX|CpuSSE|CpuSSE2|CpuPNI|Cpu3dnow|CpuK6|CpuAthlon|CpuPadLock)
 
   /* the bits in opcode_modifier are used to generate the final opcode from
      the base_opcode.  These bits also are used to detect alternate forms of
Index: include/opcode/i386.h
===================================================================
RCS file: /cvs/src/src/include/opcode/i386.h,v
retrieving revision 1.40
diff -u -p -r1.40 i386.h
--- include/opcode/i386.h	23 Jun 2003 20:15:33 -0000	1.40
+++ include/opcode/i386.h	11 Mar 2004 12:41:54 -0000
@@ -1361,6 +1361,13 @@ static const template i386_optab[] = {
 {"sysret",   0, 0x0f07,    X, CpuK6,	lq_Suf|DefaultSize,	{ 0, 0, 0} },
 {"swapgs",   0, 0x0f01, 0xf8, Cpu64,	NoSuf|ImmExt,		{ 0, 0, 0} },
 
+/* VIA PadLock extensions. */
+{"xstorerng", 0, 0x0fa7c0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} },
+{"xcryptecb", 0, 0xf30fa7c8, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} },
+{"xcryptcbc", 0, 0xf30fa7d0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} },
+{"xcryptcfb", 0, 0xf30fa7e0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} },
+{"xcryptofb", 0, 0xf30fa7e8, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} },
+
 /* sentinel */
 {NULL, 0, 0, 0, 0, 0, { 0, 0, 0} }
 };
Index: opcodes/i386-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/i386-dis.c,v
retrieving revision 1.42
diff -u -p -r1.42 i386-dis.c
--- opcodes/i386-dis.c	18 Jan 2004 23:12:47 -0000	1.42
+++ opcodes/i386-dis.c	11 Mar 2004 12:41:54 -0000
@@ -362,6 +362,7 @@ fetch_data (struct disassemble_info *inf
 #define USE_GROUPS 2
 #define USE_PREFIX_USER_TABLE 3
 #define X86_64_SPECIAL 4
+#define PADLOCK_SPECIAL 5
 
 #define FLOAT	  NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
 
@@ -425,6 +426,8 @@ fetch_data (struct disassemble_info *inf
 
 #define X86_64_0  NULL, NULL, X86_64_SPECIAL, NULL,  0, NULL, 0
 
+#define PADLOCK_0  NULL, NULL, PADLOCK_SPECIAL, NULL,  0, NULL, 0
+
 typedef void (*op_rtn) (int bytemode, int sizeflag);
 
 struct dis386 {
@@ -948,7 +951,7 @@ static const struct dis386 dis386_twobyt
   { "shldS",		Ev, Gv, Ib },
   { "shldS",		Ev, Gv, CL },
   { "(bad)",		XX, XX, XX },
-  { "(bad)",		XX, XX, XX },
+  { PADLOCK_0 },
   /* a8 */
   { "pushT",		gs, XX, XX },
   { "popT",		gs, XX, XX },
@@ -1694,6 +1697,19 @@ static const struct dis386 x86_64_table[
   },
 };
 
+static const struct dis386 padlock_table[][8] = {
+  {
+    { "xstorerng", XX, XX, XX },
+    { "xcryptecb", XX, XX, XX },
+    { "xcryptcbc", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "xcryptcfb", XX, XX, XX },
+    { "xcryptofb", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+  },
+};
+
 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
 
 static void
@@ -2190,6 +2206,12 @@ print_insn (bfd_vma pc, disassemble_info
 
 	    case X86_64_SPECIAL:
 	      dp = &x86_64_table[dp->bytemode2][mode_64bit];
+	      break;
+
+	    case PADLOCK_SPECIAL:
+	      FETCH_DATA (info, codep + 1);
+	      index = (*codep++ >> 3) & 0x07;
+	      dp = &padlock_table[dp->bytemode2][index];
 	      break;
 
 	    default:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]