ldstop.isa revision 12234:78ece221f9f5
16145Snate@binkert.org// Copyright (c) 2007-2008 The Hewlett-Packard Development Company 26145Snate@binkert.org// Copyright (c) 2015 Advanced Micro Devices, Inc. 36145Snate@binkert.org// All rights reserved. 46145Snate@binkert.org// 56145Snate@binkert.org// The license below extends only to copyright in the software and shall 66145Snate@binkert.org// not be construed as granting a license to any other intellectual 76145Snate@binkert.org// property including but not limited to intellectual property relating 86145Snate@binkert.org// to a hardware implementation of the functionality of the software 96145Snate@binkert.org// licensed hereunder. You may use the software subject to the license 106145Snate@binkert.org// terms below provided that you ensure that this notice is replicated 116145Snate@binkert.org// unmodified and in its entirety in all distributions of the software, 126145Snate@binkert.org// modified or unmodified, in source code or in binary form. 136145Snate@binkert.org// 146145Snate@binkert.org// Copyright (c) 2008 The Regents of The University of Michigan 156145Snate@binkert.org// All rights reserved. 166145Snate@binkert.org// 176145Snate@binkert.org// Redistribution and use in source and binary forms, with or without 186145Snate@binkert.org// modification, are permitted provided that the following conditions are 196145Snate@binkert.org// met: redistributions of source code must retain the above copyright 206145Snate@binkert.org// notice, this list of conditions and the following disclaimer; 216145Snate@binkert.org// redistributions in binary form must reproduce the above copyright 226145Snate@binkert.org// notice, this list of conditions and the following disclaimer in the 236145Snate@binkert.org// documentation and/or other materials provided with the distribution; 246145Snate@binkert.org// neither the name of the copyright holders nor the names of its 256145Snate@binkert.org// contributors may be used to endorse or promote products derived from 266145Snate@binkert.org// this software without specific prior written permission. 276145Snate@binkert.org// 286145Snate@binkert.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297832Snate@binkert.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307832Snate@binkert.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 318645Snilay@cs.wisc.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327054Snate@binkert.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 338232Snate@binkert.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 346154Snate@binkert.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 358229Snate@binkert.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 366154Snate@binkert.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 377054Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 386154Snate@binkert.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 396145Snate@binkert.org// 407055Snate@binkert.org// Authors: Gabe Black 417055Snate@binkert.org 426145Snate@binkert.org////////////////////////////////////////////////////////////////////////// 436145Snate@binkert.org// 446145Snate@binkert.org// LdStOp Microop templates 456145Snate@binkert.org// 466145Snate@binkert.org////////////////////////////////////////////////////////////////////////// 476145Snate@binkert.org 486145Snate@binkert.org// LEA template 496145Snate@binkert.org 506145Snate@binkert.orgdef template MicroLeaExecute {{ 517054Snate@binkert.org Fault %(class_name)s::execute(ExecContext *xc, 528259SBrad.Beckmann@amd.com Trace::InstRecord *traceData) const 536145Snate@binkert.org { 548259SBrad.Beckmann@amd.com Fault fault = NoFault; 557054Snate@binkert.org Addr EA; 566145Snate@binkert.org 576145Snate@binkert.org %(op_decl)s; 587054Snate@binkert.org %(op_rd)s; 598259SBrad.Beckmann@amd.com %(ea_code)s; 606145Snate@binkert.org DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 618259SBrad.Beckmann@amd.com 627054Snate@binkert.org %(code)s; 636145Snate@binkert.org if(fault == NoFault) 646145Snate@binkert.org { 657054Snate@binkert.org %(op_wb)s; 668259SBrad.Beckmann@amd.com } 678259SBrad.Beckmann@amd.com 686145Snate@binkert.org return fault; 697054Snate@binkert.org } 707054Snate@binkert.org}}; 716145Snate@binkert.org 727832Snate@binkert.orgdef template MicroLeaDeclare {{ 737054Snate@binkert.org class %(class_name)s : public %(base_class)s 747054Snate@binkert.org { 758259SBrad.Beckmann@amd.com public: 766145Snate@binkert.org %(class_name)s(ExtMachInst _machInst, 777054Snate@binkert.org const char * instMnem, uint64_t setFlags, 787054Snate@binkert.org uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 796145Snate@binkert.org uint64_t _disp, InstRegIndex _segment, 806145Snate@binkert.org InstRegIndex _data, 817054Snate@binkert.org uint8_t _dataSize, uint8_t _addressSize, 827054Snate@binkert.org Request::FlagsType _memFlags); 836145Snate@binkert.org 847054Snate@binkert.org %(BasicExecDeclare)s 857054Snate@binkert.org }; 867054Snate@binkert.org}}; 877054Snate@binkert.org 886145Snate@binkert.org// Load templates 896145Snate@binkert.org 907054Snate@binkert.orgdef template MicroLoadExecute {{ 917454Snate@binkert.org Fault %(class_name)s::execute(ExecContext *xc, 927454Snate@binkert.org Trace::InstRecord *traceData) const 936145Snate@binkert.org { 947054Snate@binkert.org Fault fault = NoFault; 957054Snate@binkert.org Addr EA; 967054Snate@binkert.org 977054Snate@binkert.org %(op_decl)s; 986145Snate@binkert.org %(op_rd)s; 997454Snate@binkert.org %(ea_code)s; 1007054Snate@binkert.org DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 1017454Snate@binkert.org 1027054Snate@binkert.org fault = readMemAtomic(xc, traceData, EA, Mem, 1037054Snate@binkert.org %(memDataSize)s, memFlags); 1047054Snate@binkert.org 1056145Snate@binkert.org if (fault == NoFault) { 1066145Snate@binkert.org %(code)s; 1076145Snate@binkert.org } else if (memFlags & Request::PREFETCH) { 1087054Snate@binkert.org // For prefetches, ignore any faults/exceptions. 1097054Snate@binkert.org return NoFault; 1106145Snate@binkert.org } 1117454Snate@binkert.org if(fault == NoFault) 1127454Snate@binkert.org { 1137454Snate@binkert.org %(op_wb)s; 1146145Snate@binkert.org } 1157054Snate@binkert.org 1167054Snate@binkert.org return fault; 1178608Snilay@cs.wisc.edu } 1188608Snilay@cs.wisc.edu}}; 1197054Snate@binkert.org 1207054Snate@binkert.orgdef template MicroLoadInitiateAcc {{ 1216145Snate@binkert.org Fault %(class_name)s::initiateAcc(ExecContext * xc, 1226145Snate@binkert.org Trace::InstRecord * traceData) const 1237054Snate@binkert.org { 1247054Snate@binkert.org Fault fault = NoFault; 1256145Snate@binkert.org Addr EA; 1267054Snate@binkert.org 1277054Snate@binkert.org %(op_decl)s; 1287054Snate@binkert.org %(op_rd)s; 1296145Snate@binkert.org %(ea_code)s; 1307054Snate@binkert.org DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 1317054Snate@binkert.org 1327054Snate@binkert.org fault = initiateMemRead(xc, traceData, EA, 1337054Snate@binkert.org %(memDataSize)s, memFlags); 1347054Snate@binkert.org 1357054Snate@binkert.org return fault; 1366145Snate@binkert.org } 1377054Snate@binkert.org}}; 1387054Snate@binkert.org 1397054Snate@binkert.orgdef template MicroLoadCompleteAcc {{ 1407054Snate@binkert.org Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext * xc, 1417054Snate@binkert.org Trace::InstRecord * traceData) const 1427054Snate@binkert.org { 1436145Snate@binkert.org Fault fault = NoFault; 1446145Snate@binkert.org 1457054Snate@binkert.org %(op_decl)s; 1467054Snate@binkert.org %(op_rd)s; 1477054Snate@binkert.org 1487054Snate@binkert.org getMem(pkt, Mem, %(memDataSize)s, traceData); 1497054Snate@binkert.org 1507054Snate@binkert.org %(code)s; 1517054Snate@binkert.org 1527054Snate@binkert.org if(fault == NoFault) 1537054Snate@binkert.org { 1547054Snate@binkert.org %(op_wb)s; 1557054Snate@binkert.org } 1567054Snate@binkert.org 1577054Snate@binkert.org return fault; 1587054Snate@binkert.org } 1597054Snate@binkert.org}}; 1607054Snate@binkert.org 1617054Snate@binkert.org// Store templates 1627054Snate@binkert.org 1637453Snate@binkert.orgdef template MicroStoreExecute {{ 1647054Snate@binkert.org Fault %(class_name)s::execute(ExecContext * xc, 1657054Snate@binkert.org Trace::InstRecord *traceData) const 1667054Snate@binkert.org { 1677780Snilay@cs.wisc.edu Fault fault = NoFault; 1687780Snilay@cs.wisc.edu 1697054Snate@binkert.org Addr EA; 1707780Snilay@cs.wisc.edu %(op_decl)s; 1717054Snate@binkert.org %(op_rd)s; 1727054Snate@binkert.org %(ea_code)s; 1737054Snate@binkert.org DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 1747054Snate@binkert.org 1757054Snate@binkert.org %(code)s; 1767054Snate@binkert.org 1777054Snate@binkert.org if(fault == NoFault) 1787054Snate@binkert.org { 1797780Snilay@cs.wisc.edu fault = writeMemAtomic(xc, traceData, Mem, %(memDataSize)s, EA, 1807054Snate@binkert.org memFlags, NULL); 1817054Snate@binkert.org if(fault == NoFault) 1827054Snate@binkert.org { 1837054Snate@binkert.org %(op_wb)s; 1847054Snate@binkert.org } 1857054Snate@binkert.org } 1867054Snate@binkert.org 1877054Snate@binkert.org return fault; 1887054Snate@binkert.org } 1897054Snate@binkert.org}}; 1907054Snate@binkert.org 1917780Snilay@cs.wisc.edudef template MicroStoreInitiateAcc {{ 1927054Snate@binkert.org Fault %(class_name)s::initiateAcc(ExecContext * xc, 1937054Snate@binkert.org Trace::InstRecord * traceData) const 1947054Snate@binkert.org { 1957054Snate@binkert.org Fault fault = NoFault; 1966145Snate@binkert.org 1976145Snate@binkert.org Addr EA; 1987054Snate@binkert.org %(op_decl)s; 1997054Snate@binkert.org %(op_rd)s; 2007054Snate@binkert.org %(ea_code)s; 2016145Snate@binkert.org DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 2027054Snate@binkert.org 2037054Snate@binkert.org %(code)s; 2046145Snate@binkert.org 2057054Snate@binkert.org if(fault == NoFault) 2067054Snate@binkert.org { 2077054Snate@binkert.org fault = writeMemTiming(xc, traceData, Mem, %(memDataSize)s, EA, 2087054Snate@binkert.org memFlags, NULL); 2097054Snate@binkert.org } 2107054Snate@binkert.org return fault; 2117054Snate@binkert.org } 2127780Snilay@cs.wisc.edu}}; 2137054Snate@binkert.org 2147780Snilay@cs.wisc.edudef template MicroStoreCompleteAcc {{ 2157054Snate@binkert.org Fault %(class_name)s::completeAcc(PacketPtr pkt, 2167054Snate@binkert.org ExecContext * xc, Trace::InstRecord * traceData) const 2177054Snate@binkert.org { 2187054Snate@binkert.org %(op_decl)s; 2197054Snate@binkert.org %(op_rd)s; 2206145Snate@binkert.org %(complete_code)s; 2216145Snate@binkert.org %(op_wb)s; 2227054Snate@binkert.org return NoFault; 2237054Snate@binkert.org } 2246145Snate@binkert.org}}; 2257054Snate@binkert.org 2266145Snate@binkert.org// Common templates 2276145Snate@binkert.org 2287054Snate@binkert.org//This delcares the initiateAcc function in memory operations 2297054Snate@binkert.orgdef template InitiateAccDeclare {{ 2306145Snate@binkert.org Fault initiateAcc(ExecContext *, Trace::InstRecord *) const; 2317054Snate@binkert.org}}; 2327054Snate@binkert.org 2336145Snate@binkert.org//This declares the completeAcc function in memory operations 2347054Snate@binkert.orgdef template CompleteAccDeclare {{ 2357054Snate@binkert.org Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const; 2367054Snate@binkert.org}}; 2377054Snate@binkert.org 2386145Snate@binkert.orgdef template MicroLdStOpDeclare {{ 2396145Snate@binkert.org class %(class_name)s : public %(base_class)s 2406145Snate@binkert.org { 2417054Snate@binkert.org public: 2427054Snate@binkert.org %(class_name)s(ExtMachInst _machInst, 2436145Snate@binkert.org const char * instMnem, uint64_t setFlags, 2446145Snate@binkert.org uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 2456145Snate@binkert.org uint64_t _disp, InstRegIndex _segment, 2467054Snate@binkert.org InstRegIndex _data, 2477054Snate@binkert.org uint8_t _dataSize, uint8_t _addressSize, 2486145Snate@binkert.org Request::FlagsType _memFlags); 2497054Snate@binkert.org 2507054Snate@binkert.org %(BasicExecDeclare)s 2516145Snate@binkert.org 2526145Snate@binkert.org %(InitiateAccDeclare)s 2537054Snate@binkert.org 2547054Snate@binkert.org %(CompleteAccDeclare)s 2556145Snate@binkert.org }; 2568054Sksewell@umich.edu}}; 2576145Snate@binkert.org 2586145Snate@binkert.org// LdStSplitOp is a load or store that uses a pair of regs as the 2597054Snate@binkert.org// source or destination. Used for cmpxchg{8,16}b. 2607054Snate@binkert.orgdef template MicroLdStSplitOpDeclare {{ 2617054Snate@binkert.org class %(class_name)s : public %(base_class)s 2627054Snate@binkert.org { 2636145Snate@binkert.org public: 2647054Snate@binkert.org %(class_name)s(ExtMachInst _machInst, 2657054Snate@binkert.org const char * instMnem, uint64_t setFlags, 2667054Snate@binkert.org uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 2676145Snate@binkert.org uint64_t _disp, InstRegIndex _segment, 2687054Snate@binkert.org InstRegIndex _dataLow, InstRegIndex _dataHi, 2697054Snate@binkert.org uint8_t _dataSize, uint8_t _addressSize, 2707054Snate@binkert.org Request::FlagsType _memFlags); 2717054Snate@binkert.org 2727054Snate@binkert.org %(BasicExecDeclare)s 2736145Snate@binkert.org 274 %(InitiateAccDeclare)s 275 276 %(CompleteAccDeclare)s 277 }; 278}}; 279 280def template MicroLdStOpConstructor {{ 281 %(class_name)s::%(class_name)s( 282 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 283 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 284 uint64_t _disp, InstRegIndex _segment, 285 InstRegIndex _data, 286 uint8_t _dataSize, uint8_t _addressSize, 287 Request::FlagsType _memFlags) : 288 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 289 _scale, _index, _base, 290 _disp, _segment, _data, 291 _dataSize, _addressSize, _memFlags, %(op_class)s) 292 { 293 %(constructor)s; 294 } 295}}; 296 297def template MicroLdStSplitOpConstructor {{ 298 %(class_name)s::%(class_name)s( 299 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 300 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 301 uint64_t _disp, InstRegIndex _segment, 302 InstRegIndex _dataLow, InstRegIndex _dataHi, 303 uint8_t _dataSize, uint8_t _addressSize, 304 Request::FlagsType _memFlags) : 305 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 306 _scale, _index, _base, 307 _disp, _segment, _dataLow, _dataHi, 308 _dataSize, _addressSize, _memFlags, %(op_class)s) 309 { 310 %(constructor)s; 311 } 312}}; 313 314let {{ 315 class LdStOp(X86Microop): 316 def __init__(self, data, segment, addr, disp, 317 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, 318 implicitStack): 319 self.data = data 320 [self.scale, self.index, self.base] = addr 321 self.disp = disp 322 self.segment = segment 323 self.dataSize = dataSize 324 self.addressSize = addressSize 325 self.memFlags = baseFlags 326 if atCPL0: 327 self.memFlags += " | (CPL0FlagBit << FlagShift)" 328 self.instFlags = "" 329 if prefetch: 330 self.memFlags += " | Request::PREFETCH" 331 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" 332 if nonSpec: 333 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" 334 # For implicit stack operations, we should use *not* use the 335 # alternative addressing mode for loads/stores if the prefix is set 336 if not implicitStack: 337 self.memFlags += " | (machInst.legacy.addr ? " + \ 338 "(AddrSizeFlagBit << FlagShift) : 0)" 339 340 def getAllocator(self, microFlags): 341 allocator = '''new %(class_name)s(machInst, macrocodeBlock, 342 %(flags)s, %(scale)s, %(index)s, %(base)s, 343 %(disp)s, %(segment)s, %(data)s, 344 %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % { 345 "class_name" : self.className, 346 "flags" : self.microFlagsText(microFlags) + self.instFlags, 347 "scale" : self.scale, "index" : self.index, 348 "base" : self.base, 349 "disp" : self.disp, 350 "segment" : self.segment, "data" : self.data, 351 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 352 "memFlags" : self.memFlags} 353 return allocator 354 355 class BigLdStOp(X86Microop): 356 def __init__(self, data, segment, addr, disp, 357 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, 358 implicitStack): 359 self.data = data 360 [self.scale, self.index, self.base] = addr 361 self.disp = disp 362 self.segment = segment 363 self.dataSize = dataSize 364 self.addressSize = addressSize 365 self.memFlags = baseFlags 366 if atCPL0: 367 self.memFlags += " | (CPL0FlagBit << FlagShift)" 368 self.instFlags = "" 369 if prefetch: 370 self.memFlags += " | Request::PREFETCH" 371 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" 372 if nonSpec: 373 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" 374 # For implicit stack operations, we should use *not* use the 375 # alternative addressing mode for loads/stores if the prefix is set 376 if not implicitStack: 377 self.memFlags += " | (machInst.legacy.addr ? " + \ 378 "(AddrSizeFlagBit << FlagShift) : 0)" 379 380 def getAllocator(self, microFlags): 381 allocString = ''' 382 (%(dataSize)s >= 4) ? 383 (StaticInstPtr)(new %(class_name)sBig(machInst, 384 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 385 %(base)s, %(disp)s, %(segment)s, %(data)s, 386 %(dataSize)s, %(addressSize)s, %(memFlags)s)) : 387 (StaticInstPtr)(new %(class_name)s(machInst, 388 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 389 %(base)s, %(disp)s, %(segment)s, %(data)s, 390 %(dataSize)s, %(addressSize)s, %(memFlags)s)) 391 ''' 392 allocator = allocString % { 393 "class_name" : self.className, 394 "flags" : self.microFlagsText(microFlags) + self.instFlags, 395 "scale" : self.scale, "index" : self.index, 396 "base" : self.base, 397 "disp" : self.disp, 398 "segment" : self.segment, "data" : self.data, 399 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 400 "memFlags" : self.memFlags} 401 return allocator 402 403 class LdStSplitOp(LdStOp): 404 def __init__(self, data, segment, addr, disp, 405 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, 406 implicitStack): 407 super(LdStSplitOp, self).__init__(0, segment, addr, disp, 408 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, 409 implicitStack) 410 (self.dataLow, self.dataHi) = data 411 412 def getAllocator(self, microFlags): 413 allocString = '''(StaticInstPtr)(new %(class_name)s(machInst, 414 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 415 %(base)s, %(disp)s, %(segment)s, 416 %(dataLow)s, %(dataHi)s, 417 %(dataSize)s, %(addressSize)s, %(memFlags)s)) 418 ''' 419 allocator = allocString % { 420 "class_name" : self.className, 421 "flags" : self.microFlagsText(microFlags) + self.instFlags, 422 "scale" : self.scale, "index" : self.index, 423 "base" : self.base, 424 "disp" : self.disp, 425 "segment" : self.segment, 426 "dataLow" : self.dataLow, "dataHi" : self.dataHi, 427 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 428 "memFlags" : self.memFlags} 429 return allocator 430 431}}; 432 433let {{ 434 435 # Make these empty strings so that concatenating onto 436 # them will always work. 437 header_output = "" 438 decoder_output = "" 439 exec_output = "" 440 441 segmentEAExpr = \ 442 'bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);' 443 444 calculateEA = 'EA = SegBase + ' + segmentEAExpr 445 446 def defineMicroLoadOp(mnemonic, code, bigCode='', 447 mem_flags="0", big=True, nonSpec=False, 448 implicitStack=False): 449 global header_output 450 global decoder_output 451 global exec_output 452 global microopClasses 453 Name = mnemonic 454 name = mnemonic.lower() 455 456 # Build up the all register version of this micro op 457 iops = [InstObjParams(name, Name, 'X86ISA::LdStOp', 458 { "code": code, 459 "ea_code": calculateEA, 460 "memDataSize": "dataSize" })] 461 if big: 462 iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp', 463 { "code": bigCode, 464 "ea_code": calculateEA, 465 "memDataSize": "dataSize" })] 466 for iop in iops: 467 header_output += MicroLdStOpDeclare.subst(iop) 468 decoder_output += MicroLdStOpConstructor.subst(iop) 469 exec_output += MicroLoadExecute.subst(iop) 470 exec_output += MicroLoadInitiateAcc.subst(iop) 471 exec_output += MicroLoadCompleteAcc.subst(iop) 472 473 if implicitStack: 474 # For instructions that implicitly access the stack, the address 475 # size is the same as the stack segment pointer size, not the 476 # address size if specified by the instruction prefix 477 addressSize = "env.stackSize" 478 else: 479 addressSize = "env.addressSize" 480 481 base = LdStOp 482 if big: 483 base = BigLdStOp 484 class LoadOp(base): 485 def __init__(self, data, segment, addr, disp = 0, 486 dataSize="env.dataSize", 487 addressSize=addressSize, 488 atCPL0=False, prefetch=False, nonSpec=nonSpec, 489 implicitStack=implicitStack): 490 super(LoadOp, self).__init__(data, segment, addr, 491 disp, dataSize, addressSize, mem_flags, 492 atCPL0, prefetch, nonSpec, implicitStack) 493 self.className = Name 494 self.mnemonic = name 495 496 microopClasses[name] = LoadOp 497 498 defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);', 499 'Data = Mem & mask(dataSize * 8);') 500 defineMicroLoadOp('Ldis', 'Data = merge(Data, Mem, dataSize);', 501 'Data = Mem & mask(dataSize * 8);', 502 implicitStack=True) 503 defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 504 'Data = Mem & mask(dataSize * 8);', 505 '(StoreCheck << FlagShift)') 506 defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);', 507 'Data = Mem & mask(dataSize * 8);', 508 '(StoreCheck << FlagShift) | Request::LOCKED_RMW', 509 nonSpec=True) 510 511 defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False) 512 513 defineMicroLoadOp('Ldfp87', code=''' 514 switch (dataSize) 515 { 516 case 4: 517 FpData_df = *(float *)&Mem; 518 break; 519 case 8: 520 FpData_df = *(double *)&Mem; 521 break; 522 default: 523 panic("Unhandled data size in LdFp87.\\n"); 524 } 525 ''', big = False) 526 527 # Load integer from memory into x87 top-of-stack register. 528 # Used to implement fild instruction. 529 defineMicroLoadOp('Ldifp87', code=''' 530 switch (dataSize) 531 { 532 case 2: 533 FpData_df = (int64_t)sext<16>(Mem); 534 break; 535 case 4: 536 FpData_df = (int64_t)sext<32>(Mem); 537 break; 538 case 8: 539 FpData_df = (int64_t)Mem; 540 break; 541 default: 542 panic("Unhandled data size in LdIFp87.\\n"); 543 } 544 ''', big = False) 545 546 def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False): 547 global header_output 548 global decoder_output 549 global exec_output 550 global microopClasses 551 Name = mnemonic 552 name = mnemonic.lower() 553 554 iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp', 555 { "code": code, 556 "ea_code": calculateEA, 557 "memDataSize": "2 * dataSize" }) 558 559 header_output += MicroLdStSplitOpDeclare.subst(iop) 560 decoder_output += MicroLdStSplitOpConstructor.subst(iop) 561 exec_output += MicroLoadExecute.subst(iop) 562 exec_output += MicroLoadInitiateAcc.subst(iop) 563 exec_output += MicroLoadCompleteAcc.subst(iop) 564 565 class LoadOp(LdStSplitOp): 566 def __init__(self, data, segment, addr, disp = 0, 567 dataSize="env.dataSize", 568 addressSize="env.addressSize", 569 atCPL0=False, prefetch=False, nonSpec=nonSpec, 570 implicitStack=False): 571 super(LoadOp, self).__init__(data, segment, addr, 572 disp, dataSize, addressSize, mem_flags, 573 atCPL0, prefetch, nonSpec, implicitStack) 574 self.className = Name 575 self.mnemonic = name 576 577 microopClasses[name] = LoadOp 578 579 code = ''' 580 switch (dataSize) { 581 case 4: 582 DataLow = bits(Mem_u2qw[0], 31, 0); 583 DataHi = bits(Mem_u2qw[0], 63, 32); 584 break; 585 case 8: 586 DataLow = Mem_u2qw[0]; 587 DataHi = Mem_u2qw[1]; 588 break; 589 default: 590 panic("Unhandled data size %d in LdSplit.\\n", dataSize); 591 }''' 592 593 defineMicroLoadSplitOp('LdSplit', code, 594 '(StoreCheck << FlagShift)') 595 596 defineMicroLoadSplitOp('LdSplitl', code, 597 '(StoreCheck << FlagShift) | Request::LOCKED_RMW', 598 nonSpec=True) 599 600 def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0", 601 implicitStack=False): 602 global header_output 603 global decoder_output 604 global exec_output 605 global microopClasses 606 Name = mnemonic 607 name = mnemonic.lower() 608 609 # Build up the all register version of this micro op 610 iop = InstObjParams(name, Name, 'X86ISA::LdStOp', 611 { "code": code, 612 "complete_code": completeCode, 613 "ea_code": calculateEA, 614 "memDataSize": "dataSize" }) 615 header_output += MicroLdStOpDeclare.subst(iop) 616 decoder_output += MicroLdStOpConstructor.subst(iop) 617 exec_output += MicroStoreExecute.subst(iop) 618 exec_output += MicroStoreInitiateAcc.subst(iop) 619 exec_output += MicroStoreCompleteAcc.subst(iop) 620 621 if implicitStack: 622 # For instructions that implicitly access the stack, the address 623 # size is the same as the stack segment pointer size, not the 624 # address size if specified by the instruction prefix 625 addressSize = "env.stackSize" 626 else: 627 addressSize = "env.addressSize" 628 629 class StoreOp(LdStOp): 630 def __init__(self, data, segment, addr, disp = 0, 631 dataSize="env.dataSize", 632 addressSize=addressSize, 633 atCPL0=False, nonSpec=False, implicitStack=implicitStack): 634 super(StoreOp, self).__init__(data, segment, addr, disp, 635 dataSize, addressSize, mem_flags, atCPL0, False, 636 nonSpec, implicitStack) 637 self.className = Name 638 self.mnemonic = name 639 640 microopClasses[name] = StoreOp 641 642 defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') 643 defineMicroStoreOp('Stis', 'Mem = pick(Data, 2, dataSize);', 644 implicitStack=True) 645 defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);', 646 mem_flags="Request::LOCKED_RMW") 647 648 defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;') 649 650 defineMicroStoreOp('Stfp87', code=''' 651 switch (dataSize) 652 { 653 case 4: { 654 float single(FpData_df); 655 Mem = *(uint32_t *)&single; 656 } break; 657 case 8: 658 Mem = *(uint64_t *)&FpData_df; 659 break; 660 default: 661 panic("Unhandled data size in StFp87.\\n"); 662 } 663 ''') 664 665 defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") 666 667 def defineMicroStoreSplitOp(mnemonic, code, 668 completeCode="", mem_flags="0"): 669 global header_output 670 global decoder_output 671 global exec_output 672 global microopClasses 673 Name = mnemonic 674 name = mnemonic.lower() 675 676 iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp', 677 { "code": code, 678 "complete_code": completeCode, 679 "ea_code": calculateEA, 680 "memDataSize": "2 * dataSize" }) 681 682 header_output += MicroLdStSplitOpDeclare.subst(iop) 683 decoder_output += MicroLdStSplitOpConstructor.subst(iop) 684 exec_output += MicroStoreExecute.subst(iop) 685 exec_output += MicroStoreInitiateAcc.subst(iop) 686 exec_output += MicroStoreCompleteAcc.subst(iop) 687 688 class StoreOp(LdStSplitOp): 689 def __init__(self, data, segment, addr, disp = 0, 690 dataSize="env.dataSize", 691 addressSize="env.addressSize", 692 atCPL0=False, nonSpec=False, implicitStack=False): 693 super(StoreOp, self).__init__(data, segment, addr, disp, 694 dataSize, addressSize, mem_flags, atCPL0, False, 695 nonSpec, implicitStack) 696 self.className = Name 697 self.mnemonic = name 698 699 microopClasses[name] = StoreOp 700 701 code = ''' 702 switch (dataSize) { 703 case 4: 704 Mem_u2qw[0] = (DataHi << 32) | DataLow; 705 break; 706 case 8: 707 Mem_u2qw[0] = DataLow; 708 Mem_u2qw[1] = DataHi; 709 break; 710 default: 711 panic("Unhandled data size %d in StSplit.\\n", dataSize); 712 }''' 713 714 defineMicroStoreSplitOp('StSplit', code); 715 716 defineMicroStoreSplitOp('StSplitul', code, 717 mem_flags='Request::LOCKED_RMW') 718 719 iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', 720 { "code": "Data = merge(Data, EA, dataSize);", 721 "ea_code": "EA = " + segmentEAExpr, 722 "memDataSize": "dataSize" }) 723 header_output += MicroLeaDeclare.subst(iop) 724 decoder_output += MicroLdStOpConstructor.subst(iop) 725 exec_output += MicroLeaExecute.subst(iop) 726 727 class LeaOp(LdStOp): 728 def __init__(self, data, segment, addr, disp = 0, 729 dataSize="env.dataSize", addressSize="env.addressSize"): 730 super(LeaOp, self).__init__(data, segment, addr, disp, 731 dataSize, addressSize, "0", False, False, False, False) 732 self.className = "Lea" 733 self.mnemonic = "lea" 734 735 microopClasses["lea"] = LeaOp 736 737 738 iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp', 739 { "code": "xc->demapPage(EA, 0);", 740 "ea_code": calculateEA, 741 "memDataSize": "dataSize" }) 742 header_output += MicroLeaDeclare.subst(iop) 743 decoder_output += MicroLdStOpConstructor.subst(iop) 744 exec_output += MicroLeaExecute.subst(iop) 745 746 class TiaOp(LdStOp): 747 def __init__(self, segment, addr, disp = 0, 748 dataSize="env.dataSize", 749 addressSize="env.addressSize"): 750 super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, 751 addr, disp, dataSize, addressSize, "0", False, False, 752 False, False) 753 self.className = "Tia" 754 self.mnemonic = "tia" 755 756 microopClasses["tia"] = TiaOp 757 758 class CdaOp(LdStOp): 759 def __init__(self, segment, addr, disp = 0, 760 dataSize="env.dataSize", 761 addressSize="env.addressSize", atCPL0=False): 762 super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, 763 addr, disp, dataSize, addressSize, "Request::NO_ACCESS", 764 atCPL0, False, False, False) 765 self.className = "Cda" 766 self.mnemonic = "cda" 767 768 microopClasses["cda"] = CdaOp 769}}; 770