Deleted Added
sdiff udiff text old ( 7480:6a854784be4f ) new ( 7620:3d8a23caa1ef )
full compact
1// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
2// All rights reserved.
3//
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.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Gabe Black
37
38//////////////////////////////////////////////////////////////////////////
39//
40// RegOp Microop templates
41//
42//////////////////////////////////////////////////////////////////////////
43
44def template MicroRegOpExecute {{
45 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
46 Trace::InstRecord *traceData) const
47 {
48 Fault fault = NoFault;
49
50 DPRINTF(X86, "The data size is %d\n", dataSize);
51 %(op_decl)s;
52 %(op_rd)s;
53
54 if(%(cond_check)s)
55 {
56 %(code)s;
57 %(flag_code)s;
58 }
59 else
60 {
61 %(else_code)s;
62 }
63
64 //Write the resulting state to the execution context
65 if(fault == NoFault)
66 {
67 %(op_wb)s;
68 }
69 return fault;
70 }
71}};
72
73def template MicroRegOpImmExecute {{
74 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
75 Trace::InstRecord *traceData) const
76 {
77 Fault fault = NoFault;
78
79 %(op_decl)s;
80 %(op_rd)s;
81
82 if(%(cond_check)s)
83 {
84 %(code)s;
85 %(flag_code)s;
86 }
87 else
88 {
89 %(else_code)s;
90 }
91
92 //Write the resulting state to the execution context
93 if(fault == NoFault)
94 {
95 %(op_wb)s;
96 }
97 return fault;
98 }
99}};
100
101def template MicroRegOpDeclare {{
102 class %(class_name)s : public %(base_class)s
103 {
104 protected:
105 void buildMe();
106
107 public:
108 %(class_name)s(ExtMachInst _machInst,
109 const char * instMnem, uint64_t setFlags,
110 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
111 uint8_t _dataSize, uint16_t _ext);
112
113 %(class_name)s(ExtMachInst _machInst,
114 const char * instMnem,
115 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
116 uint8_t _dataSize, uint16_t _ext);
117
118 %(BasicExecDeclare)s
119 };
120}};
121
122def template MicroRegOpImmDeclare {{
123
124 class %(class_name)s : public %(base_class)s
125 {
126 protected:
127 void buildMe();
128
129 public:
130 %(class_name)s(ExtMachInst _machInst,
131 const char * instMnem, uint64_t setFlags,
132 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
133 uint8_t _dataSize, uint16_t _ext);
134
135 %(class_name)s(ExtMachInst _machInst,
136 const char * instMnem,
137 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
138 uint8_t _dataSize, uint16_t _ext);
139
140 %(BasicExecDeclare)s
141 };
142}};
143
144def template MicroRegOpConstructor {{
145
146 inline void %(class_name)s::buildMe()
147 {
148 %(constructor)s;
149 }
150
151 inline %(class_name)s::%(class_name)s(
152 ExtMachInst machInst, const char * instMnem,
153 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
154 uint8_t _dataSize, uint16_t _ext) :
155 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 0,
156 _src1, _src2, _dest, _dataSize, _ext,
157 %(op_class)s)
158 {
159 buildMe();
160 }
161
162 inline %(class_name)s::%(class_name)s(
163 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
164 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
165 uint8_t _dataSize, uint16_t _ext) :
166 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
167 _src1, _src2, _dest, _dataSize, _ext,
168 %(op_class)s)
169 {
170 buildMe();
171 }
172}};
173
174def template MicroRegOpImmConstructor {{
175
176 inline void %(class_name)s::buildMe()
177 {
178 %(constructor)s;
179 }
180
181 inline %(class_name)s::%(class_name)s(
182 ExtMachInst machInst, const char * instMnem,
183 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
184 uint8_t _dataSize, uint16_t _ext) :
185 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 0,
186 _src1, _imm8, _dest, _dataSize, _ext,
187 %(op_class)s)
188 {
189 buildMe();
190 }
191
192 inline %(class_name)s::%(class_name)s(
193 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
194 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
195 uint8_t _dataSize, uint16_t _ext) :
196 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
197 _src1, _imm8, _dest, _dataSize, _ext,
198 %(op_class)s)
199 {
200 buildMe();
201 }
202}};
203
204output header {{
205 void
206 divide(uint64_t dividend, uint64_t divisor,
207 uint64_t &quotient, uint64_t &remainder);
208
209 enum SegmentSelectorCheck {
210 SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
211 SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
212 SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
213 };
214
215 enum LongModeDescriptorType {
216 LDT64 = 2,
217 AvailableTSS64 = 9,
218 BusyTSS64 = 0xb,
219 CallGate64 = 0xc,
220 IntGate64 = 0xe,
221 TrapGate64 = 0xf
222 };
223}};
224
225output decoder {{
226 void
227 divide(uint64_t dividend, uint64_t divisor,
228 uint64_t &quotient, uint64_t &remainder)
229 {
230 //Check for divide by zero.
231 if (divisor == 0)
232 panic("Divide by zero!\\n");
233 //If the divisor is bigger than the dividend, don't do anything.
234 if (divisor <= dividend) {
235 //Shift the divisor so it's msb lines up with the dividend.
236 int dividendMsb = findMsbSet(dividend);
237 int divisorMsb = findMsbSet(divisor);
238 int shift = dividendMsb - divisorMsb;
239 divisor <<= shift;
240 //Compute what we'll add to the quotient if the divisor isn't
241 //now larger than the dividend.
242 uint64_t quotientBit = 1;
243 quotientBit <<= shift;
244 //If we need to step back a bit (no pun intended) because the
245 //divisor got too to large, do that here. This is the "or two"
246 //part of one or two bit division.
247 if (divisor > dividend) {
248 quotientBit >>= 1;
249 divisor >>= 1;
250 }
251 //Decrement the remainder and increment the quotient.
252 quotient += quotientBit;
253 remainder -= divisor;
254 }
255 }
256}};
257
258let {{
259 # Make these empty strings so that concatenating onto
260 # them will always work.
261 header_output = ""
262 decoder_output = ""
263 exec_output = ""
264
265 immTemplates = (
266 MicroRegOpImmDeclare,
267 MicroRegOpImmConstructor,
268 MicroRegOpImmExecute)
269
270 regTemplates = (
271 MicroRegOpDeclare,
272 MicroRegOpConstructor,
273 MicroRegOpExecute)
274
275 class RegOpMeta(type):
276 def buildCppClasses(self, name, Name, suffix, \
277 code, flag_code, cond_check, else_code):
278
279 # Globals to stick the output in
280 global header_output
281 global decoder_output
282 global exec_output
283
284 # Stick all the code together so it can be searched at once
285 allCode = "|".join((code, flag_code, cond_check, else_code))
286
287 # If op2 is used anywhere, make register and immediate versions
288 # of this code.
289 matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
290 match = matcher.search(allCode)
291 if match:
292 typeQual = ""
293 if match.group("typeQual"):
294 typeQual = match.group("typeQual")
295 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
296 self.buildCppClasses(name, Name, suffix,
297 matcher.sub(src2_name, code),
298 matcher.sub(src2_name, flag_code),
299 matcher.sub(src2_name, cond_check),
300 matcher.sub(src2_name, else_code))
301 imm_name = "%simm8" % match.group("prefix")
302 self.buildCppClasses(name + "i", Name, suffix + "Imm",
303 matcher.sub(imm_name, code),
304 matcher.sub(imm_name, flag_code),
305 matcher.sub(imm_name, cond_check),
306 matcher.sub(imm_name, else_code))
307 return
308
309 # If there's something optional to do with flags, generate
310 # a version without it and fix up this version to use it.
311 if flag_code != "" or cond_check != "true":
312 self.buildCppClasses(name, Name, suffix,
313 code, "", "true", else_code)
314 suffix = "Flags" + suffix
315
316 # If psrc1 or psrc2 is used, we need to actually insert code to
317 # compute it.
318 matcher = re.compile("(?<!\w)psrc1(?!\w)")
319 if matcher.search(allCode):
320 code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code
321 matcher = re.compile("(?<!\w)psrc2(?!\w)")
322 if matcher.search(allCode):
323 code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code
324 # Also make available versions which do sign extension
325 matcher = re.compile("(?<!\w)spsrc1(?!\w)")
326 if matcher.search(allCode):
327 code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code
328 matcher = re.compile("(?<!\w)spsrc2(?!\w)")
329 if matcher.search(allCode):
330 code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code
331 matcher = re.compile("(?<!\w)simm8(?!\w)")
332 if matcher.search(allCode):
333 code = "int8_t simm8 = imm8;" + code
334
335 base = "X86ISA::RegOp"
336
337 # If imm8 shows up in the code, use the immediate templates, if
338 # not, hopefully the register ones will be correct.
339 templates = regTemplates
340 matcher = re.compile("(?<!\w)s?imm8(?!\w)")
341 if matcher.search(allCode):
342 base += "Imm"
343 templates = immTemplates
344
345 # Get everything ready for the substitution
346 iop = InstObjParams(name, Name + suffix, base,
347 {"code" : code,
348 "flag_code" : flag_code,
349 "cond_check" : cond_check,
350 "else_code" : else_code})
351
352 # Generate the actual code (finally!)
353 header_output += templates[0].subst(iop)
354 decoder_output += templates[1].subst(iop)
355 exec_output += templates[2].subst(iop)
356
357
358 def __new__(mcls, Name, bases, dict):
359 abstract = False
360 name = Name.lower()
361 if "abstract" in dict:
362 abstract = dict['abstract']
363 del dict['abstract']
364
365 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
366 if not abstract:
367 cls.className = Name
368 cls.base_mnemonic = name
369 code = cls.code
370 flag_code = cls.flag_code
371 cond_check = cls.cond_check
372 else_code = cls.else_code
373
374 # Set up the C++ classes
375 mcls.buildCppClasses(cls, name, Name, "",
376 code, flag_code, cond_check, else_code)
377
378 # Hook into the microassembler dict
379 global microopClasses
380 microopClasses[name] = cls
381
382 allCode = "|".join((code, flag_code, cond_check, else_code))
383
384 # If op2 is used anywhere, make register and immediate versions
385 # of this code.
386 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
387 if matcher.search(allCode):
388 microopClasses[name + 'i'] = cls
389 return cls
390
391
392 class RegOp(X86Microop):
393 __metaclass__ = RegOpMeta
394 # This class itself doesn't act as a microop
395 abstract = True
396
397 # Default template parameter values
398 flag_code = ""
399 cond_check = "true"
400 else_code = ";"
401
402 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
403 self.dest = dest
404 self.src1 = src1
405 self.op2 = op2
406 self.flags = flags
407 self.dataSize = dataSize
408 if flags is None:
409 self.ext = 0
410 else:
411 if not isinstance(flags, (list, tuple)):
412 raise Exception, "flags must be a list or tuple of flags"
413 self.ext = " | ".join(flags)
414 self.className += "Flags"
415
416 def getAllocator(self, microFlags):
417 className = self.className
418 if self.mnemonic == self.base_mnemonic + 'i':
419 className += "Imm"
420 allocator = '''new %(class_name)s(machInst, macrocodeBlock,
421 %(flags)s, %(src1)s, %(op2)s, %(dest)s,
422 %(dataSize)s, %(ext)s)''' % {
423 "class_name" : className,
424 "flags" : self.microFlagsText(microFlags),
425 "src1" : self.src1, "op2" : self.op2,
426 "dest" : self.dest,
427 "dataSize" : self.dataSize,
428 "ext" : self.ext}
429 return allocator
430
431 class LogicRegOp(RegOp):
432 abstract = True
433 flag_code = '''
434 //Don't have genFlags handle the OF or CF bits
435 uint64_t mask = CFBit | ECFBit | OFBit;
436 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
437 //If a logic microop wants to set these, it wants to set them to 0.
438 ccFlagBits &= ~(CFBit & ext);
439 ccFlagBits &= ~(ECFBit & ext);
440 ccFlagBits &= ~(OFBit & ext);
441 '''
442
443 class FlagRegOp(RegOp):
444 abstract = True
445 flag_code = \
446 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
447
448 class SubRegOp(RegOp):
449 abstract = True
450 flag_code = \
451 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
452
453 class CondRegOp(RegOp):
454 abstract = True
455 cond_check = "checkCondition(ccFlagBits, ext)"
456
457 class RdRegOp(RegOp):
458 abstract = True
459 def __init__(self, dest, src1=None, dataSize="env.dataSize"):
460 if not src1:
461 src1 = dest
462 super(RdRegOp, self).__init__(dest, src1, \
463 "InstRegIndex(NUM_INTREGS)", None, dataSize)
464
465 class WrRegOp(RegOp):
466 abstract = True
467 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
468 super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
469 src1, src2, flags, dataSize)
470
471 class Add(FlagRegOp):
472 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
473
474 class Or(LogicRegOp):
475 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
476
477 class Adc(FlagRegOp):
478 code = '''
479 CCFlagBits flags = ccFlagBits;
480 DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize);
481 '''
482
483 class Sbb(SubRegOp):
484 code = '''
485 CCFlagBits flags = ccFlagBits;
486 DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize);
487 '''
488
489 class And(LogicRegOp):
490 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
491
492 class Sub(SubRegOp):
493 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
494
495 class Xor(LogicRegOp):
496 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
497
498 class Mul1s(WrRegOp):
499 code = '''
500 ProdLow = psrc1 * op2;
501 int halfSize = (dataSize * 8) / 2;
502 uint64_t shifter = (ULL(1) << halfSize);
503 uint64_t hiResult;
504 uint64_t psrc1_h = psrc1 / shifter;
505 uint64_t psrc1_l = psrc1 & mask(halfSize);
506 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
507 uint64_t psrc2_l = op2 & mask(halfSize);
508 hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
509 ((psrc1_l * psrc2_l) / shifter)) /shifter) +
510 psrc1_h * psrc2_h;
511 if (bits(psrc1, dataSize * 8 - 1))
512 hiResult -= op2;
513 if (bits(op2, dataSize * 8 - 1))
514 hiResult -= psrc1;
515 ProdHi = hiResult;
516 '''
517 flag_code = '''
518 if ((-ProdHi & mask(dataSize * 8)) !=
519 bits(ProdLow, dataSize * 8 - 1)) {
520 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
521 } else {
522 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
523 }
524 '''
525
526 class Mul1u(WrRegOp):
527 code = '''
528 ProdLow = psrc1 * op2;
529 int halfSize = (dataSize * 8) / 2;
530 uint64_t shifter = (ULL(1) << halfSize);
531 uint64_t psrc1_h = psrc1 / shifter;
532 uint64_t psrc1_l = psrc1 & mask(halfSize);
533 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
534 uint64_t psrc2_l = op2 & mask(halfSize);
535 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
536 ((psrc1_l * psrc2_l) / shifter)) / shifter) +
537 psrc1_h * psrc2_h;
538 '''
539 flag_code = '''
540 if (ProdHi) {
541 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
542 } else {
543 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
544 }
545 '''
546
547 class Mulel(RdRegOp):
548 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
549
550 class Muleh(RdRegOp):
551 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
552 if not src1:
553 src1 = dest
554 super(RdRegOp, self).__init__(dest, src1, \
555 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
556 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
557
558 # One or two bit divide
559 class Div1(WrRegOp):
560 code = '''
561 //These are temporaries so that modifying them later won't make
562 //the ISA parser think they're also sources.
563 uint64_t quotient = 0;
564 uint64_t remainder = psrc1;
565 //Similarly, this is a temporary so changing it doesn't make it
566 //a source.
567 uint64_t divisor = op2;
568 //This is a temporary just for consistency and clarity.
569 uint64_t dividend = remainder;
570 //Do the division.
571 divide(dividend, divisor, quotient, remainder);
572 //Record the final results.
573 Remainder = remainder;
574 Quotient = quotient;
575 Divisor = divisor;
576 '''
577
578 # Step divide
579 class Div2(RegOp):
580 code = '''
581 uint64_t dividend = Remainder;
582 uint64_t divisor = Divisor;
583 uint64_t quotient = Quotient;
584 uint64_t remainder = dividend;
585 int remaining = op2;
586 //If we overshot, do nothing. This lets us unrool division loops a
587 //little.
588 if (remaining) {
589 if (divisor & (ULL(1) << 63)) {
590 while (remaining && !(dividend & (ULL(1) << 63))) {
591 dividend = (dividend << 1) |
592 bits(SrcReg1, remaining - 1);
593 quotient <<= 1;
594 remaining--;
595 }
596 if (dividend & (ULL(1) << 63)) {
597 bool highBit = false;
598 if (dividend < divisor && remaining) {
599 highBit = true;
600 dividend = (dividend << 1) |
601 bits(SrcReg1, remaining - 1);
602 quotient <<= 1;
603 remaining--;
604 }
605 if (highBit || divisor <= dividend) {
606 quotient++;
607 dividend -= divisor;
608 }
609 }
610 remainder = dividend;
611 } else {
612 //Shift in bits from the low order portion of the dividend
613 while (dividend < divisor && remaining) {
614 dividend = (dividend << 1) |
615 bits(SrcReg1, remaining - 1);
616 quotient <<= 1;
617 remaining--;
618 }
619 remainder = dividend;
620 //Do the division.
621 divide(dividend, divisor, quotient, remainder);
622 }
623 }
624 //Keep track of how many bits there are still to pull in.
625 DestReg = merge(DestReg, remaining, dataSize);
626 //Record the final results
627 Remainder = remainder;
628 Quotient = quotient;
629 '''
630 flag_code = '''
631 if (remaining == 0)
632 ccFlagBits = ccFlagBits | (ext & EZFBit);
633 else
634 ccFlagBits = ccFlagBits & ~(ext & EZFBit);
635 '''
636
637 class Divq(RdRegOp):
638 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
639
640 class Divr(RdRegOp):
641 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
642
643 class Mov(CondRegOp):
644 code = 'DestReg = merge(SrcReg1, op2, dataSize)'
645 else_code = 'DestReg = DestReg;'
646
647 # Shift instructions
648
649 class Sll(RegOp):
650 code = '''
651 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
652 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
653 '''
654 flag_code = '''
655 // If the shift amount is zero, no flags should be modified.
656 if (shiftAmt) {
657 //Zero out any flags we might modify. This way we only have to
658 //worry about setting them.
659 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
660 int CFBits = 0;
661 //Figure out if we -would- set the CF bits if requested.
662 if (shiftAmt <= dataSize * 8 &&
663 bits(SrcReg1, dataSize * 8 - shiftAmt)) {
664 CFBits = 1;
665 }
666 //If some combination of the CF bits need to be set, set them.
667 if ((ext & (CFBit | ECFBit)) && CFBits)
668 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
669 //Figure out what the OF bit should be.
670 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
671 ccFlagBits = ccFlagBits | OFBit;
672 //Use the regular mechanisms to calculate the other flags.
673 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
674 DestReg, psrc1, op2);
675 }
676 '''
677
678 class Srl(RegOp):
679 code = '''
680 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
681 // Because what happens to the bits shift -in- on a right shift
682 // is not defined in the C/C++ standard, we have to mask them out
683 // to be sure they're zero.
684 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
685 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
686 '''
687 flag_code = '''
688 // If the shift amount is zero, no flags should be modified.
689 if (shiftAmt) {
690 //Zero out any flags we might modify. This way we only have to
691 //worry about setting them.
692 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
693 //If some combination of the CF bits need to be set, set them.
694 if ((ext & (CFBit | ECFBit)) &&
695 shiftAmt <= dataSize * 8 &&
696 bits(SrcReg1, shiftAmt - 1)) {
697 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
698 }
699 //Figure out what the OF bit should be.
700 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
701 ccFlagBits = ccFlagBits | OFBit;
702 //Use the regular mechanisms to calculate the other flags.
703 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
704 DestReg, psrc1, op2);
705 }
706 '''
707
708 class Sra(RegOp):
709 code = '''
710 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
711 // Because what happens to the bits shift -in- on a right shift
712 // is not defined in the C/C++ standard, we have to sign extend
713 // them manually to be sure.
714 uint64_t arithMask = (shiftAmt == 0) ? 0 :
715 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
716 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
717 '''
718 flag_code = '''
719 // If the shift amount is zero, no flags should be modified.
720 if (shiftAmt) {
721 //Zero out any flags we might modify. This way we only have to
722 //worry about setting them.
723 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
724 //If some combination of the CF bits need to be set, set them.
725 uint8_t effectiveShift =
726 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
727 if ((ext & (CFBit | ECFBit)) &&
728 bits(SrcReg1, effectiveShift - 1)) {
729 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
730 }
731 //Use the regular mechanisms to calculate the other flags.
732 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
733 DestReg, psrc1, op2);
734 }
735 '''
736
737 class Ror(RegOp):
738 code = '''
739 uint8_t shiftAmt =
740 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
741 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
742 if(realShiftAmt)
743 {
744 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
745 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
746 DestReg = merge(DestReg, top | bottom, dataSize);
747 }
748 else
749 DestReg = merge(DestReg, DestReg, dataSize);
750 '''
751 flag_code = '''
752 // If the shift amount is zero, no flags should be modified.
753 if (shiftAmt) {
754 //Zero out any flags we might modify. This way we only have to
755 //worry about setting them.
756 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
757 //Find the most and second most significant bits of the result.
758 int msb = bits(DestReg, dataSize * 8 - 1);
759 int smsb = bits(DestReg, dataSize * 8 - 2);
760 //If some combination of the CF bits need to be set, set them.
761 if ((ext & (CFBit | ECFBit)) && msb)
762 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
763 //Figure out what the OF bit should be.
764 if ((ext & OFBit) && (msb ^ smsb))
765 ccFlagBits = ccFlagBits | OFBit;
766 //Use the regular mechanisms to calculate the other flags.
767 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
768 DestReg, psrc1, op2);
769 }
770 '''
771
772 class Rcr(RegOp):
773 code = '''
774 uint8_t shiftAmt =
775 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
776 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
777 if(realShiftAmt)
778 {
779 CCFlagBits flags = ccFlagBits;
780 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
781 if (realShiftAmt > 1)
782 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
783 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
784 DestReg = merge(DestReg, top | bottom, dataSize);
785 }
786 else
787 DestReg = merge(DestReg, DestReg, dataSize);
788 '''
789 flag_code = '''
790 // If the shift amount is zero, no flags should be modified.
791 if (shiftAmt) {
792 int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
793 //Zero out any flags we might modify. This way we only have to
794 //worry about setting them.
795 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
796 //Figure out what the OF bit should be.
797 if ((ext & OFBit) && (origCFBit ^
798 bits(SrcReg1, dataSize * 8 - 1))) {
799 ccFlagBits = ccFlagBits | OFBit;
800 }
801 //If some combination of the CF bits need to be set, set them.
802 if ((ext & (CFBit | ECFBit)) &&
803 (realShiftAmt == 0) ? origCFBit :
804 bits(SrcReg1, realShiftAmt - 1)) {
805 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
806 }
807 //Use the regular mechanisms to calculate the other flags.
808 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
809 DestReg, psrc1, op2);
810 }
811 '''
812
813 class Rol(RegOp):
814 code = '''
815 uint8_t shiftAmt =
816 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
817 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
818 if(realShiftAmt)
819 {
820 uint64_t top = psrc1 << realShiftAmt;
821 uint64_t bottom =
822 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
823 DestReg = merge(DestReg, top | bottom, dataSize);
824 }
825 else
826 DestReg = merge(DestReg, DestReg, dataSize);
827 '''
828 flag_code = '''
829 // If the shift amount is zero, no flags should be modified.
830 if (shiftAmt) {
831 //Zero out any flags we might modify. This way we only have to
832 //worry about setting them.
833 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
834 //The CF bits, if set, would be set to the lsb of the result.
835 int lsb = DestReg & 0x1;
836 int msb = bits(DestReg, dataSize * 8 - 1);
837 //If some combination of the CF bits need to be set, set them.
838 if ((ext & (CFBit | ECFBit)) && lsb)
839 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
840 //Figure out what the OF bit should be.
841 if ((ext & OFBit) && (msb ^ lsb))
842 ccFlagBits = ccFlagBits | OFBit;
843 //Use the regular mechanisms to calculate the other flags.
844 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
845 DestReg, psrc1, op2);
846 }
847 '''
848
849 class Rcl(RegOp):
850 code = '''
851 uint8_t shiftAmt =
852 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
853 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
854 if(realShiftAmt)
855 {
856 CCFlagBits flags = ccFlagBits;
857 uint64_t top = psrc1 << realShiftAmt;
858 uint64_t bottom = flags.cf << (realShiftAmt - 1);
859 if(shiftAmt > 1)
860 bottom |=
861 bits(psrc1, dataSize * 8 - 1,
862 dataSize * 8 - realShiftAmt + 1);
863 DestReg = merge(DestReg, top | bottom, dataSize);
864 }
865 else
866 DestReg = merge(DestReg, DestReg, dataSize);
867 '''
868 flag_code = '''
869 // If the shift amount is zero, no flags should be modified.
870 if (shiftAmt) {
871 int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
872 //Zero out any flags we might modify. This way we only have to
873 //worry about setting them.
874 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
875 int msb = bits(DestReg, dataSize * 8 - 1);
876 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
877 //If some combination of the CF bits need to be set, set them.
878 if ((ext & (CFBit | ECFBit)) &&
879 (realShiftAmt == 0) ? origCFBit : CFBits)
880 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
881 //Figure out what the OF bit should be.
882 if ((ext & OFBit) && (msb ^ CFBits))
883 ccFlagBits = ccFlagBits | OFBit;
884 //Use the regular mechanisms to calculate the other flags.
885 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
886 DestReg, psrc1, op2);
887 }
888 '''
889
890 class Sld(RegOp):
891 code = '''
892 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
893 uint8_t dataBits = dataSize * 8;
894 uint8_t realShiftAmt = shiftAmt % (2 * dataBits);
895 uint64_t result;
896 if (realShiftAmt == 0) {
897 result = psrc1;
898 } else if (realShiftAmt < dataBits) {
899 result = (psrc1 << realShiftAmt) |
900 (DoubleBits >> (dataBits - realShiftAmt));
901 } else {
902 result = (DoubleBits << (realShiftAmt - dataBits)) |
903 (psrc1 >> (2 * dataBits - realShiftAmt));
904 }
905 DestReg = merge(DestReg, result, dataSize);
906 '''
907 flag_code = '''
908 // If the shift amount is zero, no flags should be modified.
909 if (shiftAmt) {
910 //Zero out any flags we might modify. This way we only have to
911 //worry about setting them.
912 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
913 int CFBits = 0;
914 //Figure out if we -would- set the CF bits if requested.
915 if ((realShiftAmt == 0 &&
916 bits(DoubleBits, 0)) ||
917 (realShiftAmt <= dataBits &&
918 bits(SrcReg1, dataBits - realShiftAmt)) ||
919 (realShiftAmt > dataBits &&
920 bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
921 CFBits = 1;
922 }
923 //If some combination of the CF bits need to be set, set them.
924 if ((ext & (CFBit | ECFBit)) && CFBits)
925 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
926 //Figure out what the OF bit should be.
927 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
928 bits(result, dataBits - 1)))
929 ccFlagBits = ccFlagBits | OFBit;
930 //Use the regular mechanisms to calculate the other flags.
931 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
932 DestReg, psrc1, op2);
933 }
934 '''
935
936 class Srd(RegOp):
937 code = '''
938 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
939 uint8_t dataBits = dataSize * 8;
940 uint8_t realShiftAmt = shiftAmt % (2 * dataBits);
941 uint64_t result;
942 if (realShiftAmt == 0) {
943 result = psrc1;
944 } else if (realShiftAmt < dataBits) {
945 // Because what happens to the bits shift -in- on a right
946 // shift is not defined in the C/C++ standard, we have to
947 // mask them out to be sure they're zero.
948 uint64_t logicalMask = mask(dataBits - realShiftAmt);
949 result = ((psrc1 >> realShiftAmt) & logicalMask) |
950 (DoubleBits << (dataBits - realShiftAmt));
951 } else {
952 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
953 result = ((DoubleBits >> (realShiftAmt - dataBits)) &
954 logicalMask) |
955 (psrc1 << (2 * dataBits - realShiftAmt));
956 }
957 DestReg = merge(DestReg, result, dataSize);
958 '''
959 flag_code = '''
960 // If the shift amount is zero, no flags should be modified.
961 if (shiftAmt) {
962 //Zero out any flags we might modify. This way we only have to
963 //worry about setting them.
964 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
965 int CFBits = 0;
966 //If some combination of the CF bits need to be set, set them.
967 if ((realShiftAmt == 0 &&
968 bits(DoubleBits, dataBits - 1)) ||
969 (realShiftAmt <= dataBits &&
970 bits(SrcReg1, realShiftAmt - 1)) ||
971 (realShiftAmt > dataBits &&
972 bits(DoubleBits, realShiftAmt - dataBits - 1))) {
973 CFBits = 1;
974 }
975 //If some combination of the CF bits need to be set, set them.
976 if ((ext & (CFBit | ECFBit)) && CFBits)
977 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
978 //Figure out what the OF bit should be.
979 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
980 bits(result, dataBits - 1)))
981 ccFlagBits = ccFlagBits | OFBit;
982 //Use the regular mechanisms to calculate the other flags.
983 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
984 DestReg, psrc1, op2);
985 }
986 '''
987
988 class Mdb(WrRegOp):
989 code = 'DoubleBits = psrc1 ^ op2;'
990
991 class Wrip(WrRegOp, CondRegOp):
992 code = 'RIP = psrc1 + sop2 + CSBase'
993 else_code="RIP = RIP;"
994
995 class Wruflags(WrRegOp):
996 code = 'ccFlagBits = psrc1 ^ op2'
997
998 class Wrflags(WrRegOp):
999 code = '''
1000 MiscReg newFlags = psrc1 ^ op2;
1001 MiscReg userFlagMask = 0xDD5;
1002 // Get only the user flags
1003 ccFlagBits = newFlags & userFlagMask;
1004 // Get everything else
1005 nccFlagBits = newFlags & ~userFlagMask;
1006 '''
1007
1008 class Rdip(RdRegOp):
1009 code = 'DestReg = RIP - CSBase'
1010
1011 class Ruflags(RdRegOp):
1012 code = 'DestReg = ccFlagBits'
1013
1014 class Rflags(RdRegOp):
1015 code = 'DestReg = ccFlagBits | nccFlagBits'
1016
1017 class Ruflag(RegOp):
1018 code = '''
1019 int flag = bits(ccFlagBits, imm8);
1020 DestReg = merge(DestReg, flag, dataSize);
1021 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1022 (ccFlagBits & ~EZFBit);
1023 '''
1024 def __init__(self, dest, imm, flags=None, \
1025 dataSize="env.dataSize"):
1026 super(Ruflag, self).__init__(dest, \
1027 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1028
1029 class Rflag(RegOp):
1030 code = '''
1031 MiscReg flagMask = 0x3F7FDD5;
1032 MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
1033 int flag = bits(flags, imm8);
1034 DestReg = merge(DestReg, flag, dataSize);
1035 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1036 (ccFlagBits & ~EZFBit);
1037 '''
1038 def __init__(self, dest, imm, flags=None, \
1039 dataSize="env.dataSize"):
1040 super(Rflag, self).__init__(dest, \
1041 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1042
1043 class Sext(RegOp):
1044 code = '''
1045 IntReg val = psrc1;
1046 // Mask the bit position so that it wraps.
1047 int bitPos = op2 & (dataSize * 8 - 1);
1048 int sign_bit = bits(val, bitPos, bitPos);
1049 uint64_t maskVal = mask(bitPos+1);
1050 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1051 DestReg = merge(DestReg, val, dataSize);
1052 '''
1053 flag_code = '''
1054 if (!sign_bit)
1055 ccFlagBits = ccFlagBits &
1056 ~(ext & (CFBit | ECFBit | ZFBit | EZFBit));
1057 else
1058 ccFlagBits = ccFlagBits |
1059 (ext & (CFBit | ECFBit | ZFBit | EZFBit));
1060 '''
1061
1062 class Zext(RegOp):
1063 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1064
1065 class Rddr(RegOp):
1066 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1067 super(Rddr, self).__init__(dest, \
1068 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1069 code = '''
1070 CR4 cr4 = CR4Op;
1071 DR7 dr7 = DR7Op;
1072 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1073 fault = new InvalidOpcode();
1074 } else if (dr7.gd) {
1075 fault = new DebugException();
1076 } else {
1077 DestReg = merge(DestReg, DebugSrc1, dataSize);
1078 }
1079 '''
1080
1081 class Wrdr(RegOp):
1082 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1083 super(Wrdr, self).__init__(dest, \
1084 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1085 code = '''
1086 CR4 cr4 = CR4Op;
1087 DR7 dr7 = DR7Op;
1088 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1089 fault = new InvalidOpcode();
1090 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1091 machInst.mode.mode == LongMode) {
1092 fault = new GeneralProtection(0);
1093 } else if (dr7.gd) {
1094 fault = new DebugException();
1095 } else {
1096 DebugDest = psrc1;
1097 }
1098 '''
1099
1100 class Rdcr(RegOp):
1101 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1102 super(Rdcr, self).__init__(dest, \
1103 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1104 code = '''
1105 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1106 fault = new InvalidOpcode();
1107 } else {
1108 DestReg = merge(DestReg, ControlSrc1, dataSize);
1109 }
1110 '''
1111
1112 class Wrcr(RegOp):
1113 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1114 super(Wrcr, self).__init__(dest, \
1115 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1116 code = '''
1117 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1118 fault = new InvalidOpcode();
1119 } else {
1120 // There are *s in the line below so it doesn't confuse the
1121 // parser. They may be unnecessary.
1122 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1123 MiscReg newVal = psrc1;
1124
1125 // Check for any modifications that would cause a fault.
1126 switch(dest) {
1127 case 0:
1128 {
1129 Efer efer = EferOp;
1130 CR0 cr0 = newVal;
1131 CR4 oldCr4 = CR4Op;
1132 if (bits(newVal, 63, 32) ||
1133 (!cr0.pe && cr0.pg) ||
1134 (!cr0.cd && cr0.nw) ||
1135 (cr0.pg && efer.lme && !oldCr4.pae))
1136 fault = new GeneralProtection(0);
1137 }
1138 break;
1139 case 2:
1140 break;
1141 case 3:
1142 break;
1143 case 4:
1144 {
1145 CR4 cr4 = newVal;
1146 // PAE can't be disabled in long mode.
1147 if (bits(newVal, 63, 11) ||
1148 (machInst.mode.mode == LongMode && !cr4.pae))
1149 fault = new GeneralProtection(0);
1150 }
1151 break;
1152 case 8:
1153 {
1154 if (bits(newVal, 63, 4))
1155 fault = new GeneralProtection(0);
1156 }
1157 default:
1158 panic("Unrecognized control register %d.\\n", dest);
1159 }
1160 ControlDest = newVal;
1161 }
1162 '''
1163
1164 # Microops for manipulating segmentation registers
1165 class SegOp(CondRegOp):
1166 abstract = True
1167 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1168 super(SegOp, self).__init__(dest, \
1169 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1170
1171 class Wrbase(SegOp):
1172 code = '''
1173 SegBaseDest = psrc1;
1174 '''
1175
1176 class Wrlimit(SegOp):
1177 code = '''
1178 SegLimitDest = psrc1;
1179 '''
1180
1181 class Wrsel(SegOp):
1182 code = '''
1183 SegSelDest = psrc1;
1184 '''
1185
1186 class WrAttr(SegOp):
1187 code = '''
1188 SegAttrDest = psrc1;
1189 '''
1190
1191 class Rdbase(SegOp):
1192 code = '''
1193 DestReg = merge(DestReg, SegBaseSrc1, dataSize);
1194 '''
1195
1196 class Rdlimit(SegOp):
1197 code = '''
1198 DestReg = merge(DestReg, SegLimitSrc1, dataSize);
1199 '''
1200
1201 class RdAttr(SegOp):
1202 code = '''
1203 DestReg = merge(DestReg, SegAttrSrc1, dataSize);
1204 '''
1205
1206 class Rdsel(SegOp):
1207 code = '''
1208 DestReg = merge(DestReg, SegSelSrc1, dataSize);
1209 '''
1210
1211 class Rdval(RegOp):
1212 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1213 super(Rdval, self).__init__(dest, src1, \
1214 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1215 code = '''
1216 DestReg = MiscRegSrc1;
1217 '''
1218
1219 class Wrval(RegOp):
1220 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1221 super(Wrval, self).__init__(dest, src1, \
1222 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1223 code = '''
1224 MiscRegDest = SrcReg1;
1225 '''
1226
1227 class Chks(RegOp):
1228 def __init__(self, dest, src1, src2=0,
1229 flags=None, dataSize="env.dataSize"):
1230 super(Chks, self).__init__(dest,
1231 src1, src2, flags, dataSize)
1232 code = '''
1233 // The selector is in source 1 and can be at most 16 bits.
1234 SegSelector selector = DestReg;
1235 SegDescriptor desc = SrcReg1;
1236 HandyM5Reg m5reg = M5Reg;
1237
1238 switch (imm8)
1239 {
1240 case SegNoCheck:
1241 break;
1242 case SegCSCheck:
1243 // Make sure it's the right type
1244 if (desc.s == 0 || desc.type.codeOrData != 1) {
1245 fault = new GeneralProtection(0);
1246 } else if (m5reg.cpl != desc.dpl) {
1247 fault = new GeneralProtection(0);
1248 }
1249 break;
1250 case SegCallGateCheck:
1251 panic("CS checks for far calls/jumps through call gates"
1252 "not implemented.\\n");
1253 break;
1254 case SegSoftIntGateCheck:
1255 // Check permissions.
1256 if (desc.dpl < m5reg.cpl) {
1257 fault = new GeneralProtection(selector);
1258 break;
1259 }
1260 // Fall through on purpose
1261 case SegIntGateCheck:
1262 // Make sure the gate's the right type.
1263 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1264 ((desc.type & 0x6) != 0x6)) {
1265 fault = new GeneralProtection(0);
1266 }
1267 break;
1268 case SegSSCheck:
1269 if (selector.si || selector.ti) {
1270 if (!desc.p) {
1271 fault = new StackFault(selector);
1272 }
1273 } else {
1274 if ((m5reg.submode != SixtyFourBitMode ||
1275 m5reg.cpl == 3) ||
1276 !(desc.s == 1 &&
1277 desc.type.codeOrData == 0 && desc.type.w) ||
1278 (desc.dpl != m5reg.cpl) ||
1279 (selector.rpl != m5reg.cpl)) {
1280 fault = new GeneralProtection(selector);
1281 }
1282 }
1283 break;
1284 case SegIretCheck:
1285 {
1286 if ((!selector.si && !selector.ti) ||
1287 (selector.rpl < m5reg.cpl) ||
1288 !(desc.s == 1 && desc.type.codeOrData == 1) ||
1289 (!desc.type.c && desc.dpl != selector.rpl) ||
1290 (desc.type.c && desc.dpl > selector.rpl)) {
1291 fault = new GeneralProtection(selector);
1292 } else if (!desc.p) {
1293 fault = new SegmentNotPresent(selector);
1294 }
1295 break;
1296 }
1297 case SegIntCSCheck:
1298 if (m5reg.mode == LongMode) {
1299 if (desc.l != 1 || desc.d != 0) {
1300 fault = new GeneralProtection(selector);
1301 }
1302 } else {
1303 panic("Interrupt CS checks not implemented "
1304 "in legacy mode.\\n");
1305 }
1306 break;
1307 case SegTRCheck:
1308 if (!selector.si || selector.ti) {
1309 fault = new GeneralProtection(selector);
1310 }
1311 break;
1312 case SegTSSCheck:
1313 if (!desc.p) {
1314 fault = new SegmentNotPresent(selector);
1315 } else if (!(desc.type == 0x9 ||
1316 (desc.type == 1 &&
1317 m5reg.mode != LongMode))) {
1318 fault = new GeneralProtection(selector);
1319 }
1320 break;
1321 case SegInGDTCheck:
1322 if (selector.ti) {
1323 fault = new GeneralProtection(selector);
1324 }
1325 break;
1326 case SegLDTCheck:
1327 if (!desc.p) {
1328 fault = new SegmentNotPresent(selector);
1329 } else if (desc.type != 0x2) {
1330 fault = new GeneralProtection(selector);
1331 }
1332 break;
1333 default:
1334 panic("Undefined segment check type.\\n");
1335 }
1336 '''
1337 flag_code = '''
1338 // Check for a NULL selector and set ZF,EZF appropriately.
1339 ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
1340 if (!selector.si && !selector.ti)
1341 ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
1342 '''
1343
1344 class Wrdh(RegOp):
1345 code = '''
1346 SegDescriptor desc = SrcReg1;
1347
1348 uint64_t target = bits(SrcReg2, 31, 0) << 32;
1349 switch(desc.type) {
1350 case LDT64:
1351 case AvailableTSS64:
1352 case BusyTSS64:
1353 replaceBits(target, 23, 0, desc.baseLow);
1354 replaceBits(target, 31, 24, desc.baseHigh);
1355 break;
1356 case CallGate64:
1357 case IntGate64:
1358 case TrapGate64:
1359 replaceBits(target, 15, 0, bits(desc, 15, 0));
1360 replaceBits(target, 31, 16, bits(desc, 63, 48));
1361 break;
1362 default:
1363 panic("Wrdh used with wrong descriptor type!\\n");
1364 }
1365 DestReg = target;
1366 '''
1367
1368 class Wrtsc(WrRegOp):
1369 code = '''
1370 TscOp = psrc1;
1371 '''
1372
1373 class Rdtsc(RdRegOp):
1374 code = '''
1375 DestReg = TscOp;
1376 '''
1377
1378 class Rdm5reg(RdRegOp):
1379 code = '''
1380 DestReg = M5Reg;
1381 '''
1382
1383 class Wrdl(RegOp):
1384 code = '''
1385 SegDescriptor desc = SrcReg1;
1386 SegSelector selector = SrcReg2;
1387 if (selector.si || selector.ti) {
1388 if (!desc.p)
1389 panic("Segment not present.\\n");
1390 SegAttr attr = 0;
1391 attr.dpl = desc.dpl;
1392 attr.unusable = 0;
1393 attr.defaultSize = desc.d;
1394 attr.longMode = desc.l;
1395 attr.avl = desc.avl;
1396 attr.granularity = desc.g;
1397 attr.present = desc.p;
1398 attr.system = desc.s;
1399 attr.type = desc.type;
1400 if (!desc.s) {
1401 // The expand down bit happens to be set for gates.
1402 if (desc.type.e) {
1403 panic("Gate descriptor encountered.\\n");
1404 }
1405 attr.readable = 1;
1406 attr.writable = 1;
1407 attr.expandDown = 0;
1408 } else {
1409 if (desc.type.codeOrData) {
1410 attr.expandDown = 0;
1411 attr.readable = desc.type.r;
1412 attr.writable = 0;
1413 } else {
1414 attr.expandDown = desc.type.e;
1415 attr.readable = 1;
1416 attr.writable = desc.type.w;
1417 }
1418 }
1419 Addr base = desc.baseLow | (desc.baseHigh << 24);
1420 Addr limit = desc.limitLow | (desc.limitHigh << 16);
1421 if (desc.g)
1422 limit = (limit << 12) | mask(12);
1423 SegBaseDest = base;
1424 SegLimitDest = limit;
1425 SegAttrDest = attr;
1426 } else {
1427 SegBaseDest = SegBaseDest;
1428 SegLimitDest = SegLimitDest;
1429 SegAttrDest = SegAttrDest;
1430 }
1431 '''
1432}};