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