From 3012383869aefee12175ab4c8f5028449b4be4e9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 5 Jul 2005 07:16:54 +0000 Subject: [PATCH] gas/ 2005-07-05 Jan Beulich * config/tc-i386.h (CpuSVME): New. (CpuUnknownFlags): Include CpuSVME. * config/tc-i386.c (cpu_arch): Add .pacifica and .svme. Add opteron as alias of sledgehammer. (md_assemble): Include invlpga in the check for insns with two source operands. (process_operands): Include SVME insns in the check for ignored segment overrides. Adjust diagnostic. (i386_index_check): Special-case SVME insns with memory operands. gas/testsuite/ 2005-07-05 Jan Beulich * gas/i386/svme.d: New. * gas/i386/svme.s: New. * gas/i386/svme64.d: New. * gas/i386/i386.exp: Run new tests. include/opcode/ 2005-07-05 Jan Beulich * i386.h (i386_optab): Add new insns. opcodes/ 2005-07-05 Jan Beulich * i386-dis.c (SVME_Fixup): New. (grps): Use it for the lidt entry. (PNI_Fixup): Call OP_M rather than OP_E. (INVLPG_Fixup): Likewise. --- gas/ChangeLog | 12 +++++++ gas/config/tc-i386.c | 35 +++++++++++++++++-- gas/config/tc-i386.h | 5 ++- gas/testsuite/ChangeLog | 7 ++++ gas/testsuite/gas/i386/i386.exp | 2 ++ gas/testsuite/gas/i386/svme.d | 29 ++++++++++++++++ gas/testsuite/gas/i386/svme.s | 36 +++++++++++++++++++ gas/testsuite/gas/i386/svme64.d | 41 ++++++++++++++++++++++ include/opcode/ChangeLog | 4 +++ include/opcode/i386.h | 16 +++++++++ opcodes/ChangeLog | 7 ++++ opcodes/i386-dis.c | 77 +++++++++++++++++++++++++++++++++++++++-- 12 files changed, 264 insertions(+), 7 deletions(-) create mode 100644 gas/testsuite/gas/i386/svme.d create mode 100644 gas/testsuite/gas/i386/svme.s create mode 100644 gas/testsuite/gas/i386/svme64.d diff --git a/gas/ChangeLog b/gas/ChangeLog index 52b007e..07b9374 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +2005-07-05 Jan Beulich + + * config/tc-i386.h (CpuSVME): New. + (CpuUnknownFlags): Include CpuSVME. + * config/tc-i386.c (cpu_arch): Add .pacifica and .svme. Add opteron + as alias of sledgehammer. + (md_assemble): Include invlpga in the check for insns with two source + operands. + (process_operands): Include SVME insns in the check for ignored + segment overrides. Adjust diagnostic. + (i386_index_check): Special-case SVME insns with memory operands. + 2005-07-04 Khem Raj Nick Clifton diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 76c43f9..9f9b23a 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -429,12 +429,15 @@ static const arch_entry cpu_arch[] = { {"k6_2", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow }, {"athlon", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA }, {"sledgehammer",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2 }, + {"opteron", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2 }, {".mmx", CpuMMX }, {".sse", CpuMMX|CpuMMX2|CpuSSE }, {".sse2", CpuMMX|CpuMMX2|CpuSSE|CpuSSE2 }, {".3dnow", CpuMMX|Cpu3dnow }, {".3dnowa", CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA }, {".padlock", CpuPadLock }, + {".pacifica", CpuSVME }, + {".svme", CpuSVME }, {NULL, 0 } }; @@ -1403,6 +1406,7 @@ md_assemble (line) have two immediate operands. */ if (intel_syntax && i.operands > 1 && (strcmp (mnemonic, "bound") != 0) + && (strcmp (mnemonic, "invlpga") != 0) && !((i.types[0] & Imm) && (i.types[1] & Imm))) swap_operands (); @@ -2846,8 +2850,10 @@ process_operands () default_seg = &ds; } - if (i.tm.base_opcode == 0x8d /* lea */ && i.seg[0] && !quiet_warnings) - as_warn (_("segment override on `lea' is ineffectual")); + if ((i.tm.base_opcode == 0x8d /* lea */ + || (i.tm.cpu_flags & CpuSVME)) + && i.seg[0] && !quiet_warnings) + as_warn (_("segment override on `%s' is ineffectual"), i.tm.name); /* If a segment was explicitly specified, and the specified segment is not the default, use an opcode prefix to select it. If we @@ -4194,7 +4200,30 @@ i386_index_check (operand_string) tryprefix: #endif ok = 1; - if (flag_code == CODE_64BIT) + if ((current_templates->start->cpu_flags & CpuSVME) + && current_templates->end[-1].operand_types[0] == AnyMem) + { + /* Memory operands of SVME insns are special in that they only allow + rAX as their memory address and ignore any segment override. */ + unsigned RegXX; + + /* SKINIT is even more restrictive: it always requires EAX. */ + if (strcmp (current_templates->start->name, "skinit") == 0) + RegXX = Reg32; + else if (flag_code == CODE_64BIT) + RegXX = i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32; + else + RegXX = (flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0) + ? Reg16 + : Reg32; + if (!i.base_reg + || !(i.base_reg->reg_type & Acc) + || !(i.base_reg->reg_type & RegXX) + || i.index_reg + || (i.types[0] & Disp)) + ok = 0; + } + else if (flag_code == CODE_64BIT) { unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32); diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 2fc21d9..e4359fe 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -184,13 +184,16 @@ typedef struct #define Cpu3dnowA 0x10000 /* 3dnow!Extensions support required */ #define CpuPNI 0x20000 /* Prescott New Instructions required */ #define CpuPadLock 0x40000 /* VIA PadLock required */ +#define CpuSVME 0x80000 /* AMD Secure Virtual Machine Ext-s 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|CpuMMX2|CpuSSE|CpuSSE2|CpuPNI|Cpu3dnow|Cpu3dnowA|CpuK6|CpuAthlon|CpuPadLock) +#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 \ + |CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuPNI \ + |Cpu3dnow|Cpu3dnowA|CpuK6|CpuAthlon|CpuPadLock|CpuSVME) /* 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 diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 05f1610..57fa47a 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-07-05 Jan Beulich + + * gas/i386/svme.d: New. + * gas/i386/svme.s: New. + * gas/i386/svme64.d: New. + * gas/i386/i386.exp: Run new tests. + 2005-07-04 Zack Weinberg * lib/gas-defs.exp (run_dump_tests): New proc. diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index 34862a5..169d552 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -74,6 +74,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] run_dump_test "padlock" run_dump_test "crx" run_list_test "cr-err" "" + run_dump_test "svme" # These tests require support for 8 and 16 bit relocs, # so we only run them for ELF and COFF targets. @@ -128,6 +129,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t run_list_test "x86-64-segment" "-al" run_list_test "x86-64-inval-seg" "-al" run_dump_test "x86-64-branch" + run_dump_test "svme64" # For ELF targets verify that @unwind works. if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"] diff --git a/gas/testsuite/gas/i386/svme.d b/gas/testsuite/gas/i386/svme.d new file mode 100644 index 0000000..d7682a4 --- /dev/null +++ b/gas/testsuite/gas/i386/svme.d @@ -0,0 +1,29 @@ +#objdump: -dw +#name: 32-bit SVME + +.*: +file format .* + +Disassembly of section .text: + +0+000 : +[ ]*[0-9a-f]+:[ ]+0f 01 dd[ ]+clgi[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 df[ ]+invlpga[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 de[ ]+skinit[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 dc[ ]+stgi[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 da[ ]+vmload[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d9[ ]+vmmcall[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d8[ ]+vmrun[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 db[ ]+vmsave[ ]* +[0-9a-f]+ : +[ ]*[0-9a-f]+:[ ]+0f 01 de[ ]+skinit[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 df[ ]+invlpga[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 da[ ]+vmload[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d8[ ]+vmrun[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 db[ ]+vmsave[ ]* +[0-9a-f]+ : +[ ]*[0-9a-f]+:[ ]+0f 01 de[ ]+skinit[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 df[ ]+invlpga[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 da[ ]+vmload[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d8[ ]+vmrun[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 db[ ]+vmsave[ ]* +#pass diff --git a/gas/testsuite/gas/i386/svme.s b/gas/testsuite/gas/i386/svme.s new file mode 100644 index 0000000..1b7f234 --- /dev/null +++ b/gas/testsuite/gas/i386/svme.s @@ -0,0 +1,36 @@ + .text +common: + clgi + invlpga + skinit + stgi + vmload + vmmcall + vmrun + vmsave + +.macro do_args arg1, arg2 + invlpga \arg1, \arg2 + vmload \arg1 + vmrun \arg1 + vmsave \arg1 +.endm + +.ifdef __amd64__ +att64: + do_args (%rax), %ecx +.endif +att32: + skinit (%eax) + do_args (%eax), %ecx + +.intel_syntax noprefix +.ifdef __amd64__ +intel64: + do_args [rax], ecx +.endif +intel32: + skinit [eax] + do_args [eax], ecx + + .p2align 4,0 diff --git a/gas/testsuite/gas/i386/svme64.d b/gas/testsuite/gas/i386/svme64.d new file mode 100644 index 0000000..876d439 --- /dev/null +++ b/gas/testsuite/gas/i386/svme64.d @@ -0,0 +1,41 @@ +#as: --defsym __amd64__=1 +#objdump: -dw +#name: 64-bit SVME +#source: svme.s + +.*: +file format .* + +Disassembly of section .text: + +0+000 : +[ ]*[0-9a-f]+:[ ]+0f 01 dd[ ]+clgi[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 df[ ]+invlpga[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 de[ ]+skinit[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 dc[ ]+stgi[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 da[ ]+vmload[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d9[ ]+vmmcall[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d8[ ]+vmrun[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 db[ ]+vmsave[ ]* +[0-9a-f]+ : +[ ]*[0-9a-f]+:[ ]+0f 01 df[ ]+invlpga[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 da[ ]+vmload[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d8[ ]+vmrun[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 db[ ]+vmsave[ ]* +[0-9a-f]+ : +[ ]*[0-9a-f]+:[ ]+0f 01 de[ ]+skinit[ ]* +[ ]*[0-9a-f]+:[ ]+67 0f 01 df[ ]+(addr32 )?invlpga[ ]*\(%eax\),[ ]*%ecx +[ ]*[0-9a-f]+:[ ]+67 0f 01 da[ ]+(addr32 )?vmload[ ]*\(%eax\) +[ ]*[0-9a-f]+:[ ]+67 0f 01 d8[ ]+(addr32 )?vmrun[ ]*\(%eax\) +[ ]*[0-9a-f]+:[ ]+67 0f 01 db[ ]+(addr32 )?vmsave[ ]*\(%eax\) +[0-9a-f]+ : +[ ]*[0-9a-f]+:[ ]+0f 01 df[ ]+invlpga[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 da[ ]+vmload[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 d8[ ]+vmrun[ ]* +[ ]*[0-9a-f]+:[ ]+0f 01 db[ ]+vmsave[ ]* +[0-9a-f]+ : +[ ]*[0-9a-f]+:[ ]+0f 01 de[ ]+skinit[ ]* +[ ]*[0-9a-f]+:[ ]+67 0f 01 df[ ]+(addr32 )?invlpga[ ]*\(%eax\),[ ]*%ecx +[ ]*[0-9a-f]+:[ ]+67 0f 01 da[ ]+(addr32 )?vmload[ ]*\(%eax\) +[ ]*[0-9a-f]+:[ ]+67 0f 01 d8[ ]+(addr32 )?vmrun[ ]*\(%eax\) +[ ]*[0-9a-f]+:[ ]+67 0f 01 db[ ]+(addr32 )?vmsave[ ]*\(%eax\) +#pass diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index ccddcff..10fc851 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,7 @@ +2005-07-05 Jan Beulich + + * i386.h (i386_optab): Add new insns. + 2005-07-01 Nick Clifton * sparc.h: Add typedefs to structure declarations. diff --git a/include/opcode/i386.h b/include/opcode/i386.h index 449ffee..56266a8 100644 --- a/include/opcode/i386.h +++ b/include/opcode/i386.h @@ -1383,6 +1383,22 @@ static const template i386_optab[] = {"swapgs", 0, 0x0f01, 0xf8, Cpu64, NoSuf|ImmExt, { 0, 0, 0} }, {"rdtscp", 0, 0x0f01, 0xf9, CpuSledgehammer,NoSuf|ImmExt, { 0, 0, 0} }, +/* AMD Pacifica additions. */ +{"clgi", 0, 0x0f01, 0xdd, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"invlpga", 0, 0x0f01, 0xdf, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +/* Need to ensure only "invlpga ...,%ecx" is accepted. */ +{"invlpga", 2, 0x0f01, 0xdf, CpuSVME, NoSuf|ImmExt, { AnyMem, Reg32, 0 } }, +{"skinit", 0, 0x0f01, 0xde, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"skinit", 1, 0x0f01, 0xde, CpuSVME, NoSuf|ImmExt, { AnyMem, 0, 0 } }, +{"stgi", 0, 0x0f01, 0xdc, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"vmload", 0, 0x0f01, 0xda, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"vmload", 1, 0x0f01, 0xda, CpuSVME, NoSuf|ImmExt, { AnyMem, 0, 0 } }, +{"vmmcall", 0, 0x0f01, 0xd9, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"vmrun", 0, 0x0f01, 0xd8, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"vmrun", 1, 0x0f01, 0xd8, CpuSVME, NoSuf|ImmExt, { AnyMem, 0, 0 } }, +{"vmsave", 0, 0x0f01, 0xdb, CpuSVME, NoSuf|ImmExt, { 0, 0, 0 } }, +{"vmsave", 1, 0x0f01, 0xdb, CpuSVME, NoSuf|ImmExt, { AnyMem, 0, 0 } }, + /* VIA PadLock extensions. */ {"xstore-rng",0, 0x000fa7, 0xc0, Cpu686|CpuPadLock, NoSuf|IsString|ImmExt, { 0, 0, 0} }, {"xcrypt-ecb",0, 0xf30fa7, 0xc8, Cpu686|CpuPadLock, NoSuf|IsString|ImmExt, { 0, 0, 0} }, diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 605766a..f78ecf2 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +2005-07-05 Jan Beulich + + * i386-dis.c (SVME_Fixup): New. + (grps): Use it for the lidt entry. + (PNI_Fixup): Call OP_M rather than OP_E. + (INVLPG_Fixup): Likewise. + 2005-07-04 H.J. Lu * tic30-dis.c (cnvt_tmsfloat_ieee): Use HUGE_VALF if defined. diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 16c80b6..09faa94 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -95,6 +95,7 @@ static void OP_3DNowSuffix (int, int); static void OP_SIMD_Suffix (int, int); static void SIMD_Fixup (int, int); static void PNI_Fixup (int, int); +static void SVME_Fixup (int, int); static void INVLPG_Fixup (int, int); static void BadOp (void); static void SEG_Fixup (int, int); @@ -1374,7 +1375,7 @@ static const struct dis386 grps[][8] = { { "sgdtIQ", M, XX, XX }, { "sidtIQ", PNI_Fixup, 0, XX, XX }, { "lgdt{Q|Q||}", M, XX, XX }, - { "lidt{Q|Q||}", M, XX, XX }, + { "lidt{Q|Q||}", SVME_Fixup, 0, XX, XX }, { "smswQ", Ev, XX, XX }, { "(bad)", XX, XX, XX }, { "lmsw", Ew, XX, XX }, @@ -4445,7 +4446,77 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) codep++; } else - OP_E (0, sizeflag); + OP_M (0, sizeflag); +} + +static void +SVME_Fixup (int bytemode, int sizeflag) +{ + const char *alt; + char *p; + + switch (*codep) + { + case 0xd8: + alt = "vmrun"; + break; + case 0xd9: + alt = "vmmcall"; + break; + case 0xda: + alt = "vmload"; + break; + case 0xdb: + alt = "vmsave"; + break; + case 0xdc: + alt = "stgi"; + break; + case 0xdd: + alt = "clgi"; + break; + case 0xde: + alt = "skinit"; + break; + case 0xdf: + alt = "invlpga"; + break; + default: + OP_M (bytemode, sizeflag); + return; + } + /* Override "lidt". */ + p = obuf + strlen (obuf) - 4; + /* We might have a suffix. */ + if (*p == 'i') + --p; + strcpy (p, alt); + if (!(prefixes & PREFIX_ADDR)) + { + ++codep; + return; + } + used_prefixes |= PREFIX_ADDR; + switch (*codep++) + { + case 0xdf: + strcpy (op2out, names32[1]); + two_source_ops = 1; + /* Fall through. */ + case 0xd8: + case 0xda: + case 0xdb: + *obufp++ = open_char; + if (mode_64bit || (sizeflag & AFLAG)) + alt = names32[0]; + else + alt = names16[0]; + strcpy (obufp, alt); + obufp += strlen (alt); + *obufp++ = close_char; + *obufp = '\0'; + break; + } } static void @@ -4462,7 +4533,7 @@ INVLPG_Fixup (int bytemode, int sizeflag) alt = "rdtscp"; break; default: - OP_E (bytemode, sizeflag); + OP_M (bytemode, sizeflag); return; } /* Override "invlpg". */ -- 2.7.4