2004-03-11 Michal Ludvig * 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 _("") 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: