diff options
author | Alexandru Dutu <alexandru.dutu@amd.com> | 2016-02-06 17:21:20 -0800 |
---|---|---|
committer | Alexandru Dutu <alexandru.dutu@amd.com> | 2016-02-06 17:21:20 -0800 |
commit | 0f27d70e90c20ba21d3f6a3360a11d9d5e9ee133 (patch) | |
tree | b9d33a3e92e6d20e5f82d238bf6e94dfc4e2301e /src/arch/x86/insts | |
parent | 5200e04e92b487181d4a678231564272730e04a2 (diff) | |
download | gem5-0f27d70e90c20ba21d3f6a3360a11d9d5e9ee133.tar.xz |
x86: revamp cmpxchg8b/cmpxchg16b implementation
The previous implementation did a pair of nested RMW operations,
which isn't compatible with the way that locked RMW operations are
implemented in the cache models. It was convenient though in that
it didn't require any new micro-ops, and supported cmpxchg16b using
64-bit memory ops. It also worked in AtomicSimpleCPU where
atomicity was guaranteed by the core and not by the memory system.
It did not work with timing CPU models though.
This new implementation defines new 'split' load and store micro-ops
which allow a single memory operation to use a pair of registers as
the source or destination, then uses a single ldsplit/stsplit RMW
pair to implement cmpxchg. This patch requires support for 128-bit
memory accesses in the ISA (added via a separate patch) to support
cmpxchg16b.
Diffstat (limited to 'src/arch/x86/insts')
-rw-r--r-- | src/arch/x86/insts/microldstop.cc | 18 | ||||
-rw-r--r-- | src/arch/x86/insts/microldstop.hh | 74 |
2 files changed, 85 insertions, 7 deletions
diff --git a/src/arch/x86/insts/microldstop.cc b/src/arch/x86/insts/microldstop.cc index e98767992..ea38ebfe1 100644 --- a/src/arch/x86/insts/microldstop.cc +++ b/src/arch/x86/insts/microldstop.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2015 Advanced Micro Devices, Inc. * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -58,4 +59,21 @@ namespace X86ISA addressSize, false); return response.str(); } + + std::string LdStSplitOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + int baseRegIdx = flags[IsLoad] ? 0 : 2; + response << "["; + printDestReg(response, baseRegIdx, dataSize); + response << ", "; + printDestReg(response, baseRegIdx+1, dataSize); + response << "], "; + printMem(response, segment, scale, index, base, disp, + addressSize, false); + return response.str(); + } } diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh index 32f3fec04..c36fbacfd 100644 --- a/src/arch/x86/insts/microldstop.hh +++ b/src/arch/x86/insts/microldstop.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2015 Advanced Micro Devices, Inc. * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -49,9 +50,9 @@ namespace X86ISA { /** - * Base class for load and store ops + * Base class for memory ops */ - class LdStOp : public X86MicroopBase + class MemOp : public X86MicroopBase { protected: const uint8_t scale; @@ -59,34 +60,93 @@ namespace X86ISA const RegIndex base; const uint64_t disp; const uint8_t segment; - const RegIndex data; const uint8_t dataSize; const uint8_t addressSize; const Request::FlagsType memFlags; RegIndex foldOBit, foldABit; //Constructor - LdStOp(ExtMachInst _machInst, + MemOp(ExtMachInst _machInst, const char * mnem, const char * _instMnem, uint64_t setFlags, uint8_t _scale, InstRegIndex _index, InstRegIndex _base, uint64_t _disp, InstRegIndex _segment, - InstRegIndex _data, uint8_t _dataSize, uint8_t _addressSize, Request::FlagsType _memFlags, OpClass __opClass) : X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass), scale(_scale), index(_index.idx), base(_base.idx), disp(_disp), segment(_segment.idx), - data(_data.idx), dataSize(_dataSize), addressSize(_addressSize), memFlags(_memFlags | _segment.idx) { assert(_segment.idx < NUM_SEGMENTREGS); - foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0; + foldOBit = + (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0; foldABit = (addressSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0; } + }; + + /** + * Base class for load and store ops using one register + */ + class LdStOp : public MemOp + { + protected: + const RegIndex data; + + //Constructor + LdStOp(ExtMachInst _machInst, + const char * mnem, const char * _instMnem, + uint64_t setFlags, + uint8_t _scale, InstRegIndex _index, InstRegIndex _base, + uint64_t _disp, InstRegIndex _segment, + InstRegIndex _data, + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags, + OpClass __opClass) : + MemOp(_machInst, mnem, _instMnem, setFlags, + _scale, _index, _base, _disp, _segment, + _dataSize, _addressSize, _memFlags, + __opClass), + data(_data.idx) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; + + /** + * Base class for load and store ops using two registers, we will + * call them split ops for this reason. These are mainly used to + * implement cmpxchg8b and cmpxchg16b. + */ + class LdStSplitOp : public MemOp + { + protected: + const RegIndex dataLow; + const RegIndex dataHi; + + //Constructor + LdStSplitOp(ExtMachInst _machInst, + const char * mnem, const char * _instMnem, + uint64_t setFlags, + uint8_t _scale, InstRegIndex _index, InstRegIndex _base, + uint64_t _disp, InstRegIndex _segment, + InstRegIndex _dataLow, InstRegIndex _dataHi, + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags, + OpClass __opClass) : + MemOp(_machInst, mnem, _instMnem, setFlags, + _scale, _index, _base, _disp, _segment, + _dataSize, _addressSize, _memFlags, + __opClass), + dataLow(_dataLow.idx), + dataHi(_dataHi.idx) + { + } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; |