1 // Copyright (c) 2007-2008 The Hewlett-Packard Development Company
2 // All rights reserved.
4 // The license below extends only to copyright in the software and shall
5 // not be construed as granting a license to any other intellectual
6 // property including but not limited to intellectual property relating
7 // to a hardware implementation of the functionality of the software
8 // licensed hereunder. You may use the software subject to the license
9 // terms below provided that you ensure that this notice is replicated
10 // unmodified and in its entirety in all distributions of the software,
11 // modified or unmodified, in source code or in binary form.
13 // Copyright (c) 2008 The Regents of The University of Michigan
14 // All rights reserved.
16 // Redistribution and use in source and binary forms, with or without
17 // modification, are permitted provided that the following conditions are
18 // met: redistributions of source code must retain the above copyright
19 // notice, this list of conditions and the following disclaimer;
20 // redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution;
23 // neither the name of the copyright holders nor the names of its
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
27 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 // Authors: Gabe Black
41 //////////////////////////////////////////////////////////////////////////
43 // LdStOp Microop templates
45 //////////////////////////////////////////////////////////////////////////
49 def template MicroLeaExecute {{
50 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
51 Trace::InstRecord *traceData) const
53 Fault fault = NoFault;
59 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
71 def template MicroLeaDeclare {{
72 class %(class_name)s : public %(base_class)s
78 %(class_name)s(ExtMachInst _machInst,
79 const char * instMnem,
80 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
81 uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
82 uint64_t _disp, InstRegIndex _segment,
84 uint8_t _dataSize, uint8_t _addressSize,
85 Request::FlagsType _memFlags);
87 %(class_name)s(ExtMachInst _machInst,
88 const char * instMnem,
89 uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
90 uint64_t _disp, InstRegIndex _segment,
92 uint8_t _dataSize, uint8_t _addressSize,
93 Request::FlagsType _memFlags);
101 def template MicroLoadExecute {{
102 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
103 Trace::InstRecord *traceData) const
105 Fault fault = NoFault;
111 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
113 fault = read(xc, EA, Mem, memFlags);
115 if (fault == NoFault) {
117 } else if (memFlags & Request::PREFETCH) {
118 // For prefetches, ignore any faults/exceptions.
130 def template MicroLoadInitiateAcc {{
131 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
132 Trace::InstRecord * traceData) const
134 Fault fault = NoFault;
140 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
142 fault = read(xc, EA, Mem, memFlags);
148 def template MicroLoadCompleteAcc {{
149 Fault %(class_name)s::completeAcc(PacketPtr pkt,
150 %(CPU_exec_context)s * xc,
151 Trace::InstRecord * traceData) const
153 Fault fault = NoFault;
173 def template MicroStoreExecute {{
174 Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
175 Trace::InstRecord *traceData) const
177 Fault fault = NoFault;
183 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
189 fault = write(xc, Mem, EA, memFlags);
201 def template MicroStoreInitiateAcc {{
202 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
203 Trace::InstRecord * traceData) const
205 Fault fault = NoFault;
211 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
217 write(xc, Mem, EA, memFlags);
223 def template MicroStoreCompleteAcc {{
224 Fault %(class_name)s::completeAcc(PacketPtr pkt,
225 %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
237 //This delcares the initiateAcc function in memory operations
238 def template InitiateAccDeclare {{
239 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
242 //This declares the completeAcc function in memory operations
243 def template CompleteAccDeclare {{
244 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
247 def template MicroLdStOpDeclare {{
248 class %(class_name)s : public %(base_class)s
254 %(class_name)s(ExtMachInst _machInst,
255 const char * instMnem,
256 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
257 uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
258 uint64_t _disp, InstRegIndex _segment,
260 uint8_t _dataSize, uint8_t _addressSize,
261 Request::FlagsType _memFlags);
263 %(class_name)s(ExtMachInst _machInst,
264 const char * instMnem,
265 uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
266 uint64_t _disp, InstRegIndex _segment,
268 uint8_t _dataSize, uint8_t _addressSize,
269 Request::FlagsType _memFlags);
273 %(InitiateAccDeclare)s
275 %(CompleteAccDeclare)s
279 def template MicroLdStOpConstructor {{
281 inline void %(class_name)s::buildMe()
286 inline %(class_name)s::%(class_name)s(
287 ExtMachInst machInst, const char * instMnem,
288 uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
289 uint64_t _disp, InstRegIndex _segment,
291 uint8_t _dataSize, uint8_t _addressSize,
292 Request::FlagsType _memFlags) :
293 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
294 false, false, false, false,
295 _scale, _index, _base,
296 _disp, _segment, _data,
297 _dataSize, _addressSize, _memFlags, %(op_class)s)
302 inline %(class_name)s::%(class_name)s(
303 ExtMachInst machInst, const char * instMnem,
304 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
305 uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
306 uint64_t _disp, InstRegIndex _segment,
308 uint8_t _dataSize, uint8_t _addressSize,
309 Request::FlagsType _memFlags) :
310 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
311 isMicro, isDelayed, isFirst, isLast,
312 _scale, _index, _base,
313 _disp, _segment, _data,
314 _dataSize, _addressSize, _memFlags, %(op_class)s)
321 class LdStOp(X86Microop):
322 def __init__(self, data, segment, addr, disp,
323 dataSize, addressSize, baseFlags, atCPL0, prefetch):
325 [self.scale, self.index, self.base] = addr
327 self.segment = segment
328 self.dataSize = dataSize
329 self.addressSize = addressSize
330 self.memFlags = baseFlags
332 self.memFlags += " | (CPL0FlagBit << FlagShift)"
334 self.memFlags += " | Request::PREFETCH"
335 self.memFlags += " | (machInst.legacy.addr ? " + \
336 "(AddrSizeFlagBit << FlagShift) : 0)"
338 def getAllocator(self, *microFlags):
339 allocator = '''new %(class_name)s(machInst, macrocodeBlock
340 %(flags)s, %(scale)s, %(index)s, %(base)s,
341 %(disp)s, %(segment)s, %(data)s,
342 %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
343 "class_name" : self.className,
344 "flags" : self.microFlagsText(microFlags),
345 "scale" : self.scale, "index" : self.index,
348 "segment" : self.segment, "data" : self.data,
349 "dataSize" : self.dataSize, "addressSize" : self.addressSize,
350 "memFlags" : self.memFlags}
356 # Make these empty strings so that concatenating onto
357 # them will always work.
363 EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0);
366 def defineMicroLoadOp(mnemonic, code, mem_flags="0"):
368 global decoder_output
370 global microopClasses
372 name = mnemonic.lower()
374 # Build up the all register version of this micro op
375 iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
377 "ea_code": calculateEA})
378 header_output += MicroLdStOpDeclare.subst(iop)
379 decoder_output += MicroLdStOpConstructor.subst(iop)
380 exec_output += MicroLoadExecute.subst(iop)
381 exec_output += MicroLoadInitiateAcc.subst(iop)
382 exec_output += MicroLoadCompleteAcc.subst(iop)
384 class LoadOp(LdStOp):
385 def __init__(self, data, segment, addr, disp = 0,
386 dataSize="env.dataSize",
387 addressSize="env.addressSize",
388 atCPL0=False, prefetch=False):
389 super(LoadOp, self).__init__(data, segment, addr,
390 disp, dataSize, addressSize, mem_flags,
392 self.className = Name
395 microopClasses[name] = LoadOp
397 defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
398 defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
399 '(StoreCheck << FlagShift)')
400 defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
401 '(StoreCheck << FlagShift) | Request::LOCKED')
402 defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
404 def defineMicroStoreOp(mnemonic, code, \
405 postCode="", completeCode="", mem_flags="0"):
407 global decoder_output
409 global microopClasses
411 name = mnemonic.lower()
413 # Build up the all register version of this micro op
414 iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
416 "post_code": postCode,
417 "complete_code": completeCode,
418 "ea_code": calculateEA})
419 header_output += MicroLdStOpDeclare.subst(iop)
420 decoder_output += MicroLdStOpConstructor.subst(iop)
421 exec_output += MicroStoreExecute.subst(iop)
422 exec_output += MicroStoreInitiateAcc.subst(iop)
423 exec_output += MicroStoreCompleteAcc.subst(iop)
425 class StoreOp(LdStOp):
426 def __init__(self, data, segment, addr, disp = 0,
427 dataSize="env.dataSize",
428 addressSize="env.addressSize",
430 super(StoreOp, self).__init__(data, segment, addr,
431 disp, dataSize, addressSize, mem_flags, atCPL0, False)
432 self.className = Name
435 microopClasses[name] = StoreOp
437 defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
438 defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
439 mem_flags="Request::LOCKED")
440 defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
441 defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);',
442 'Base = merge(Base, EA - SegBase, addressSize);',
443 'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);');
444 defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
446 iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
447 {"code": "Data = merge(Data, EA, dataSize);",
449 EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
451 header_output += MicroLeaDeclare.subst(iop)
452 decoder_output += MicroLdStOpConstructor.subst(iop)
453 exec_output += MicroLeaExecute.subst(iop)
456 def __init__(self, data, segment, addr, disp = 0,
457 dataSize="env.dataSize", addressSize="env.addressSize"):
458 super(LeaOp, self).__init__(data, segment,
459 addr, disp, dataSize, addressSize, "0", False, False)
460 self.className = "Lea"
461 self.mnemonic = "lea"
463 microopClasses["lea"] = LeaOp
466 iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
467 {"code": "xc->demapPage(EA, 0);",
468 "ea_code": calculateEA})
469 header_output += MicroLeaDeclare.subst(iop)
470 decoder_output += MicroLdStOpConstructor.subst(iop)
471 exec_output += MicroLeaExecute.subst(iop)
474 def __init__(self, segment, addr, disp = 0,
475 dataSize="env.dataSize",
476 addressSize="env.addressSize"):
477 super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
478 addr, disp, dataSize, addressSize, "0", False, False)
479 self.className = "Tia"
480 self.mnemonic = "tia"
482 microopClasses["tia"] = TiaOp
485 def __init__(self, segment, addr, disp = 0,
486 dataSize="env.dataSize",
487 addressSize="env.addressSize", atCPL0=False):
488 super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
489 addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
491 self.className = "Cda"
492 self.mnemonic = "cda"
494 microopClasses["cda"] = CdaOp