diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-02-08 18:20:41 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2012-02-08 18:20:41 +0000 |
commit | 42164a7195927ffea7ad125ae132226c2fdec512 (patch) | |
tree | 97364b4ec2e7c7cef5eded0a0c88077469a678e3 /gas/config/tc-i386.c | |
parent | c71bb1cf63afec7dd2303fd698c33b887441d1c8 (diff) | |
download | gdb-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.c | 76 |
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])); |