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