aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2012-02-08 18:20:41 +0000
committerH.J. Lu <hjl.tools@gmail.com>2012-02-08 18:20:41 +0000
commit42164a7195927ffea7ad125ae132226c2fdec512 (patch)
tree97364b4ec2e7c7cef5eded0a0c88077469a678e3 /gas/config/tc-i386.c
parentc71bb1cf63afec7dd2303fd698c33b887441d1c8 (diff)
downloadgdb-42164a7195927ffea7ad125ae132226c2fdec512.zip
gdb-42164a7195927ffea7ad125ae132226c2fdec512.tar.gz
gdb-42164a7195927ffea7ad125ae132226c2fdec512.tar.bz2
Implement Intel Transactional Synchronization Extensions
gas/ 2012-02-08 H.J. Lu <hongjiu.lu@intel.com> * config/tc-i386.c (HLE_PREFIX): New. (check_hle): Likewise. (_i386_insn): Add have_hle. (cpu_arch): Add .hle and .rtm. (md_assemble): Call check_hle if i.have_hle isn't zero. (parse_insn): Set i.have_hle to 1 for HLE prefix. (output_jump): Support up to 2 byte opcode. * doc/c-i386.texi: Document hle/.hle and rtm/.rtm. gas/testsuite/ 2012-02-08 H.J. Lu <hongjiu.lu@intel.com> * gas/i386/hle-intel.d: New. * gas/i386/hle.d: Likewise. * gas/i386/hle.s: Likewise. * gas/i386/hlebad.l: Likewise. * gas/i386/hlebad.s: Likewise. * gas/i386/rtm-intel.d: Likewise. * gas/i386/rtm.d: Likewise. * gas/i386/rtm.s: Likewise. * gas/i386/x86-64-hle-intel.d: Likewise. * gas/i386/x86-64-hle.d: Likewise. * gas/i386/x86-64-hle.s: Likewise. * gas/i386/x86-64-hlebad.l: Likewise. * gas/i386/x86-64-hlebad.s: Likewise. * gas/i386/x86-64-rtm-intel.d: Likewise. * gas/i386/x86-64-rtm.d: Likewise. * gas/i386/x86-64-rtm.s: Likewise. * gas/i386/i386.exp: Run hle, hle-intel, hlebad x86-64-hle, rtm, rtm-intel, x86-64-hle-intel, x86-64-hlebad, x86-64-rtm and x86-64-rtm-intel. include/opcode/ 2012-02-08 H.J. Lu <hongjiu.lu@intel.com> * i386.h (XACQUIRE_PREFIX_OPCODE): New. (XRELEASE_PREFIX_OPCODE): Likewise. opcodes/ 2012-02-08 H.J. Lu <hongjiu.lu@intel.com> * i386-dis.c (HLE_Fixup1): New. (HLE_Fixup2): Likewise. (HLE_Fixup3): Likewise. (Ebh1): Likewise. (Evh1): Likewise. (Ebh2): Likewise. (Evh2): Likewise. (Ebh3): Likewise. (Evh3): Likewise. (MOD_C6_REG_7): Likewise. (MOD_C7_REG_7): Likewise. (RM_C6_REG_7): Likewise. (RM_C7_REG_7): Likewise. (XACQUIRE_PREFIX): Likewise. (XRELEASE_PREFIX): Likewise. (dis386): Use Ebh1/Evh1 on add, adc, and, btc, btr, bts, cmpxchg, dec, inc, neg, not, or, sbb, sub, xor and xadd. Use Ebh2/Evh2 on xchg. Use Ebh3/Evh3 on mov. (reg_table): Use Ebh1/Evh1 on add, adc, and, dec, inc, neg, not, or, sbb, sub and xor. Use Ebh3/Evh3 on mov. Use MOD_C6_REG_7 and MOD_C7_REG_7. (mod_table): Add MOD_C6_REG_7 and MOD_C7_REG_7. (rm_table): Add RM_C6_REG_7 and RM_C7_REG_7. Add xend and xtest. (prefix_name): Handle XACQUIRE_PREFIX and XRELEASE_PREFIX. (CMPXCHG8B_Fixup): Handle HLE prefix on cmpxchg8b. * i386-gen.c (cpu_flag_init): Add CPU_HLE_FLAGS and CPU_RTM_FLAGS. (cpu_flags): Add CpuHLE and CpuRTM. (opcode_modifiers): Add HLEPrefixOk. * i386-opc.h (CpuHLE): New. (CpuRTM): Likewise. (HLEPrefixOk): Likewise. (i386_cpu_flags): Add cpuhle and cpurtm. (i386_opcode_modifier): Add hleprefixok. * i386-opc.tbl: Add HLEPrefixOk=3 to mov. Add HLEPrefixOk to add, adc, and, btc, btr, bts, cmpxchg, dec, inc, neg, not, or, sbb, sub, xor and xadd. Add HLEPrefixOk=2 to xchg with memory operand. Add xacquire, xrelease, xabort, xbegin, xend and xtest. * i386-init.h: Regenerated. * i386-tbl.h: Likewise.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c76
1 files changed, 72 insertions, 4 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 75ed56c..97cb68e 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -60,12 +60,13 @@
WAIT_PREFIX must be the first prefix since FWAIT is really is an
instruction, and so must come before any prefixes.
The preferred prefix order is SEG_PREFIX, ADDR_PREFIX, DATA_PREFIX,
- REP_PREFIX, LOCK_PREFIX. */
+ REP_PREFIX/HLE_PREFIX, LOCK_PREFIX. */
#define WAIT_PREFIX 0
#define SEG_PREFIX 1
#define ADDR_PREFIX 2
#define DATA_PREFIX 3
#define REP_PREFIX 4
+#define HLE_PREFIX REP_PREFIX
#define LOCK_PREFIX 5
#define REX_PREFIX 6 /* must come last. */
#define MAX_PREFIXES 7 /* max prefixes per opcode */
@@ -288,6 +289,9 @@ struct _i386_insn
disp_encoding_32bit
} disp_encoding;
+ /* Have HLE prefix. */
+ unsigned int have_hle;
+
/* Error message. */
enum i386_error error;
};
@@ -731,6 +735,10 @@ static const arch_entry cpu_arch[] =
CPU_EPT_FLAGS, 0, 0 },
{ STRING_COMMA_LEN (".lzcnt"), PROCESSOR_UNKNOWN,
CPU_LZCNT_FLAGS, 0, 0 },
+ { STRING_COMMA_LEN (".hle"), PROCESSOR_UNKNOWN,
+ CPU_HLE_FLAGS, 0, 0 },
+ { STRING_COMMA_LEN (".rtm"), PROCESSOR_UNKNOWN,
+ CPU_RTM_FLAGS, 0, 0 },
{ STRING_COMMA_LEN (".invpcid"), PROCESSOR_UNKNOWN,
CPU_INVPCID_FLAGS, 0, 0 },
{ STRING_COMMA_LEN (".clflush"), PROCESSOR_UNKNOWN,
@@ -2999,6 +3007,50 @@ process_immext (void)
i.tm.extension_opcode = None;
}
+
+static int
+check_hle (void)
+{
+ switch (i.tm.opcode_modifier.hleprefixok)
+ {
+ default:
+ abort ();
+ case 0:
+ if (i.prefix[HLE_PREFIX] == XACQUIRE_PREFIX_OPCODE)
+ as_bad (_("invalid instruction `%s' after `xacquire'"),
+ i.tm.name);
+ else
+ as_bad (_("invalid instruction `%s' after `xrelease'"),
+ i.tm.name);
+ return 0;
+ case 1:
+ if (i.prefix[LOCK_PREFIX])
+ return 1;
+ if (i.prefix[HLE_PREFIX] == XACQUIRE_PREFIX_OPCODE)
+ as_bad (_("missing `lock' with `xacquire'"));
+ else
+ as_bad (_("missing `lock' with `xrelease'"));
+ return 0;
+ case 2:
+ return 1;
+ case 3:
+ if (i.prefix[HLE_PREFIX] != XRELEASE_PREFIX_OPCODE)
+ {
+ as_bad (_("instruction `%s' after `xacquire' not allowed"),
+ i.tm.name);
+ return 0;
+ }
+ if (i.mem_operands == 0
+ || !operand_type_check (i.types[i.operands - 1], anymem))
+ {
+ as_bad (_("memory destination needed for instruction `%s'"
+ " after `xrelease'"), i.tm.name);
+ return 0;
+ }
+ return 1;
+ }
+}
+
/* This is the guts of the machine-dependent assembler. LINE points to a
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
@@ -3117,6 +3169,10 @@ md_assemble (char *line)
return;
}
+ /* Check if HLE prefix is OK. */
+ if (i.have_hle && !check_hle ())
+ return;
+
/* Check string instruction segment overrides. */
if (i.tm.opcode_modifier.isstring && i.mem_operands != 0)
{
@@ -3320,7 +3376,10 @@ parse_insn (char *line, char *mnemonic)
case PREFIX_EXIST:
return NULL;
case PREFIX_REP:
- expecting_string_instruction = current_templates->start->name;
+ if (current_templates->start->cpu_flags.bitfield.cpuhle)
+ i.have_hle = 1;
+ else
+ expecting_string_instruction = current_templates->start->name;
break;
default:
break;
@@ -6041,8 +6100,17 @@ output_jump (void)
if (i.prefixes != 0 && !intel_syntax)
as_warn (_("skipping prefixes on this instruction"));
- p = frag_more (1 + size);
- *p++ = i.tm.base_opcode;
+ p = frag_more (i.tm.opcode_length + size);
+ switch (i.tm.opcode_length)
+ {
+ case 2:
+ *p++ = i.tm.base_opcode >> 8;
+ case 1:
+ *p++ = i.tm.base_opcode;
+ break;
+ default:
+ abort ();
+ }
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));