regop.isa (12236:126ac9da6050) regop.isa (12392:e0dbdf30a2a5)
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(ExecContext *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 IntReg result M5_VAR_USED;
55
56 if(%(cond_check)s)
57 {
58 %(code)s;
59 %(flag_code)s;
60 }
61 else
62 {
63 %(else_code)s;
64 }
65
66 //Write the resulting state to the execution context
67 if(fault == NoFault)
68 {
69 %(op_wb)s;
70 }
71 return fault;
72 }
73}};
74
75def template MicroRegOpImmExecute {{
76 Fault %(class_name)s::execute(ExecContext *xc,
77 Trace::InstRecord *traceData) const
78 {
79 Fault fault = NoFault;
80
81 %(op_decl)s;
82 %(op_rd)s;
83
84 IntReg result M5_VAR_USED;
85
86 if(%(cond_check)s)
87 {
88 %(code)s;
89 %(flag_code)s;
90 }
91 else
92 {
93 %(else_code)s;
94 }
95
96 //Write the resulting state to the execution context
97 if(fault == NoFault)
98 {
99 %(op_wb)s;
100 }
101 return fault;
102 }
103}};
104
105def template MicroRegOpDeclare {{
106 class %(class_name)s : public %(base_class)s
107 {
108 public:
109 %(class_name)s(ExtMachInst _machInst,
110 const char * instMnem, uint64_t setFlags,
111 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
112 uint8_t _dataSize, uint16_t _ext);
113
114 Fault execute(ExecContext *, Trace::InstRecord *) const;
115 };
116}};
117
118def template MicroRegOpImmDeclare {{
119
120 class %(class_name)s : public %(base_class)s
121 {
122 public:
123 %(class_name)s(ExtMachInst _machInst,
124 const char * instMnem, uint64_t setFlags,
125 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
126 uint8_t _dataSize, uint16_t _ext);
127
128 Fault execute(ExecContext *, Trace::InstRecord *) const;
129 };
130}};
131
132def template MicroRegOpConstructor {{
133 %(class_name)s::%(class_name)s(
134 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
135 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
136 uint8_t _dataSize, uint16_t _ext) :
137 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
138 _src1, _src2, _dest, _dataSize, _ext,
139 %(op_class)s)
140 {
141 %(constructor)s;
142 %(cond_control_flag_init)s;
143 }
144}};
145
146def template MicroRegOpImmConstructor {{
147 %(class_name)s::%(class_name)s(
148 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
149 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
150 uint8_t _dataSize, uint16_t _ext) :
151 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
152 _src1, _imm8, _dest, _dataSize, _ext,
153 %(op_class)s)
154 {
155 %(constructor)s;
156 %(cond_control_flag_init)s;
157 }
158}};
159
160output header {{
161 void
162 divide(uint64_t dividend, uint64_t divisor,
163 uint64_t &quotient, uint64_t &remainder);
164
165 enum SegmentSelectorCheck {
166 SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
167 SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
168 SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
169 };
170
171 enum LongModeDescriptorType {
172 LDT64 = 2,
173 AvailableTSS64 = 9,
174 BusyTSS64 = 0xb,
175 CallGate64 = 0xc,
176 IntGate64 = 0xe,
177 TrapGate64 = 0xf
178 };
179}};
180
181output decoder {{
182 void
183 divide(uint64_t dividend, uint64_t divisor,
184 uint64_t &quotient, uint64_t &remainder)
185 {
186 //Check for divide by zero.
187 assert(divisor != 0);
188 //If the divisor is bigger than the dividend, don't do anything.
189 if (divisor <= dividend) {
190 //Shift the divisor so it's msb lines up with the dividend.
191 int dividendMsb = findMsbSet(dividend);
192 int divisorMsb = findMsbSet(divisor);
193 int shift = dividendMsb - divisorMsb;
194 divisor <<= shift;
195 //Compute what we'll add to the quotient if the divisor isn't
196 //now larger than the dividend.
197 uint64_t quotientBit = 1;
198 quotientBit <<= shift;
199 //If we need to step back a bit (no pun intended) because the
200 //divisor got too to large, do that here. This is the "or two"
201 //part of one or two bit division.
202 if (divisor > dividend) {
203 quotientBit >>= 1;
204 divisor >>= 1;
205 }
206 //Decrement the remainder and increment the quotient.
207 quotient += quotientBit;
208 remainder -= divisor;
209 }
210 }
211}};
212
213let {{
214 # Make these empty strings so that concatenating onto
215 # them will always work.
216 header_output = ""
217 decoder_output = ""
218 exec_output = ""
219
220 immTemplates = (
221 MicroRegOpImmDeclare,
222 MicroRegOpImmConstructor,
223 MicroRegOpImmExecute)
224
225 regTemplates = (
226 MicroRegOpDeclare,
227 MicroRegOpConstructor,
228 MicroRegOpExecute)
229
230 class RegOpMeta(type):
231 def buildCppClasses(self, name, Name, suffix, code, big_code, \
232 flag_code, cond_check, else_code, cond_control_flag_init,
233 op_class):
234
235 # Globals to stick the output in
236 global header_output
237 global decoder_output
238 global exec_output
239
240 # Stick all the code together so it can be searched at once
241 allCode = "|".join((code, flag_code, cond_check, else_code,
242 cond_control_flag_init))
243 allBigCode = "|".join((big_code, flag_code, cond_check, else_code,
244 cond_control_flag_init))
245
246 # If op2 is used anywhere, make register and immediate versions
247 # of this code.
248 matcher = re.compile(r"(?<!\w)(?P<prefix>s?)op2(?P<typeQual>_[^\W_]+)?")
249 match = matcher.search(allCode + allBigCode)
250 if match:
251 typeQual = ""
252 if match.group("typeQual"):
253 typeQual = match.group("typeQual")
254 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
255 self.buildCppClasses(name, Name, suffix,
256 matcher.sub(src2_name, code),
257 matcher.sub(src2_name, big_code),
258 matcher.sub(src2_name, flag_code),
259 matcher.sub(src2_name, cond_check),
260 matcher.sub(src2_name, else_code),
261 matcher.sub(src2_name, cond_control_flag_init),
262 op_class)
263 imm_name = "%simm8" % match.group("prefix")
264 self.buildCppClasses(name + "i", Name, suffix + "Imm",
265 matcher.sub(imm_name, code),
266 matcher.sub(imm_name, big_code),
267 matcher.sub(imm_name, flag_code),
268 matcher.sub(imm_name, cond_check),
269 matcher.sub(imm_name, else_code),
270 matcher.sub(imm_name, cond_control_flag_init),
271 op_class)
272 return
273
274 # If there's something optional to do with flags, generate
275 # a version without it and fix up this version to use it.
276 if flag_code != "" or cond_check != "true":
277 self.buildCppClasses(name, Name, suffix,
278 code, big_code, "", "true", else_code, "", op_class)
279 suffix = "Flags" + suffix
280
281 # If psrc1 or psrc2 is used, we need to actually insert code to
282 # compute it.
283 for (big, all) in ((False, allCode), (True, allBigCode)):
284 prefix = ""
285 for (rex, decl) in (
286 ("(?<!\w)psrc1(?!\w)",
287 "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);"),
288 ("(?<!\w)psrc2(?!\w)",
289 "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);"),
290 ("(?<!\w)spsrc1(?!\w)",
291 "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);"),
292 ("(?<!\w)spsrc2(?!\w)",
293 "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);"),
294 ("(?<!\w)simm8(?!\w)",
295 "int8_t simm8 = imm8;")):
296 matcher = re.compile(rex)
297 if matcher.search(all):
298 prefix += decl + "\n"
299 if big:
300 if big_code != "":
301 big_code = prefix + big_code
302 else:
303 code = prefix + code
304
305 base = "X86ISA::RegOp"
306
307 # If imm8 shows up in the code, use the immediate templates, if
308 # not, hopefully the register ones will be correct.
309 templates = regTemplates
310 matcher = re.compile("(?<!\w)s?imm8(?!\w)")
311 if matcher.search(allCode):
312 base += "Imm"
313 templates = immTemplates
314
315 # Get everything ready for the substitution
316 iops = [InstObjParams(name, Name + suffix, base,
317 {"code" : code,
318 "flag_code" : flag_code,
319 "cond_check" : cond_check,
320 "else_code" : else_code,
321 "cond_control_flag_init" : cond_control_flag_init,
322 "op_class" : op_class})]
323 if big_code != "":
324 iops += [InstObjParams(name, Name + suffix + "Big", base,
325 {"code" : big_code,
326 "flag_code" : flag_code,
327 "cond_check" : cond_check,
328 "else_code" : else_code,
329 "cond_control_flag_init" : cond_control_flag_init,
330 "op_class" : op_class})]
331
332 # Generate the actual code (finally!)
333 for iop in iops:
334 header_output += templates[0].subst(iop)
335 decoder_output += templates[1].subst(iop)
336 exec_output += templates[2].subst(iop)
337
338
339 def __new__(mcls, Name, bases, dict):
340 abstract = False
341 name = Name.lower()
342 if "abstract" in dict:
343 abstract = dict['abstract']
344 del dict['abstract']
345
346 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
347 if not abstract:
348 cls.className = Name
349 cls.base_mnemonic = name
350 code = cls.code
351 big_code = cls.big_code
352 flag_code = cls.flag_code
353 cond_check = cls.cond_check
354 else_code = cls.else_code
355 cond_control_flag_init = cls.cond_control_flag_init
356 op_class = cls.op_class
357
358 # Set up the C++ classes
359 mcls.buildCppClasses(cls, name, Name, "", code, big_code,
360 flag_code, cond_check, else_code,
361 cond_control_flag_init, op_class)
362
363 # Hook into the microassembler dict
364 global microopClasses
365 microopClasses[name] = cls
366
367 allCode = "|".join((code, flag_code, cond_check, else_code,
368 cond_control_flag_init))
369
370 # If op2 is used anywhere, make register and immediate versions
371 # of this code.
372 matcher = re.compile(r"op2(?P<typeQual>_[^\W_]+)?")
373 if matcher.search(allCode):
374 microopClasses[name + 'i'] = cls
375 return cls
376
377
378 class RegOp(X86Microop):
379 __metaclass__ = RegOpMeta
380 # This class itself doesn't act as a microop
381 abstract = True
382
383 # Default template parameter values
384 big_code = ""
385 flag_code = ""
386 cond_check = "true"
387 else_code = ";"
388 cond_control_flag_init = ""
389 op_class = "IntAluOp"
390
391 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
392 self.dest = dest
393 self.src1 = src1
394 self.op2 = op2
395 self.flags = flags
396 self.dataSize = dataSize
397 if flags is None:
398 self.ext = 0
399 else:
400 if not isinstance(flags, (list, tuple)):
401 raise Exception, "flags must be a list or tuple of flags"
402 self.ext = " | ".join(flags)
403 self.className += "Flags"
404
405 def getAllocator(self, microFlags):
406 if self.big_code != "":
407 className = self.className
408 if self.mnemonic == self.base_mnemonic + 'i':
409 className += "Imm"
410 allocString = '''
411 (%(dataSize)s >= 4) ?
412 (StaticInstPtr)(new %(class_name)sBig(machInst,
413 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
414 %(dest)s, %(dataSize)s, %(ext)s)) :
415 (StaticInstPtr)(new %(class_name)s(machInst,
416 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
417 %(dest)s, %(dataSize)s, %(ext)s))
418 '''
419 allocator = allocString % {
420 "class_name" : className,
421 "flags" : self.microFlagsText(microFlags),
422 "src1" : self.src1, "op2" : self.op2,
423 "dest" : self.dest,
424 "dataSize" : self.dataSize,
425 "ext" : self.ext}
426 return allocator
427 else:
428 className = self.className
429 if self.mnemonic == self.base_mnemonic + 'i':
430 className += "Imm"
431 allocator = '''new %(class_name)s(machInst, macrocodeBlock,
432 %(flags)s, %(src1)s, %(op2)s, %(dest)s,
433 %(dataSize)s, %(ext)s)''' % {
434 "class_name" : className,
435 "flags" : self.microFlagsText(microFlags),
436 "src1" : self.src1, "op2" : self.op2,
437 "dest" : self.dest,
438 "dataSize" : self.dataSize,
439 "ext" : self.ext}
440 return allocator
441
442 class LogicRegOp(RegOp):
443 abstract = True
444 flag_code = '''
445 //Don't have genFlags handle the OF or CF bits
446 uint64_t mask = CFBit | ECFBit | OFBit;
447 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
448 PredezfBit, ext & ~mask, result, psrc1, op2);
449 PredezfBit = newFlags & EZFBit;
450 PreddfBit = newFlags & DFBit;
451 PredccFlagBits = newFlags & ccFlagMask;
452
453 //If a logic microop wants to set these, it wants to set them to 0.
454 PredcfofBits = PredcfofBits & ~((CFBit | OFBit) & ext);
455 PredecfBit = PredecfBit & ~(ECFBit & ext);
456 '''
457
458 class FlagRegOp(RegOp):
459 abstract = True
460 flag_code = '''
461 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits |
462 PreddfBit | PredecfBit | PredezfBit,
463 ext, result, psrc1, op2);
464
465 PredcfofBits = newFlags & cfofMask;
466 PredecfBit = newFlags & ECFBit;
467 PredezfBit = newFlags & EZFBit;
468 PreddfBit = newFlags & DFBit;
469 PredccFlagBits = newFlags & ccFlagMask;
470 '''
471
472 class SubRegOp(RegOp):
473 abstract = True
474 flag_code = '''
475 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits |
476 PreddfBit | PredecfBit | PredezfBit,
477 ext, result, psrc1, ~op2, true);
478
479 PredcfofBits = newFlags & cfofMask;
480 PredecfBit = newFlags & ECFBit;
481 PredezfBit = newFlags & EZFBit;
482 PreddfBit = newFlags & DFBit;
483 PredccFlagBits = newFlags & ccFlagMask;
484 '''
485
486 class CondRegOp(RegOp):
487 abstract = True
488 cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | ecfBit | \
489 ezfBit, ext)"
490 cond_control_flag_init = "flags[IsCondControl] = flags[IsControl];"
491
492 class RdRegOp(RegOp):
493 abstract = True
494 def __init__(self, dest, src1=None, dataSize="env.dataSize"):
495 if not src1:
496 src1 = dest
497 super(RdRegOp, self).__init__(dest, src1, \
498 "InstRegIndex(NUM_INTREGS)", None, dataSize)
499
500 class WrRegOp(RegOp):
501 abstract = True
502 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
503 super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
504 src1, src2, flags, dataSize)
505
506 class Add(FlagRegOp):
507 code = 'DestReg = merge(DestReg, result = (psrc1 + op2), dataSize);'
508 big_code = 'DestReg = result = (psrc1 + op2) & mask(dataSize * 8);'
509
510 class Or(LogicRegOp):
511 code = 'DestReg = merge(DestReg, result = (psrc1 | op2), dataSize);'
512 big_code = 'DestReg = result = (psrc1 | op2) & mask(dataSize * 8);'
513
514 class Adc(FlagRegOp):
515 code = '''
516 CCFlagBits flags = cfofBits;
517 DestReg = merge(DestReg, result = (psrc1 + op2 + flags.cf), dataSize);
518 '''
519 big_code = '''
520 CCFlagBits flags = cfofBits;
521 DestReg = result = (psrc1 + op2 + flags.cf) & mask(dataSize * 8);
522 '''
523
524 class Sbb(SubRegOp):
525 code = '''
526 CCFlagBits flags = cfofBits;
527 DestReg = merge(DestReg, result = (psrc1 - op2 - flags.cf), dataSize);
528 '''
529 big_code = '''
530 CCFlagBits flags = cfofBits;
531 DestReg = result = (psrc1 - op2 - flags.cf) & mask(dataSize * 8);
532 '''
533
534 class And(LogicRegOp):
535 code = 'DestReg = merge(DestReg, result = (psrc1 & op2), dataSize)'
536 big_code = 'DestReg = result = (psrc1 & op2) & mask(dataSize * 8)'
537
538 class Sub(SubRegOp):
539 code = 'DestReg = merge(DestReg, result = (psrc1 - op2), dataSize)'
540 big_code = 'DestReg = result = (psrc1 - op2) & mask(dataSize * 8)'
541
542 class Xor(LogicRegOp):
543 code = 'DestReg = merge(DestReg, result = (psrc1 ^ op2), dataSize)'
544 big_code = 'DestReg = result = (psrc1 ^ op2) & mask(dataSize * 8)'
545
546 class Mul1s(WrRegOp):
547 op_class = 'IntMultOp'
548
549 # Multiply two values Aa and Bb where Aa = A << p + a, then correct for
550 # negative operands.
551 # Aa * Bb
552 # = (A << p + a) * (B << p + b)
553 # = (A * B) << 2p + (A * b + a * B) << p + a * b
554 code = '''
555 ProdLow = psrc1 * op2;
556
557 int p = (dataSize * 8) / 2;
558 uint64_t A = bits(psrc1, 2 * p - 1, p);
559 uint64_t a = bits(psrc1, p - 1, 0);
560 uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p);
561 uint64_t b = bits<uint64_t>(op2, p - 1, 0);
562
563 uint64_t c1, c2; // Carry between place values.
564 uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B;
565
566 c1 = ab >> p;
567
568 // Be careful to avoid overflow if p is large.
569 if (p == 32) {
570 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
571 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
572 c2 >>= (p - 1);
573 } else {
574 c2 = (c1 + Ab + aB) >> p;
575 }
576
577 uint64_t hi = AB + c2;
578
579 if (bits(psrc1, dataSize * 8 - 1))
580 hi -= op2;
581 if (bits(op2, dataSize * 8 - 1))
582 hi -= psrc1;
583
584 ProdHi = hi;
585 '''
586 flag_code = '''
587 if ((-ProdHi & mask(dataSize * 8)) !=
588 bits(ProdLow, dataSize * 8 - 1)) {
589 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit));
590 PredecfBit = PredecfBit | (ext & ECFBit);
591 } else {
592 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
593 PredecfBit = PredecfBit & ~(ext & ECFBit);
594 }
595 '''
596
597 class Mul1u(WrRegOp):
598 op_class = 'IntMultOp'
599
600 # Multiply two values Aa and Bb where Aa = A << p + a.
601 # Aa * Bb
602 # = (A << p + a) * (B << p + b)
603 # = (A * B) << 2p + (A * b + a * B) << p + a * b
604 code = '''
605 ProdLow = psrc1 * op2;
606
607 int p = (dataSize * 8) / 2;
608 uint64_t A = bits(psrc1, 2 * p - 1, p);
609 uint64_t a = bits(psrc1, p - 1, 0);
610 uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p);
611 uint64_t b = bits<uint64_t>(op2, p - 1, 0);
612
613 uint64_t c1, c2; // Carry between place values.
614 uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B;
615
616 c1 = ab >> p;
617
618 // Be careful to avoid overflow if p is large.
619 if (p == 32) {
620 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
621 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
622 c2 >>= (p - 1);
623 } else {
624 c2 = (c1 + Ab + aB) >> p;
625 }
626
627 ProdHi = AB + c2;
628 '''
629 flag_code = '''
630 if (ProdHi) {
631 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit));
632 PredecfBit = PredecfBit | (ext & ECFBit);
633 } else {
634 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
635 PredecfBit = PredecfBit & ~(ext & ECFBit);
636 }
637 '''
638
639 class Mulel(RdRegOp):
640 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
641 big_code = 'DestReg = ProdLow & mask(dataSize * 8);'
642
643 class Muleh(RdRegOp):
644 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
645 if not src1:
646 src1 = dest
647 super(RdRegOp, self).__init__(dest, src1, \
648 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
649 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
650 big_code = 'DestReg = ProdHi & mask(dataSize * 8);'
651
652 # One or two bit divide
653 class Div1(WrRegOp):
654 op_class = 'IntDivOp'
655
656 code = '''
657 //These are temporaries so that modifying them later won't make
658 //the ISA parser think they're also sources.
659 uint64_t quotient = 0;
660 uint64_t remainder = psrc1;
661 //Similarly, this is a temporary so changing it doesn't make it
662 //a source.
663 uint64_t divisor = op2;
664 //This is a temporary just for consistency and clarity.
665 uint64_t dividend = remainder;
666 //Do the division.
667 if (divisor == 0) {
668 fault = std::make_shared<DivideError>();
669 } else {
670 divide(dividend, divisor, quotient, remainder);
671 //Record the final results.
672 Remainder = remainder;
673 Quotient = quotient;
674 Divisor = divisor;
675 }
676 '''
677
678 # Step divide
679 class Div2(RegOp):
680 op_class = 'IntDivOp'
681
682 divCode = '''
683 uint64_t dividend = Remainder;
684 uint64_t divisor = Divisor;
685 uint64_t quotient = Quotient;
686 uint64_t remainder = dividend;
687 int remaining = op2;
688 //If we overshot, do nothing. This lets us unrool division loops a
689 //little.
690 if (divisor == 0) {
691 fault = std::make_shared<DivideError>();
692 } else if (remaining) {
693 if (divisor & (ULL(1) << 63)) {
694 while (remaining && !(dividend & (ULL(1) << 63))) {
695 dividend = (dividend << 1) |
696 bits(SrcReg1, remaining - 1);
697 quotient <<= 1;
698 remaining--;
699 }
700 if (dividend & (ULL(1) << 63)) {
701 bool highBit = false;
702 if (dividend < divisor && remaining) {
703 highBit = true;
704 dividend = (dividend << 1) |
705 bits(SrcReg1, remaining - 1);
706 quotient <<= 1;
707 remaining--;
708 }
709 if (highBit || divisor <= dividend) {
710 quotient++;
711 dividend -= divisor;
712 }
713 }
714 remainder = dividend;
715 } else {
716 //Shift in bits from the low order portion of the dividend
717 while (dividend < divisor && remaining) {
718 dividend = (dividend << 1) |
719 bits(SrcReg1, remaining - 1);
720 quotient <<= 1;
721 remaining--;
722 }
723 remainder = dividend;
724 //Do the division.
725 divide(dividend, divisor, quotient, remainder);
726 }
727 }
728 //Keep track of how many bits there are still to pull in.
729 %s
730 //Record the final results
731 Remainder = remainder;
732 Quotient = quotient;
733 '''
734 code = divCode % "DestReg = merge(DestReg, remaining, dataSize);"
735 big_code = divCode % "DestReg = remaining & mask(dataSize * 8);"
736 flag_code = '''
737 if (remaining == 0)
738 PredezfBit = PredezfBit | (ext & EZFBit);
739 else
740 PredezfBit = PredezfBit & ~(ext & EZFBit);
741 '''
742
743 class Divq(RdRegOp):
744 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
745 big_code = 'DestReg = Quotient & mask(dataSize * 8);'
746
747 class Divr(RdRegOp):
748 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
749 big_code = 'DestReg = Remainder & mask(dataSize * 8);'
750
751 class Mov(CondRegOp):
752 code = 'DestReg = merge(SrcReg1, op2, dataSize)'
753 else_code = 'DestReg = DestReg;'
754
755 # Shift instructions
756
757 class Sll(RegOp):
758 code = '''
759 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
760 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
761 '''
762 big_code = '''
763 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
764 DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8);
765 '''
766 flag_code = '''
767 // If the shift amount is zero, no flags should be modified.
768 if (shiftAmt) {
769 //Zero out any flags we might modify. This way we only have to
770 //worry about setting them.
771 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
772 PredecfBit = PredecfBit & ~(ext & ECFBit);
773
774 int CFBits = 0;
775 //Figure out if we -would- set the CF bits if requested.
776 if (shiftAmt <= dataSize * 8 &&
777 bits(SrcReg1, dataSize * 8 - shiftAmt)) {
778 CFBits = 1;
779 }
780
781 //If some combination of the CF bits need to be set, set them.
782 if ((ext & (CFBit | ECFBit)) && CFBits) {
783 PredcfofBits = PredcfofBits | (ext & CFBit);
784 PredecfBit = PredecfBit | (ext & ECFBit);
785 }
786
787 //Figure out what the OF bit should be.
788 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
789 PredcfofBits = PredcfofBits | OFBit;
790
791 //Use the regular mechanisms to calculate the other flags.
792 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
793 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
794 DestReg, psrc1, op2);
795
796 PredezfBit = newFlags & EZFBit;
797 PreddfBit = newFlags & DFBit;
798 PredccFlagBits = newFlags & ccFlagMask;
799 }
800 '''
801
802 class Srl(RegOp):
803 # Because what happens to the bits shift -in- on a right shift
804 # is not defined in the C/C++ standard, we have to mask them out
805 # to be sure they're zero.
806 code = '''
807 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
808 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
809 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
810 '''
811 big_code = '''
812 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
813 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
814 DestReg = (psrc1 >> shiftAmt) & logicalMask;
815 '''
816 flag_code = '''
817 // If the shift amount is zero, no flags should be modified.
818 if (shiftAmt) {
819 //Zero out any flags we might modify. This way we only have to
820 //worry about setting them.
821 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
822 PredecfBit = PredecfBit & ~(ext & ECFBit);
823
824 //If some combination of the CF bits need to be set, set them.
825 if ((ext & (CFBit | ECFBit)) &&
826 shiftAmt <= dataSize * 8 &&
827 bits(SrcReg1, shiftAmt - 1)) {
828 PredcfofBits = PredcfofBits | (ext & CFBit);
829 PredecfBit = PredecfBit | (ext & ECFBit);
830 }
831
832 //Figure out what the OF bit should be.
833 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
834 PredcfofBits = PredcfofBits | OFBit;
835
836 //Use the regular mechanisms to calculate the other flags.
837 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
838 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
839 DestReg, psrc1, op2);
840
841 PredezfBit = newFlags & EZFBit;
842 PreddfBit = newFlags & DFBit;
843 PredccFlagBits = newFlags & ccFlagMask;
844 }
845 '''
846
847 class Sra(RegOp):
848 # Because what happens to the bits shift -in- on a right shift
849 # is not defined in the C/C++ standard, we have to sign extend
850 # them manually to be sure.
851 code = '''
852 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
853 uint64_t arithMask = (shiftAmt == 0) ? 0 :
854 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
855 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
856 '''
857 big_code = '''
858 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
859 uint64_t arithMask = (shiftAmt == 0) ? 0 :
860 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
861 DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8);
862 '''
863 flag_code = '''
864 // If the shift amount is zero, no flags should be modified.
865 if (shiftAmt) {
866 //Zero out any flags we might modify. This way we only have to
867 //worry about setting them.
868 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
869 PredecfBit = PredecfBit & ~(ext & ECFBit);
870
871 //If some combination of the CF bits need to be set, set them.
872 uint8_t effectiveShift =
873 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
874 if ((ext & (CFBit | ECFBit)) &&
875 bits(SrcReg1, effectiveShift - 1)) {
876 PredcfofBits = PredcfofBits | (ext & CFBit);
877 PredecfBit = PredecfBit | (ext & ECFBit);
878 }
879
880 //Use the regular mechanisms to calculate the other flags.
881 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
882 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
883 DestReg, psrc1, op2);
884
885 PredezfBit = newFlags & EZFBit;
886 PreddfBit = newFlags & DFBit;
887 PredccFlagBits = newFlags & ccFlagMask;
888 }
889 '''
890
891 class Ror(RegOp):
892 code = '''
893 uint8_t shiftAmt =
894 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
895 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
896 if (realShiftAmt) {
897 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
898 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
899 DestReg = merge(DestReg, top | bottom, dataSize);
900 } else
901 DestReg = merge(DestReg, DestReg, dataSize);
902 '''
903 flag_code = '''
904 // If the shift amount is zero, no flags should be modified.
905 if (shiftAmt) {
906 //Zero out any flags we might modify. This way we only have to
907 //worry about setting them.
908 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
909 PredecfBit = PredecfBit & ~(ext & ECFBit);
910
911 //Find the most and second most significant bits of the result.
912 int msb = bits(DestReg, dataSize * 8 - 1);
913 int smsb = bits(DestReg, dataSize * 8 - 2);
914 //If some combination of the CF bits need to be set, set them.
915 if ((ext & (CFBit | ECFBit)) && msb) {
916 PredcfofBits = PredcfofBits | (ext & CFBit);
917 PredecfBit = PredecfBit | (ext & ECFBit);
918 }
919
920 //Figure out what the OF bit should be.
921 if ((ext & OFBit) && (msb ^ smsb))
922 PredcfofBits = PredcfofBits | OFBit;
923
924 //Use the regular mechanisms to calculate the other flags.
925 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
926 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
927 DestReg, psrc1, op2);
928
929 PredezfBit = newFlags & EZFBit;
930 PreddfBit = newFlags & DFBit;
931 PredccFlagBits = newFlags & ccFlagMask;
932 }
933 '''
934
935 class Rcr(RegOp):
936 code = '''
937 uint8_t shiftAmt =
938 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
939 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
940 if (realShiftAmt) {
941 CCFlagBits flags = cfofBits;
942 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
943 if (realShiftAmt > 1)
944 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
945 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
946 DestReg = merge(DestReg, top | bottom, dataSize);
947 } else
948 DestReg = merge(DestReg, DestReg, dataSize);
949 '''
950 flag_code = '''
951 // If the shift amount is zero, no flags should be modified.
952 if (shiftAmt) {
953 int origCFBit = (cfofBits & CFBit) ? 1 : 0;
954 //Zero out any flags we might modify. This way we only have to
955 //worry about setting them.
956 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
957 PredecfBit = PredecfBit & ~(ext & ECFBit);
958
959 //Figure out what the OF bit should be.
960 if ((ext & OFBit) && (origCFBit ^
961 bits(SrcReg1, dataSize * 8 - 1))) {
962 PredcfofBits = PredcfofBits | OFBit;
963 }
964 //If some combination of the CF bits need to be set, set them.
965 if ((ext & (CFBit | ECFBit)) &&
966 (realShiftAmt == 0) ? origCFBit :
967 bits(SrcReg1, realShiftAmt - 1)) {
968 PredcfofBits = PredcfofBits | (ext & CFBit);
969 PredecfBit = PredecfBit | (ext & ECFBit);
970 }
971
972 //Use the regular mechanisms to calculate the other flags.
973 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
974 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
975 DestReg, psrc1, op2);
976
977 PredezfBit = newFlags & EZFBit;
978 PreddfBit = newFlags & DFBit;
979 PredccFlagBits = newFlags & ccFlagMask;
980 }
981 '''
982
983 class Rol(RegOp):
984 code = '''
985 uint8_t shiftAmt =
986 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
987 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
988 if (realShiftAmt) {
989 uint64_t top = psrc1 << realShiftAmt;
990 uint64_t bottom =
991 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
992 DestReg = merge(DestReg, top | bottom, dataSize);
993 } else
994 DestReg = merge(DestReg, DestReg, dataSize);
995 '''
996 flag_code = '''
997 // If the shift amount is zero, no flags should be modified.
998 if (shiftAmt) {
999 //Zero out any flags we might modify. This way we only have to
1000 //worry about setting them.
1001 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1002 PredecfBit = PredecfBit & ~(ext & ECFBit);
1003
1004 //The CF bits, if set, would be set to the lsb of the result.
1005 int lsb = DestReg & 0x1;
1006 int msb = bits(DestReg, dataSize * 8 - 1);
1007 //If some combination of the CF bits need to be set, set them.
1008 if ((ext & (CFBit | ECFBit)) && lsb) {
1009 PredcfofBits = PredcfofBits | (ext & CFBit);
1010 PredecfBit = PredecfBit | (ext & ECFBit);
1011 }
1012
1013 //Figure out what the OF bit should be.
1014 if ((ext & OFBit) && (msb ^ lsb))
1015 PredcfofBits = PredcfofBits | OFBit;
1016
1017 //Use the regular mechanisms to calculate the other flags.
1018 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1019 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1020 DestReg, psrc1, op2);
1021
1022 PredezfBit = newFlags & EZFBit;
1023 PreddfBit = newFlags & DFBit;
1024 PredccFlagBits = newFlags & ccFlagMask;
1025 }
1026 '''
1027
1028 class Rcl(RegOp):
1029 code = '''
1030 uint8_t shiftAmt =
1031 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
1032 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
1033 if (realShiftAmt) {
1034 CCFlagBits flags = cfofBits;
1035 uint64_t top = psrc1 << realShiftAmt;
1036 uint64_t bottom = flags.cf << (realShiftAmt - 1);
1037 if(shiftAmt > 1)
1038 bottom |=
1039 bits(psrc1, dataSize * 8 - 1,
1040 dataSize * 8 - realShiftAmt + 1);
1041 DestReg = merge(DestReg, top | bottom, dataSize);
1042 } else
1043 DestReg = merge(DestReg, DestReg, dataSize);
1044 '''
1045 flag_code = '''
1046 // If the shift amount is zero, no flags should be modified.
1047 if (shiftAmt) {
1048 int origCFBit = (cfofBits & CFBit) ? 1 : 0;
1049 //Zero out any flags we might modify. This way we only have to
1050 //worry about setting them.
1051 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1052 PredecfBit = PredecfBit & ~(ext & ECFBit);
1053
1054 int msb = bits(DestReg, dataSize * 8 - 1);
1055 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
1056 //If some combination of the CF bits need to be set, set them.
1057 if ((ext & (CFBit | ECFBit)) &&
1058 (realShiftAmt == 0) ? origCFBit : CFBits) {
1059 PredcfofBits = PredcfofBits | (ext & CFBit);
1060 PredecfBit = PredecfBit | (ext & ECFBit);
1061 }
1062
1063 //Figure out what the OF bit should be.
1064 if ((ext & OFBit) && (msb ^ CFBits))
1065 PredcfofBits = PredcfofBits | OFBit;
1066
1067 //Use the regular mechanisms to calculate the other flags.
1068 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1069 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1070 DestReg, psrc1, op2);
1071
1072 PredezfBit = newFlags & EZFBit;
1073 PreddfBit = newFlags & DFBit;
1074 PredccFlagBits = newFlags & ccFlagMask;
1075 }
1076 '''
1077
1078 class Sld(RegOp):
1079 sldCode = '''
1080 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
1081 uint8_t dataBits = dataSize * 8;
1082 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
1083 uint64_t result;
1084 if (realShiftAmt == 0) {
1085 result = psrc1;
1086 } else if (realShiftAmt < dataBits) {
1087 result = (psrc1 << realShiftAmt) |
1088 (DoubleBits >> (dataBits - realShiftAmt));
1089 } else {
1090 result = (DoubleBits << (realShiftAmt - dataBits)) |
1091 (psrc1 >> (2 * dataBits - realShiftAmt));
1092 }
1093 %s
1094 '''
1095 code = sldCode % "DestReg = merge(DestReg, result, dataSize);"
1096 big_code = sldCode % "DestReg = result & mask(dataSize * 8);"
1097 flag_code = '''
1098 // If the shift amount is zero, no flags should be modified.
1099 if (shiftAmt) {
1100 //Zero out any flags we might modify. This way we only have to
1101 //worry about setting them.
1102 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1103 PredecfBit = PredecfBit & ~(ext & ECFBit);
1104 int CFBits = 0;
1105
1106 //Figure out if we -would- set the CF bits if requested.
1107 if ((realShiftAmt == 0 &&
1108 bits(DoubleBits, 0)) ||
1109 (realShiftAmt <= dataBits &&
1110 bits(SrcReg1, dataBits - realShiftAmt)) ||
1111 (realShiftAmt > dataBits &&
1112 bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
1113 CFBits = 1;
1114 }
1115
1116 //If some combination of the CF bits need to be set, set them.
1117 if ((ext & (CFBit | ECFBit)) && CFBits) {
1118 PredcfofBits = PredcfofBits | (ext & CFBit);
1119 PredecfBit = PredecfBit | (ext & ECFBit);
1120 }
1121
1122 //Figure out what the OF bit should be.
1123 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
1124 bits(result, dataBits - 1)))
1125 PredcfofBits = PredcfofBits | OFBit;
1126
1127 //Use the regular mechanisms to calculate the other flags.
1128 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1129 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1130 DestReg, psrc1, op2);
1131
1132 PredezfBit = newFlags & EZFBit;
1133 PreddfBit = newFlags & DFBit;
1134 PredccFlagBits = newFlags & ccFlagMask;
1135 }
1136 '''
1137
1138 class Srd(RegOp):
1139 srdCode = '''
1140 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
1141 uint8_t dataBits = dataSize * 8;
1142 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
1143 uint64_t result;
1144 if (realShiftAmt == 0) {
1145 result = psrc1;
1146 } else if (realShiftAmt < dataBits) {
1147 // Because what happens to the bits shift -in- on a right
1148 // shift is not defined in the C/C++ standard, we have to
1149 // mask them out to be sure they're zero.
1150 uint64_t logicalMask = mask(dataBits - realShiftAmt);
1151 result = ((psrc1 >> realShiftAmt) & logicalMask) |
1152 (DoubleBits << (dataBits - realShiftAmt));
1153 } else {
1154 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
1155 result = ((DoubleBits >> (realShiftAmt - dataBits)) &
1156 logicalMask) |
1157 (psrc1 << (2 * dataBits - realShiftAmt));
1158 }
1159 %s
1160 '''
1161 code = srdCode % "DestReg = merge(DestReg, result, dataSize);"
1162 big_code = srdCode % "DestReg = result & mask(dataSize * 8);"
1163 flag_code = '''
1164 // If the shift amount is zero, no flags should be modified.
1165 if (shiftAmt) {
1166 //Zero out any flags we might modify. This way we only have to
1167 //worry about setting them.
1168 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1169 PredecfBit = PredecfBit & ~(ext & ECFBit);
1170 int CFBits = 0;
1171
1172 //If some combination of the CF bits need to be set, set them.
1173 if ((realShiftAmt == 0 &&
1174 bits(DoubleBits, dataBits - 1)) ||
1175 (realShiftAmt <= dataBits &&
1176 bits(SrcReg1, realShiftAmt - 1)) ||
1177 (realShiftAmt > dataBits &&
1178 bits(DoubleBits, realShiftAmt - dataBits - 1))) {
1179 CFBits = 1;
1180 }
1181
1182 //If some combination of the CF bits need to be set, set them.
1183 if ((ext & (CFBit | ECFBit)) && CFBits) {
1184 PredcfofBits = PredcfofBits | (ext & CFBit);
1185 PredecfBit = PredecfBit | (ext & ECFBit);
1186 }
1187
1188 //Figure out what the OF bit should be.
1189 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
1190 bits(result, dataBits - 1)))
1191 PredcfofBits = PredcfofBits | OFBit;
1192
1193 //Use the regular mechanisms to calculate the other flags.
1194 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1195 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1196 DestReg, psrc1, op2);
1197
1198 PredezfBit = newFlags & EZFBit;
1199 PreddfBit = newFlags & DFBit;
1200 PredccFlagBits = newFlags & ccFlagMask;
1201 }
1202 '''
1203
1204 class Mdb(WrRegOp):
1205 code = 'DoubleBits = psrc1 ^ op2;'
1206
1207 class Wrip(WrRegOp, CondRegOp):
1208 code = 'NRIP = psrc1 + sop2 + CSBase;'
1209 else_code = "NRIP = NRIP;"
1210
1211 class Wruflags(WrRegOp):
1212 code = '''
1213 uint64_t newFlags = psrc1 ^ op2;
1214 cfofBits = newFlags & cfofMask;
1215 ecfBit = newFlags & ECFBit;
1216 ezfBit = newFlags & EZFBit;
1217 dfBit = newFlags & DFBit;
1218 ccFlagBits = newFlags & ccFlagMask;
1219 '''
1220
1221 class Wrflags(WrRegOp):
1222 code = '''
1223 MiscReg newFlags = psrc1 ^ op2;
1224 MiscReg userFlagMask = 0xDD5;
1225
1226 // Get only the user flags
1227 ccFlagBits = newFlags & ccFlagMask;
1228 dfBit = newFlags & DFBit;
1229 cfofBits = newFlags & cfofMask;
1230 ecfBit = 0;
1231 ezfBit = 0;
1232
1233 // Get everything else
1234 nccFlagBits = newFlags & ~userFlagMask;
1235 '''
1236
1237 class Rdip(RdRegOp):
1238 code = 'DestReg = NRIP - CSBase;'
1239
1240 class Ruflags(RdRegOp):
1241 code = 'DestReg = ccFlagBits | cfofBits | dfBit | ecfBit | ezfBit;'
1242
1243 class Rflags(RdRegOp):
1244 code = '''
1245 DestReg = ccFlagBits | cfofBits | dfBit |
1246 ecfBit | ezfBit | nccFlagBits;
1247 '''
1248
1249 class Ruflag(RegOp):
1250 code = '''
1251 int flag = bits(ccFlagBits | cfofBits | dfBit |
1252 ecfBit | ezfBit, imm8);
1253 DestReg = merge(DestReg, flag, dataSize);
1254 ezfBit = (flag == 0) ? EZFBit : 0;
1255 '''
1256
1257 big_code = '''
1258 int flag = bits(ccFlagBits | cfofBits | dfBit |
1259 ecfBit | ezfBit, imm8);
1260 DestReg = flag & mask(dataSize * 8);
1261 ezfBit = (flag == 0) ? EZFBit : 0;
1262 '''
1263
1264 def __init__(self, dest, imm, flags=None, \
1265 dataSize="env.dataSize"):
1266 super(Ruflag, self).__init__(dest, \
1267 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1268
1269 class Rflag(RegOp):
1270 code = '''
1271 MiscReg flagMask = 0x3F7FDD5;
1272 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit |
1273 ecfBit | ezfBit) & flagMask;
1274
1275 int flag = bits(flags, imm8);
1276 DestReg = merge(DestReg, flag, dataSize);
1277 ezfBit = (flag == 0) ? EZFBit : 0;
1278 '''
1279
1280 big_code = '''
1281 MiscReg flagMask = 0x3F7FDD5;
1282 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit |
1283 ecfBit | ezfBit) & flagMask;
1284
1285 int flag = bits(flags, imm8);
1286 DestReg = flag & mask(dataSize * 8);
1287 ezfBit = (flag == 0) ? EZFBit : 0;
1288 '''
1289
1290 def __init__(self, dest, imm, flags=None, \
1291 dataSize="env.dataSize"):
1292 super(Rflag, self).__init__(dest, \
1293 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1294
1295 class Sext(RegOp):
1296 code = '''
1297 IntReg val = psrc1;
1298 // Mask the bit position so that it wraps.
1299 int bitPos = op2 & (dataSize * 8 - 1);
1300 int sign_bit = bits(val, bitPos, bitPos);
1301 uint64_t maskVal = mask(bitPos+1);
1302 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1303 DestReg = merge(DestReg, val, dataSize);
1304 '''
1305
1306 big_code = '''
1307 IntReg val = psrc1;
1308 // Mask the bit position so that it wraps.
1309 int bitPos = op2 & (dataSize * 8 - 1);
1310 int sign_bit = bits(val, bitPos, bitPos);
1311 uint64_t maskVal = mask(bitPos+1);
1312 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1313 DestReg = val & mask(dataSize * 8);
1314 '''
1315
1316 flag_code = '''
1317 if (!sign_bit) {
1318 PredccFlagBits = PredccFlagBits & ~(ext & (ZFBit));
1319 PredcfofBits = PredcfofBits & ~(ext & (CFBit));
1320 PredecfBit = PredecfBit & ~(ext & ECFBit);
1321 PredezfBit = PredezfBit & ~(ext & EZFBit);
1322 } else {
1323 PredccFlagBits = PredccFlagBits | (ext & (ZFBit));
1324 PredcfofBits = PredcfofBits | (ext & (CFBit));
1325 PredecfBit = PredecfBit | (ext & ECFBit);
1326 PredezfBit = PredezfBit | (ext & EZFBit);
1327 }
1328 '''
1329
1330 class Zext(RegOp):
1331 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1332 big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);'
1333
1334 class Rddr(RegOp):
1335 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1336 super(Rddr, self).__init__(dest, \
1337 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1338 rdrCode = '''
1339 CR4 cr4 = CR4Op;
1340 DR7 dr7 = DR7Op;
1341 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1342 fault = std::make_shared<InvalidOpcode>();
1343 } else if (dr7.gd) {
1344 fault = std::make_shared<DebugException>();
1345 } else {
1346 %s
1347 }
1348 '''
1349 code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);"
1350 big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);"
1351
1352 class Wrdr(RegOp):
1353 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1354 super(Wrdr, self).__init__(dest, \
1355 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1356 code = '''
1357 CR4 cr4 = CR4Op;
1358 DR7 dr7 = DR7Op;
1359 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1360 fault = std::make_shared<InvalidOpcode>();
1361 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1362 machInst.mode.mode == LongMode) {
1363 fault = std::make_shared<GeneralProtection>(0);
1364 } else if (dr7.gd) {
1365 fault = std::make_shared<DebugException>();
1366 } else {
1367 DebugDest = psrc1;
1368 }
1369 '''
1370
1371 class Rdcr(RegOp):
1372 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1373 super(Rdcr, self).__init__(dest, \
1374 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1375 rdcrCode = '''
1376 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1377 fault = std::make_shared<InvalidOpcode>();
1378 } else {
1379 %s
1380 }
1381 '''
1382 code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);"
1383 big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);"
1384
1385 class Wrcr(RegOp):
1386 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1387 super(Wrcr, self).__init__(dest, \
1388 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1389 code = '''
1390 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1391 fault = std::make_shared<InvalidOpcode>();
1392 } else {
1393 // There are *s in the line below so it doesn't confuse the
1394 // parser. They may be unnecessary.
1395 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1396 MiscReg newVal = psrc1;
1397
1398 // Check for any modifications that would cause a fault.
1399 switch(dest) {
1400 case 0:
1401 {
1402 Efer efer = EferOp;
1403 CR0 cr0 = newVal;
1404 CR4 oldCr4 = CR4Op;
1405 if (bits(newVal, 63, 32) ||
1406 (!cr0.pe && cr0.pg) ||
1407 (!cr0.cd && cr0.nw) ||
1408 (cr0.pg && efer.lme && !oldCr4.pae))
1409 fault = std::make_shared<GeneralProtection>(0);
1410 }
1411 break;
1412 case 2:
1413 break;
1414 case 3:
1415 break;
1416 case 4:
1417 {
1418 CR4 cr4 = newVal;
1419 // PAE can't be disabled in long mode.
1420 if (bits(newVal, 63, 11) ||
1421 (machInst.mode.mode == LongMode && !cr4.pae))
1422 fault = std::make_shared<GeneralProtection>(0);
1423 }
1424 break;
1425 case 8:
1426 {
1427 if (bits(newVal, 63, 4))
1428 fault = std::make_shared<GeneralProtection>(0);
1429 }
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(ExecContext *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 IntReg result M5_VAR_USED;
55
56 if(%(cond_check)s)
57 {
58 %(code)s;
59 %(flag_code)s;
60 }
61 else
62 {
63 %(else_code)s;
64 }
65
66 //Write the resulting state to the execution context
67 if(fault == NoFault)
68 {
69 %(op_wb)s;
70 }
71 return fault;
72 }
73}};
74
75def template MicroRegOpImmExecute {{
76 Fault %(class_name)s::execute(ExecContext *xc,
77 Trace::InstRecord *traceData) const
78 {
79 Fault fault = NoFault;
80
81 %(op_decl)s;
82 %(op_rd)s;
83
84 IntReg result M5_VAR_USED;
85
86 if(%(cond_check)s)
87 {
88 %(code)s;
89 %(flag_code)s;
90 }
91 else
92 {
93 %(else_code)s;
94 }
95
96 //Write the resulting state to the execution context
97 if(fault == NoFault)
98 {
99 %(op_wb)s;
100 }
101 return fault;
102 }
103}};
104
105def template MicroRegOpDeclare {{
106 class %(class_name)s : public %(base_class)s
107 {
108 public:
109 %(class_name)s(ExtMachInst _machInst,
110 const char * instMnem, uint64_t setFlags,
111 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
112 uint8_t _dataSize, uint16_t _ext);
113
114 Fault execute(ExecContext *, Trace::InstRecord *) const;
115 };
116}};
117
118def template MicroRegOpImmDeclare {{
119
120 class %(class_name)s : public %(base_class)s
121 {
122 public:
123 %(class_name)s(ExtMachInst _machInst,
124 const char * instMnem, uint64_t setFlags,
125 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
126 uint8_t _dataSize, uint16_t _ext);
127
128 Fault execute(ExecContext *, Trace::InstRecord *) const;
129 };
130}};
131
132def template MicroRegOpConstructor {{
133 %(class_name)s::%(class_name)s(
134 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
135 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
136 uint8_t _dataSize, uint16_t _ext) :
137 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
138 _src1, _src2, _dest, _dataSize, _ext,
139 %(op_class)s)
140 {
141 %(constructor)s;
142 %(cond_control_flag_init)s;
143 }
144}};
145
146def template MicroRegOpImmConstructor {{
147 %(class_name)s::%(class_name)s(
148 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
149 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
150 uint8_t _dataSize, uint16_t _ext) :
151 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
152 _src1, _imm8, _dest, _dataSize, _ext,
153 %(op_class)s)
154 {
155 %(constructor)s;
156 %(cond_control_flag_init)s;
157 }
158}};
159
160output header {{
161 void
162 divide(uint64_t dividend, uint64_t divisor,
163 uint64_t &quotient, uint64_t &remainder);
164
165 enum SegmentSelectorCheck {
166 SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
167 SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
168 SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
169 };
170
171 enum LongModeDescriptorType {
172 LDT64 = 2,
173 AvailableTSS64 = 9,
174 BusyTSS64 = 0xb,
175 CallGate64 = 0xc,
176 IntGate64 = 0xe,
177 TrapGate64 = 0xf
178 };
179}};
180
181output decoder {{
182 void
183 divide(uint64_t dividend, uint64_t divisor,
184 uint64_t &quotient, uint64_t &remainder)
185 {
186 //Check for divide by zero.
187 assert(divisor != 0);
188 //If the divisor is bigger than the dividend, don't do anything.
189 if (divisor <= dividend) {
190 //Shift the divisor so it's msb lines up with the dividend.
191 int dividendMsb = findMsbSet(dividend);
192 int divisorMsb = findMsbSet(divisor);
193 int shift = dividendMsb - divisorMsb;
194 divisor <<= shift;
195 //Compute what we'll add to the quotient if the divisor isn't
196 //now larger than the dividend.
197 uint64_t quotientBit = 1;
198 quotientBit <<= shift;
199 //If we need to step back a bit (no pun intended) because the
200 //divisor got too to large, do that here. This is the "or two"
201 //part of one or two bit division.
202 if (divisor > dividend) {
203 quotientBit >>= 1;
204 divisor >>= 1;
205 }
206 //Decrement the remainder and increment the quotient.
207 quotient += quotientBit;
208 remainder -= divisor;
209 }
210 }
211}};
212
213let {{
214 # Make these empty strings so that concatenating onto
215 # them will always work.
216 header_output = ""
217 decoder_output = ""
218 exec_output = ""
219
220 immTemplates = (
221 MicroRegOpImmDeclare,
222 MicroRegOpImmConstructor,
223 MicroRegOpImmExecute)
224
225 regTemplates = (
226 MicroRegOpDeclare,
227 MicroRegOpConstructor,
228 MicroRegOpExecute)
229
230 class RegOpMeta(type):
231 def buildCppClasses(self, name, Name, suffix, code, big_code, \
232 flag_code, cond_check, else_code, cond_control_flag_init,
233 op_class):
234
235 # Globals to stick the output in
236 global header_output
237 global decoder_output
238 global exec_output
239
240 # Stick all the code together so it can be searched at once
241 allCode = "|".join((code, flag_code, cond_check, else_code,
242 cond_control_flag_init))
243 allBigCode = "|".join((big_code, flag_code, cond_check, else_code,
244 cond_control_flag_init))
245
246 # If op2 is used anywhere, make register and immediate versions
247 # of this code.
248 matcher = re.compile(r"(?<!\w)(?P<prefix>s?)op2(?P<typeQual>_[^\W_]+)?")
249 match = matcher.search(allCode + allBigCode)
250 if match:
251 typeQual = ""
252 if match.group("typeQual"):
253 typeQual = match.group("typeQual")
254 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
255 self.buildCppClasses(name, Name, suffix,
256 matcher.sub(src2_name, code),
257 matcher.sub(src2_name, big_code),
258 matcher.sub(src2_name, flag_code),
259 matcher.sub(src2_name, cond_check),
260 matcher.sub(src2_name, else_code),
261 matcher.sub(src2_name, cond_control_flag_init),
262 op_class)
263 imm_name = "%simm8" % match.group("prefix")
264 self.buildCppClasses(name + "i", Name, suffix + "Imm",
265 matcher.sub(imm_name, code),
266 matcher.sub(imm_name, big_code),
267 matcher.sub(imm_name, flag_code),
268 matcher.sub(imm_name, cond_check),
269 matcher.sub(imm_name, else_code),
270 matcher.sub(imm_name, cond_control_flag_init),
271 op_class)
272 return
273
274 # If there's something optional to do with flags, generate
275 # a version without it and fix up this version to use it.
276 if flag_code != "" or cond_check != "true":
277 self.buildCppClasses(name, Name, suffix,
278 code, big_code, "", "true", else_code, "", op_class)
279 suffix = "Flags" + suffix
280
281 # If psrc1 or psrc2 is used, we need to actually insert code to
282 # compute it.
283 for (big, all) in ((False, allCode), (True, allBigCode)):
284 prefix = ""
285 for (rex, decl) in (
286 ("(?<!\w)psrc1(?!\w)",
287 "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);"),
288 ("(?<!\w)psrc2(?!\w)",
289 "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);"),
290 ("(?<!\w)spsrc1(?!\w)",
291 "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);"),
292 ("(?<!\w)spsrc2(?!\w)",
293 "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);"),
294 ("(?<!\w)simm8(?!\w)",
295 "int8_t simm8 = imm8;")):
296 matcher = re.compile(rex)
297 if matcher.search(all):
298 prefix += decl + "\n"
299 if big:
300 if big_code != "":
301 big_code = prefix + big_code
302 else:
303 code = prefix + code
304
305 base = "X86ISA::RegOp"
306
307 # If imm8 shows up in the code, use the immediate templates, if
308 # not, hopefully the register ones will be correct.
309 templates = regTemplates
310 matcher = re.compile("(?<!\w)s?imm8(?!\w)")
311 if matcher.search(allCode):
312 base += "Imm"
313 templates = immTemplates
314
315 # Get everything ready for the substitution
316 iops = [InstObjParams(name, Name + suffix, base,
317 {"code" : code,
318 "flag_code" : flag_code,
319 "cond_check" : cond_check,
320 "else_code" : else_code,
321 "cond_control_flag_init" : cond_control_flag_init,
322 "op_class" : op_class})]
323 if big_code != "":
324 iops += [InstObjParams(name, Name + suffix + "Big", base,
325 {"code" : big_code,
326 "flag_code" : flag_code,
327 "cond_check" : cond_check,
328 "else_code" : else_code,
329 "cond_control_flag_init" : cond_control_flag_init,
330 "op_class" : op_class})]
331
332 # Generate the actual code (finally!)
333 for iop in iops:
334 header_output += templates[0].subst(iop)
335 decoder_output += templates[1].subst(iop)
336 exec_output += templates[2].subst(iop)
337
338
339 def __new__(mcls, Name, bases, dict):
340 abstract = False
341 name = Name.lower()
342 if "abstract" in dict:
343 abstract = dict['abstract']
344 del dict['abstract']
345
346 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
347 if not abstract:
348 cls.className = Name
349 cls.base_mnemonic = name
350 code = cls.code
351 big_code = cls.big_code
352 flag_code = cls.flag_code
353 cond_check = cls.cond_check
354 else_code = cls.else_code
355 cond_control_flag_init = cls.cond_control_flag_init
356 op_class = cls.op_class
357
358 # Set up the C++ classes
359 mcls.buildCppClasses(cls, name, Name, "", code, big_code,
360 flag_code, cond_check, else_code,
361 cond_control_flag_init, op_class)
362
363 # Hook into the microassembler dict
364 global microopClasses
365 microopClasses[name] = cls
366
367 allCode = "|".join((code, flag_code, cond_check, else_code,
368 cond_control_flag_init))
369
370 # If op2 is used anywhere, make register and immediate versions
371 # of this code.
372 matcher = re.compile(r"op2(?P<typeQual>_[^\W_]+)?")
373 if matcher.search(allCode):
374 microopClasses[name + 'i'] = cls
375 return cls
376
377
378 class RegOp(X86Microop):
379 __metaclass__ = RegOpMeta
380 # This class itself doesn't act as a microop
381 abstract = True
382
383 # Default template parameter values
384 big_code = ""
385 flag_code = ""
386 cond_check = "true"
387 else_code = ";"
388 cond_control_flag_init = ""
389 op_class = "IntAluOp"
390
391 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
392 self.dest = dest
393 self.src1 = src1
394 self.op2 = op2
395 self.flags = flags
396 self.dataSize = dataSize
397 if flags is None:
398 self.ext = 0
399 else:
400 if not isinstance(flags, (list, tuple)):
401 raise Exception, "flags must be a list or tuple of flags"
402 self.ext = " | ".join(flags)
403 self.className += "Flags"
404
405 def getAllocator(self, microFlags):
406 if self.big_code != "":
407 className = self.className
408 if self.mnemonic == self.base_mnemonic + 'i':
409 className += "Imm"
410 allocString = '''
411 (%(dataSize)s >= 4) ?
412 (StaticInstPtr)(new %(class_name)sBig(machInst,
413 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
414 %(dest)s, %(dataSize)s, %(ext)s)) :
415 (StaticInstPtr)(new %(class_name)s(machInst,
416 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
417 %(dest)s, %(dataSize)s, %(ext)s))
418 '''
419 allocator = allocString % {
420 "class_name" : className,
421 "flags" : self.microFlagsText(microFlags),
422 "src1" : self.src1, "op2" : self.op2,
423 "dest" : self.dest,
424 "dataSize" : self.dataSize,
425 "ext" : self.ext}
426 return allocator
427 else:
428 className = self.className
429 if self.mnemonic == self.base_mnemonic + 'i':
430 className += "Imm"
431 allocator = '''new %(class_name)s(machInst, macrocodeBlock,
432 %(flags)s, %(src1)s, %(op2)s, %(dest)s,
433 %(dataSize)s, %(ext)s)''' % {
434 "class_name" : className,
435 "flags" : self.microFlagsText(microFlags),
436 "src1" : self.src1, "op2" : self.op2,
437 "dest" : self.dest,
438 "dataSize" : self.dataSize,
439 "ext" : self.ext}
440 return allocator
441
442 class LogicRegOp(RegOp):
443 abstract = True
444 flag_code = '''
445 //Don't have genFlags handle the OF or CF bits
446 uint64_t mask = CFBit | ECFBit | OFBit;
447 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
448 PredezfBit, ext & ~mask, result, psrc1, op2);
449 PredezfBit = newFlags & EZFBit;
450 PreddfBit = newFlags & DFBit;
451 PredccFlagBits = newFlags & ccFlagMask;
452
453 //If a logic microop wants to set these, it wants to set them to 0.
454 PredcfofBits = PredcfofBits & ~((CFBit | OFBit) & ext);
455 PredecfBit = PredecfBit & ~(ECFBit & ext);
456 '''
457
458 class FlagRegOp(RegOp):
459 abstract = True
460 flag_code = '''
461 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits |
462 PreddfBit | PredecfBit | PredezfBit,
463 ext, result, psrc1, op2);
464
465 PredcfofBits = newFlags & cfofMask;
466 PredecfBit = newFlags & ECFBit;
467 PredezfBit = newFlags & EZFBit;
468 PreddfBit = newFlags & DFBit;
469 PredccFlagBits = newFlags & ccFlagMask;
470 '''
471
472 class SubRegOp(RegOp):
473 abstract = True
474 flag_code = '''
475 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits |
476 PreddfBit | PredecfBit | PredezfBit,
477 ext, result, psrc1, ~op2, true);
478
479 PredcfofBits = newFlags & cfofMask;
480 PredecfBit = newFlags & ECFBit;
481 PredezfBit = newFlags & EZFBit;
482 PreddfBit = newFlags & DFBit;
483 PredccFlagBits = newFlags & ccFlagMask;
484 '''
485
486 class CondRegOp(RegOp):
487 abstract = True
488 cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | ecfBit | \
489 ezfBit, ext)"
490 cond_control_flag_init = "flags[IsCondControl] = flags[IsControl];"
491
492 class RdRegOp(RegOp):
493 abstract = True
494 def __init__(self, dest, src1=None, dataSize="env.dataSize"):
495 if not src1:
496 src1 = dest
497 super(RdRegOp, self).__init__(dest, src1, \
498 "InstRegIndex(NUM_INTREGS)", None, dataSize)
499
500 class WrRegOp(RegOp):
501 abstract = True
502 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
503 super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
504 src1, src2, flags, dataSize)
505
506 class Add(FlagRegOp):
507 code = 'DestReg = merge(DestReg, result = (psrc1 + op2), dataSize);'
508 big_code = 'DestReg = result = (psrc1 + op2) & mask(dataSize * 8);'
509
510 class Or(LogicRegOp):
511 code = 'DestReg = merge(DestReg, result = (psrc1 | op2), dataSize);'
512 big_code = 'DestReg = result = (psrc1 | op2) & mask(dataSize * 8);'
513
514 class Adc(FlagRegOp):
515 code = '''
516 CCFlagBits flags = cfofBits;
517 DestReg = merge(DestReg, result = (psrc1 + op2 + flags.cf), dataSize);
518 '''
519 big_code = '''
520 CCFlagBits flags = cfofBits;
521 DestReg = result = (psrc1 + op2 + flags.cf) & mask(dataSize * 8);
522 '''
523
524 class Sbb(SubRegOp):
525 code = '''
526 CCFlagBits flags = cfofBits;
527 DestReg = merge(DestReg, result = (psrc1 - op2 - flags.cf), dataSize);
528 '''
529 big_code = '''
530 CCFlagBits flags = cfofBits;
531 DestReg = result = (psrc1 - op2 - flags.cf) & mask(dataSize * 8);
532 '''
533
534 class And(LogicRegOp):
535 code = 'DestReg = merge(DestReg, result = (psrc1 & op2), dataSize)'
536 big_code = 'DestReg = result = (psrc1 & op2) & mask(dataSize * 8)'
537
538 class Sub(SubRegOp):
539 code = 'DestReg = merge(DestReg, result = (psrc1 - op2), dataSize)'
540 big_code = 'DestReg = result = (psrc1 - op2) & mask(dataSize * 8)'
541
542 class Xor(LogicRegOp):
543 code = 'DestReg = merge(DestReg, result = (psrc1 ^ op2), dataSize)'
544 big_code = 'DestReg = result = (psrc1 ^ op2) & mask(dataSize * 8)'
545
546 class Mul1s(WrRegOp):
547 op_class = 'IntMultOp'
548
549 # Multiply two values Aa and Bb where Aa = A << p + a, then correct for
550 # negative operands.
551 # Aa * Bb
552 # = (A << p + a) * (B << p + b)
553 # = (A * B) << 2p + (A * b + a * B) << p + a * b
554 code = '''
555 ProdLow = psrc1 * op2;
556
557 int p = (dataSize * 8) / 2;
558 uint64_t A = bits(psrc1, 2 * p - 1, p);
559 uint64_t a = bits(psrc1, p - 1, 0);
560 uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p);
561 uint64_t b = bits<uint64_t>(op2, p - 1, 0);
562
563 uint64_t c1, c2; // Carry between place values.
564 uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B;
565
566 c1 = ab >> p;
567
568 // Be careful to avoid overflow if p is large.
569 if (p == 32) {
570 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
571 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
572 c2 >>= (p - 1);
573 } else {
574 c2 = (c1 + Ab + aB) >> p;
575 }
576
577 uint64_t hi = AB + c2;
578
579 if (bits(psrc1, dataSize * 8 - 1))
580 hi -= op2;
581 if (bits(op2, dataSize * 8 - 1))
582 hi -= psrc1;
583
584 ProdHi = hi;
585 '''
586 flag_code = '''
587 if ((-ProdHi & mask(dataSize * 8)) !=
588 bits(ProdLow, dataSize * 8 - 1)) {
589 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit));
590 PredecfBit = PredecfBit | (ext & ECFBit);
591 } else {
592 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
593 PredecfBit = PredecfBit & ~(ext & ECFBit);
594 }
595 '''
596
597 class Mul1u(WrRegOp):
598 op_class = 'IntMultOp'
599
600 # Multiply two values Aa and Bb where Aa = A << p + a.
601 # Aa * Bb
602 # = (A << p + a) * (B << p + b)
603 # = (A * B) << 2p + (A * b + a * B) << p + a * b
604 code = '''
605 ProdLow = psrc1 * op2;
606
607 int p = (dataSize * 8) / 2;
608 uint64_t A = bits(psrc1, 2 * p - 1, p);
609 uint64_t a = bits(psrc1, p - 1, 0);
610 uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p);
611 uint64_t b = bits<uint64_t>(op2, p - 1, 0);
612
613 uint64_t c1, c2; // Carry between place values.
614 uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B;
615
616 c1 = ab >> p;
617
618 // Be careful to avoid overflow if p is large.
619 if (p == 32) {
620 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
621 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
622 c2 >>= (p - 1);
623 } else {
624 c2 = (c1 + Ab + aB) >> p;
625 }
626
627 ProdHi = AB + c2;
628 '''
629 flag_code = '''
630 if (ProdHi) {
631 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit));
632 PredecfBit = PredecfBit | (ext & ECFBit);
633 } else {
634 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
635 PredecfBit = PredecfBit & ~(ext & ECFBit);
636 }
637 '''
638
639 class Mulel(RdRegOp):
640 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
641 big_code = 'DestReg = ProdLow & mask(dataSize * 8);'
642
643 class Muleh(RdRegOp):
644 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
645 if not src1:
646 src1 = dest
647 super(RdRegOp, self).__init__(dest, src1, \
648 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
649 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
650 big_code = 'DestReg = ProdHi & mask(dataSize * 8);'
651
652 # One or two bit divide
653 class Div1(WrRegOp):
654 op_class = 'IntDivOp'
655
656 code = '''
657 //These are temporaries so that modifying them later won't make
658 //the ISA parser think they're also sources.
659 uint64_t quotient = 0;
660 uint64_t remainder = psrc1;
661 //Similarly, this is a temporary so changing it doesn't make it
662 //a source.
663 uint64_t divisor = op2;
664 //This is a temporary just for consistency and clarity.
665 uint64_t dividend = remainder;
666 //Do the division.
667 if (divisor == 0) {
668 fault = std::make_shared<DivideError>();
669 } else {
670 divide(dividend, divisor, quotient, remainder);
671 //Record the final results.
672 Remainder = remainder;
673 Quotient = quotient;
674 Divisor = divisor;
675 }
676 '''
677
678 # Step divide
679 class Div2(RegOp):
680 op_class = 'IntDivOp'
681
682 divCode = '''
683 uint64_t dividend = Remainder;
684 uint64_t divisor = Divisor;
685 uint64_t quotient = Quotient;
686 uint64_t remainder = dividend;
687 int remaining = op2;
688 //If we overshot, do nothing. This lets us unrool division loops a
689 //little.
690 if (divisor == 0) {
691 fault = std::make_shared<DivideError>();
692 } else if (remaining) {
693 if (divisor & (ULL(1) << 63)) {
694 while (remaining && !(dividend & (ULL(1) << 63))) {
695 dividend = (dividend << 1) |
696 bits(SrcReg1, remaining - 1);
697 quotient <<= 1;
698 remaining--;
699 }
700 if (dividend & (ULL(1) << 63)) {
701 bool highBit = false;
702 if (dividend < divisor && remaining) {
703 highBit = true;
704 dividend = (dividend << 1) |
705 bits(SrcReg1, remaining - 1);
706 quotient <<= 1;
707 remaining--;
708 }
709 if (highBit || divisor <= dividend) {
710 quotient++;
711 dividend -= divisor;
712 }
713 }
714 remainder = dividend;
715 } else {
716 //Shift in bits from the low order portion of the dividend
717 while (dividend < divisor && remaining) {
718 dividend = (dividend << 1) |
719 bits(SrcReg1, remaining - 1);
720 quotient <<= 1;
721 remaining--;
722 }
723 remainder = dividend;
724 //Do the division.
725 divide(dividend, divisor, quotient, remainder);
726 }
727 }
728 //Keep track of how many bits there are still to pull in.
729 %s
730 //Record the final results
731 Remainder = remainder;
732 Quotient = quotient;
733 '''
734 code = divCode % "DestReg = merge(DestReg, remaining, dataSize);"
735 big_code = divCode % "DestReg = remaining & mask(dataSize * 8);"
736 flag_code = '''
737 if (remaining == 0)
738 PredezfBit = PredezfBit | (ext & EZFBit);
739 else
740 PredezfBit = PredezfBit & ~(ext & EZFBit);
741 '''
742
743 class Divq(RdRegOp):
744 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
745 big_code = 'DestReg = Quotient & mask(dataSize * 8);'
746
747 class Divr(RdRegOp):
748 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
749 big_code = 'DestReg = Remainder & mask(dataSize * 8);'
750
751 class Mov(CondRegOp):
752 code = 'DestReg = merge(SrcReg1, op2, dataSize)'
753 else_code = 'DestReg = DestReg;'
754
755 # Shift instructions
756
757 class Sll(RegOp):
758 code = '''
759 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
760 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
761 '''
762 big_code = '''
763 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
764 DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8);
765 '''
766 flag_code = '''
767 // If the shift amount is zero, no flags should be modified.
768 if (shiftAmt) {
769 //Zero out any flags we might modify. This way we only have to
770 //worry about setting them.
771 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
772 PredecfBit = PredecfBit & ~(ext & ECFBit);
773
774 int CFBits = 0;
775 //Figure out if we -would- set the CF bits if requested.
776 if (shiftAmt <= dataSize * 8 &&
777 bits(SrcReg1, dataSize * 8 - shiftAmt)) {
778 CFBits = 1;
779 }
780
781 //If some combination of the CF bits need to be set, set them.
782 if ((ext & (CFBit | ECFBit)) && CFBits) {
783 PredcfofBits = PredcfofBits | (ext & CFBit);
784 PredecfBit = PredecfBit | (ext & ECFBit);
785 }
786
787 //Figure out what the OF bit should be.
788 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
789 PredcfofBits = PredcfofBits | OFBit;
790
791 //Use the regular mechanisms to calculate the other flags.
792 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
793 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
794 DestReg, psrc1, op2);
795
796 PredezfBit = newFlags & EZFBit;
797 PreddfBit = newFlags & DFBit;
798 PredccFlagBits = newFlags & ccFlagMask;
799 }
800 '''
801
802 class Srl(RegOp):
803 # Because what happens to the bits shift -in- on a right shift
804 # is not defined in the C/C++ standard, we have to mask them out
805 # to be sure they're zero.
806 code = '''
807 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
808 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
809 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
810 '''
811 big_code = '''
812 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
813 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
814 DestReg = (psrc1 >> shiftAmt) & logicalMask;
815 '''
816 flag_code = '''
817 // If the shift amount is zero, no flags should be modified.
818 if (shiftAmt) {
819 //Zero out any flags we might modify. This way we only have to
820 //worry about setting them.
821 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
822 PredecfBit = PredecfBit & ~(ext & ECFBit);
823
824 //If some combination of the CF bits need to be set, set them.
825 if ((ext & (CFBit | ECFBit)) &&
826 shiftAmt <= dataSize * 8 &&
827 bits(SrcReg1, shiftAmt - 1)) {
828 PredcfofBits = PredcfofBits | (ext & CFBit);
829 PredecfBit = PredecfBit | (ext & ECFBit);
830 }
831
832 //Figure out what the OF bit should be.
833 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
834 PredcfofBits = PredcfofBits | OFBit;
835
836 //Use the regular mechanisms to calculate the other flags.
837 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
838 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
839 DestReg, psrc1, op2);
840
841 PredezfBit = newFlags & EZFBit;
842 PreddfBit = newFlags & DFBit;
843 PredccFlagBits = newFlags & ccFlagMask;
844 }
845 '''
846
847 class Sra(RegOp):
848 # Because what happens to the bits shift -in- on a right shift
849 # is not defined in the C/C++ standard, we have to sign extend
850 # them manually to be sure.
851 code = '''
852 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
853 uint64_t arithMask = (shiftAmt == 0) ? 0 :
854 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
855 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
856 '''
857 big_code = '''
858 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
859 uint64_t arithMask = (shiftAmt == 0) ? 0 :
860 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
861 DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8);
862 '''
863 flag_code = '''
864 // If the shift amount is zero, no flags should be modified.
865 if (shiftAmt) {
866 //Zero out any flags we might modify. This way we only have to
867 //worry about setting them.
868 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
869 PredecfBit = PredecfBit & ~(ext & ECFBit);
870
871 //If some combination of the CF bits need to be set, set them.
872 uint8_t effectiveShift =
873 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
874 if ((ext & (CFBit | ECFBit)) &&
875 bits(SrcReg1, effectiveShift - 1)) {
876 PredcfofBits = PredcfofBits | (ext & CFBit);
877 PredecfBit = PredecfBit | (ext & ECFBit);
878 }
879
880 //Use the regular mechanisms to calculate the other flags.
881 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
882 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
883 DestReg, psrc1, op2);
884
885 PredezfBit = newFlags & EZFBit;
886 PreddfBit = newFlags & DFBit;
887 PredccFlagBits = newFlags & ccFlagMask;
888 }
889 '''
890
891 class Ror(RegOp):
892 code = '''
893 uint8_t shiftAmt =
894 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
895 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
896 if (realShiftAmt) {
897 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
898 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
899 DestReg = merge(DestReg, top | bottom, dataSize);
900 } else
901 DestReg = merge(DestReg, DestReg, dataSize);
902 '''
903 flag_code = '''
904 // If the shift amount is zero, no flags should be modified.
905 if (shiftAmt) {
906 //Zero out any flags we might modify. This way we only have to
907 //worry about setting them.
908 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
909 PredecfBit = PredecfBit & ~(ext & ECFBit);
910
911 //Find the most and second most significant bits of the result.
912 int msb = bits(DestReg, dataSize * 8 - 1);
913 int smsb = bits(DestReg, dataSize * 8 - 2);
914 //If some combination of the CF bits need to be set, set them.
915 if ((ext & (CFBit | ECFBit)) && msb) {
916 PredcfofBits = PredcfofBits | (ext & CFBit);
917 PredecfBit = PredecfBit | (ext & ECFBit);
918 }
919
920 //Figure out what the OF bit should be.
921 if ((ext & OFBit) && (msb ^ smsb))
922 PredcfofBits = PredcfofBits | OFBit;
923
924 //Use the regular mechanisms to calculate the other flags.
925 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
926 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
927 DestReg, psrc1, op2);
928
929 PredezfBit = newFlags & EZFBit;
930 PreddfBit = newFlags & DFBit;
931 PredccFlagBits = newFlags & ccFlagMask;
932 }
933 '''
934
935 class Rcr(RegOp):
936 code = '''
937 uint8_t shiftAmt =
938 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
939 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
940 if (realShiftAmt) {
941 CCFlagBits flags = cfofBits;
942 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
943 if (realShiftAmt > 1)
944 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
945 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
946 DestReg = merge(DestReg, top | bottom, dataSize);
947 } else
948 DestReg = merge(DestReg, DestReg, dataSize);
949 '''
950 flag_code = '''
951 // If the shift amount is zero, no flags should be modified.
952 if (shiftAmt) {
953 int origCFBit = (cfofBits & CFBit) ? 1 : 0;
954 //Zero out any flags we might modify. This way we only have to
955 //worry about setting them.
956 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
957 PredecfBit = PredecfBit & ~(ext & ECFBit);
958
959 //Figure out what the OF bit should be.
960 if ((ext & OFBit) && (origCFBit ^
961 bits(SrcReg1, dataSize * 8 - 1))) {
962 PredcfofBits = PredcfofBits | OFBit;
963 }
964 //If some combination of the CF bits need to be set, set them.
965 if ((ext & (CFBit | ECFBit)) &&
966 (realShiftAmt == 0) ? origCFBit :
967 bits(SrcReg1, realShiftAmt - 1)) {
968 PredcfofBits = PredcfofBits | (ext & CFBit);
969 PredecfBit = PredecfBit | (ext & ECFBit);
970 }
971
972 //Use the regular mechanisms to calculate the other flags.
973 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
974 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
975 DestReg, psrc1, op2);
976
977 PredezfBit = newFlags & EZFBit;
978 PreddfBit = newFlags & DFBit;
979 PredccFlagBits = newFlags & ccFlagMask;
980 }
981 '''
982
983 class Rol(RegOp):
984 code = '''
985 uint8_t shiftAmt =
986 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
987 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
988 if (realShiftAmt) {
989 uint64_t top = psrc1 << realShiftAmt;
990 uint64_t bottom =
991 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
992 DestReg = merge(DestReg, top | bottom, dataSize);
993 } else
994 DestReg = merge(DestReg, DestReg, dataSize);
995 '''
996 flag_code = '''
997 // If the shift amount is zero, no flags should be modified.
998 if (shiftAmt) {
999 //Zero out any flags we might modify. This way we only have to
1000 //worry about setting them.
1001 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1002 PredecfBit = PredecfBit & ~(ext & ECFBit);
1003
1004 //The CF bits, if set, would be set to the lsb of the result.
1005 int lsb = DestReg & 0x1;
1006 int msb = bits(DestReg, dataSize * 8 - 1);
1007 //If some combination of the CF bits need to be set, set them.
1008 if ((ext & (CFBit | ECFBit)) && lsb) {
1009 PredcfofBits = PredcfofBits | (ext & CFBit);
1010 PredecfBit = PredecfBit | (ext & ECFBit);
1011 }
1012
1013 //Figure out what the OF bit should be.
1014 if ((ext & OFBit) && (msb ^ lsb))
1015 PredcfofBits = PredcfofBits | OFBit;
1016
1017 //Use the regular mechanisms to calculate the other flags.
1018 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1019 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1020 DestReg, psrc1, op2);
1021
1022 PredezfBit = newFlags & EZFBit;
1023 PreddfBit = newFlags & DFBit;
1024 PredccFlagBits = newFlags & ccFlagMask;
1025 }
1026 '''
1027
1028 class Rcl(RegOp):
1029 code = '''
1030 uint8_t shiftAmt =
1031 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
1032 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
1033 if (realShiftAmt) {
1034 CCFlagBits flags = cfofBits;
1035 uint64_t top = psrc1 << realShiftAmt;
1036 uint64_t bottom = flags.cf << (realShiftAmt - 1);
1037 if(shiftAmt > 1)
1038 bottom |=
1039 bits(psrc1, dataSize * 8 - 1,
1040 dataSize * 8 - realShiftAmt + 1);
1041 DestReg = merge(DestReg, top | bottom, dataSize);
1042 } else
1043 DestReg = merge(DestReg, DestReg, dataSize);
1044 '''
1045 flag_code = '''
1046 // If the shift amount is zero, no flags should be modified.
1047 if (shiftAmt) {
1048 int origCFBit = (cfofBits & CFBit) ? 1 : 0;
1049 //Zero out any flags we might modify. This way we only have to
1050 //worry about setting them.
1051 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1052 PredecfBit = PredecfBit & ~(ext & ECFBit);
1053
1054 int msb = bits(DestReg, dataSize * 8 - 1);
1055 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
1056 //If some combination of the CF bits need to be set, set them.
1057 if ((ext & (CFBit | ECFBit)) &&
1058 (realShiftAmt == 0) ? origCFBit : CFBits) {
1059 PredcfofBits = PredcfofBits | (ext & CFBit);
1060 PredecfBit = PredecfBit | (ext & ECFBit);
1061 }
1062
1063 //Figure out what the OF bit should be.
1064 if ((ext & OFBit) && (msb ^ CFBits))
1065 PredcfofBits = PredcfofBits | OFBit;
1066
1067 //Use the regular mechanisms to calculate the other flags.
1068 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1069 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1070 DestReg, psrc1, op2);
1071
1072 PredezfBit = newFlags & EZFBit;
1073 PreddfBit = newFlags & DFBit;
1074 PredccFlagBits = newFlags & ccFlagMask;
1075 }
1076 '''
1077
1078 class Sld(RegOp):
1079 sldCode = '''
1080 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
1081 uint8_t dataBits = dataSize * 8;
1082 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
1083 uint64_t result;
1084 if (realShiftAmt == 0) {
1085 result = psrc1;
1086 } else if (realShiftAmt < dataBits) {
1087 result = (psrc1 << realShiftAmt) |
1088 (DoubleBits >> (dataBits - realShiftAmt));
1089 } else {
1090 result = (DoubleBits << (realShiftAmt - dataBits)) |
1091 (psrc1 >> (2 * dataBits - realShiftAmt));
1092 }
1093 %s
1094 '''
1095 code = sldCode % "DestReg = merge(DestReg, result, dataSize);"
1096 big_code = sldCode % "DestReg = result & mask(dataSize * 8);"
1097 flag_code = '''
1098 // If the shift amount is zero, no flags should be modified.
1099 if (shiftAmt) {
1100 //Zero out any flags we might modify. This way we only have to
1101 //worry about setting them.
1102 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1103 PredecfBit = PredecfBit & ~(ext & ECFBit);
1104 int CFBits = 0;
1105
1106 //Figure out if we -would- set the CF bits if requested.
1107 if ((realShiftAmt == 0 &&
1108 bits(DoubleBits, 0)) ||
1109 (realShiftAmt <= dataBits &&
1110 bits(SrcReg1, dataBits - realShiftAmt)) ||
1111 (realShiftAmt > dataBits &&
1112 bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
1113 CFBits = 1;
1114 }
1115
1116 //If some combination of the CF bits need to be set, set them.
1117 if ((ext & (CFBit | ECFBit)) && CFBits) {
1118 PredcfofBits = PredcfofBits | (ext & CFBit);
1119 PredecfBit = PredecfBit | (ext & ECFBit);
1120 }
1121
1122 //Figure out what the OF bit should be.
1123 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
1124 bits(result, dataBits - 1)))
1125 PredcfofBits = PredcfofBits | OFBit;
1126
1127 //Use the regular mechanisms to calculate the other flags.
1128 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1129 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1130 DestReg, psrc1, op2);
1131
1132 PredezfBit = newFlags & EZFBit;
1133 PreddfBit = newFlags & DFBit;
1134 PredccFlagBits = newFlags & ccFlagMask;
1135 }
1136 '''
1137
1138 class Srd(RegOp):
1139 srdCode = '''
1140 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
1141 uint8_t dataBits = dataSize * 8;
1142 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
1143 uint64_t result;
1144 if (realShiftAmt == 0) {
1145 result = psrc1;
1146 } else if (realShiftAmt < dataBits) {
1147 // Because what happens to the bits shift -in- on a right
1148 // shift is not defined in the C/C++ standard, we have to
1149 // mask them out to be sure they're zero.
1150 uint64_t logicalMask = mask(dataBits - realShiftAmt);
1151 result = ((psrc1 >> realShiftAmt) & logicalMask) |
1152 (DoubleBits << (dataBits - realShiftAmt));
1153 } else {
1154 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
1155 result = ((DoubleBits >> (realShiftAmt - dataBits)) &
1156 logicalMask) |
1157 (psrc1 << (2 * dataBits - realShiftAmt));
1158 }
1159 %s
1160 '''
1161 code = srdCode % "DestReg = merge(DestReg, result, dataSize);"
1162 big_code = srdCode % "DestReg = result & mask(dataSize * 8);"
1163 flag_code = '''
1164 // If the shift amount is zero, no flags should be modified.
1165 if (shiftAmt) {
1166 //Zero out any flags we might modify. This way we only have to
1167 //worry about setting them.
1168 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit));
1169 PredecfBit = PredecfBit & ~(ext & ECFBit);
1170 int CFBits = 0;
1171
1172 //If some combination of the CF bits need to be set, set them.
1173 if ((realShiftAmt == 0 &&
1174 bits(DoubleBits, dataBits - 1)) ||
1175 (realShiftAmt <= dataBits &&
1176 bits(SrcReg1, realShiftAmt - 1)) ||
1177 (realShiftAmt > dataBits &&
1178 bits(DoubleBits, realShiftAmt - dataBits - 1))) {
1179 CFBits = 1;
1180 }
1181
1182 //If some combination of the CF bits need to be set, set them.
1183 if ((ext & (CFBit | ECFBit)) && CFBits) {
1184 PredcfofBits = PredcfofBits | (ext & CFBit);
1185 PredecfBit = PredecfBit | (ext & ECFBit);
1186 }
1187
1188 //Figure out what the OF bit should be.
1189 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
1190 bits(result, dataBits - 1)))
1191 PredcfofBits = PredcfofBits | OFBit;
1192
1193 //Use the regular mechanisms to calculate the other flags.
1194 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit |
1195 PredezfBit, ext & ~(CFBit | ECFBit | OFBit),
1196 DestReg, psrc1, op2);
1197
1198 PredezfBit = newFlags & EZFBit;
1199 PreddfBit = newFlags & DFBit;
1200 PredccFlagBits = newFlags & ccFlagMask;
1201 }
1202 '''
1203
1204 class Mdb(WrRegOp):
1205 code = 'DoubleBits = psrc1 ^ op2;'
1206
1207 class Wrip(WrRegOp, CondRegOp):
1208 code = 'NRIP = psrc1 + sop2 + CSBase;'
1209 else_code = "NRIP = NRIP;"
1210
1211 class Wruflags(WrRegOp):
1212 code = '''
1213 uint64_t newFlags = psrc1 ^ op2;
1214 cfofBits = newFlags & cfofMask;
1215 ecfBit = newFlags & ECFBit;
1216 ezfBit = newFlags & EZFBit;
1217 dfBit = newFlags & DFBit;
1218 ccFlagBits = newFlags & ccFlagMask;
1219 '''
1220
1221 class Wrflags(WrRegOp):
1222 code = '''
1223 MiscReg newFlags = psrc1 ^ op2;
1224 MiscReg userFlagMask = 0xDD5;
1225
1226 // Get only the user flags
1227 ccFlagBits = newFlags & ccFlagMask;
1228 dfBit = newFlags & DFBit;
1229 cfofBits = newFlags & cfofMask;
1230 ecfBit = 0;
1231 ezfBit = 0;
1232
1233 // Get everything else
1234 nccFlagBits = newFlags & ~userFlagMask;
1235 '''
1236
1237 class Rdip(RdRegOp):
1238 code = 'DestReg = NRIP - CSBase;'
1239
1240 class Ruflags(RdRegOp):
1241 code = 'DestReg = ccFlagBits | cfofBits | dfBit | ecfBit | ezfBit;'
1242
1243 class Rflags(RdRegOp):
1244 code = '''
1245 DestReg = ccFlagBits | cfofBits | dfBit |
1246 ecfBit | ezfBit | nccFlagBits;
1247 '''
1248
1249 class Ruflag(RegOp):
1250 code = '''
1251 int flag = bits(ccFlagBits | cfofBits | dfBit |
1252 ecfBit | ezfBit, imm8);
1253 DestReg = merge(DestReg, flag, dataSize);
1254 ezfBit = (flag == 0) ? EZFBit : 0;
1255 '''
1256
1257 big_code = '''
1258 int flag = bits(ccFlagBits | cfofBits | dfBit |
1259 ecfBit | ezfBit, imm8);
1260 DestReg = flag & mask(dataSize * 8);
1261 ezfBit = (flag == 0) ? EZFBit : 0;
1262 '''
1263
1264 def __init__(self, dest, imm, flags=None, \
1265 dataSize="env.dataSize"):
1266 super(Ruflag, self).__init__(dest, \
1267 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1268
1269 class Rflag(RegOp):
1270 code = '''
1271 MiscReg flagMask = 0x3F7FDD5;
1272 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit |
1273 ecfBit | ezfBit) & flagMask;
1274
1275 int flag = bits(flags, imm8);
1276 DestReg = merge(DestReg, flag, dataSize);
1277 ezfBit = (flag == 0) ? EZFBit : 0;
1278 '''
1279
1280 big_code = '''
1281 MiscReg flagMask = 0x3F7FDD5;
1282 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit |
1283 ecfBit | ezfBit) & flagMask;
1284
1285 int flag = bits(flags, imm8);
1286 DestReg = flag & mask(dataSize * 8);
1287 ezfBit = (flag == 0) ? EZFBit : 0;
1288 '''
1289
1290 def __init__(self, dest, imm, flags=None, \
1291 dataSize="env.dataSize"):
1292 super(Rflag, self).__init__(dest, \
1293 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1294
1295 class Sext(RegOp):
1296 code = '''
1297 IntReg val = psrc1;
1298 // Mask the bit position so that it wraps.
1299 int bitPos = op2 & (dataSize * 8 - 1);
1300 int sign_bit = bits(val, bitPos, bitPos);
1301 uint64_t maskVal = mask(bitPos+1);
1302 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1303 DestReg = merge(DestReg, val, dataSize);
1304 '''
1305
1306 big_code = '''
1307 IntReg val = psrc1;
1308 // Mask the bit position so that it wraps.
1309 int bitPos = op2 & (dataSize * 8 - 1);
1310 int sign_bit = bits(val, bitPos, bitPos);
1311 uint64_t maskVal = mask(bitPos+1);
1312 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1313 DestReg = val & mask(dataSize * 8);
1314 '''
1315
1316 flag_code = '''
1317 if (!sign_bit) {
1318 PredccFlagBits = PredccFlagBits & ~(ext & (ZFBit));
1319 PredcfofBits = PredcfofBits & ~(ext & (CFBit));
1320 PredecfBit = PredecfBit & ~(ext & ECFBit);
1321 PredezfBit = PredezfBit & ~(ext & EZFBit);
1322 } else {
1323 PredccFlagBits = PredccFlagBits | (ext & (ZFBit));
1324 PredcfofBits = PredcfofBits | (ext & (CFBit));
1325 PredecfBit = PredecfBit | (ext & ECFBit);
1326 PredezfBit = PredezfBit | (ext & EZFBit);
1327 }
1328 '''
1329
1330 class Zext(RegOp):
1331 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1332 big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);'
1333
1334 class Rddr(RegOp):
1335 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1336 super(Rddr, self).__init__(dest, \
1337 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1338 rdrCode = '''
1339 CR4 cr4 = CR4Op;
1340 DR7 dr7 = DR7Op;
1341 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1342 fault = std::make_shared<InvalidOpcode>();
1343 } else if (dr7.gd) {
1344 fault = std::make_shared<DebugException>();
1345 } else {
1346 %s
1347 }
1348 '''
1349 code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);"
1350 big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);"
1351
1352 class Wrdr(RegOp):
1353 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1354 super(Wrdr, self).__init__(dest, \
1355 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1356 code = '''
1357 CR4 cr4 = CR4Op;
1358 DR7 dr7 = DR7Op;
1359 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1360 fault = std::make_shared<InvalidOpcode>();
1361 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1362 machInst.mode.mode == LongMode) {
1363 fault = std::make_shared<GeneralProtection>(0);
1364 } else if (dr7.gd) {
1365 fault = std::make_shared<DebugException>();
1366 } else {
1367 DebugDest = psrc1;
1368 }
1369 '''
1370
1371 class Rdcr(RegOp):
1372 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1373 super(Rdcr, self).__init__(dest, \
1374 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1375 rdcrCode = '''
1376 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1377 fault = std::make_shared<InvalidOpcode>();
1378 } else {
1379 %s
1380 }
1381 '''
1382 code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);"
1383 big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);"
1384
1385 class Wrcr(RegOp):
1386 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1387 super(Wrcr, self).__init__(dest, \
1388 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1389 code = '''
1390 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1391 fault = std::make_shared<InvalidOpcode>();
1392 } else {
1393 // There are *s in the line below so it doesn't confuse the
1394 // parser. They may be unnecessary.
1395 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1396 MiscReg newVal = psrc1;
1397
1398 // Check for any modifications that would cause a fault.
1399 switch(dest) {
1400 case 0:
1401 {
1402 Efer efer = EferOp;
1403 CR0 cr0 = newVal;
1404 CR4 oldCr4 = CR4Op;
1405 if (bits(newVal, 63, 32) ||
1406 (!cr0.pe && cr0.pg) ||
1407 (!cr0.cd && cr0.nw) ||
1408 (cr0.pg && efer.lme && !oldCr4.pae))
1409 fault = std::make_shared<GeneralProtection>(0);
1410 }
1411 break;
1412 case 2:
1413 break;
1414 case 3:
1415 break;
1416 case 4:
1417 {
1418 CR4 cr4 = newVal;
1419 // PAE can't be disabled in long mode.
1420 if (bits(newVal, 63, 11) ||
1421 (machInst.mode.mode == LongMode && !cr4.pae))
1422 fault = std::make_shared<GeneralProtection>(0);
1423 }
1424 break;
1425 case 8:
1426 {
1427 if (bits(newVal, 63, 4))
1428 fault = std::make_shared<GeneralProtection>(0);
1429 }
1430 break;
1430 default:
1431 fault = std::make_shared<GenericISA::M5PanicFault>(
1432 "Unrecognized control register %d.\\n", dest);
1433 }
1434 ControlDest = newVal;
1435 }
1436 '''
1437
1438 # Microops for manipulating segmentation registers
1439 class SegOp(CondRegOp):
1440 abstract = True
1441 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1442 super(SegOp, self).__init__(dest, \
1443 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1444
1445 class Wrbase(SegOp):
1446 code = '''
1447 SegBaseDest = psrc1;
1448 '''
1449
1450 class Wrlimit(SegOp):
1451 code = '''
1452 SegLimitDest = psrc1;
1453 '''
1454
1455 class Wrsel(SegOp):
1456 code = '''
1457 SegSelDest = psrc1;
1458 '''
1459
1460 class WrAttr(SegOp):
1461 code = '''
1462 SegAttrDest = psrc1;
1463 '''
1464
1465 class Rdbase(SegOp):
1466 code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);'
1467 big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);'
1468
1469 class Rdlimit(SegOp):
1470 code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);'
1471 big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);'
1472
1473 class RdAttr(SegOp):
1474 code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);'
1475 big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);'
1476
1477 class Rdsel(SegOp):
1478 code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);'
1479 big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);'
1480
1481 class Rdval(RegOp):
1482 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1483 super(Rdval, self).__init__(dest, src1, \
1484 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1485 code = '''
1486 DestReg = MiscRegSrc1;
1487 '''
1488
1489 class Wrval(RegOp):
1490 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1491 super(Wrval, self).__init__(dest, src1, \
1492 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1493 code = '''
1494 MiscRegDest = SrcReg1;
1495 '''
1496
1497 class Chks(RegOp):
1498 def __init__(self, dest, src1, src2=0,
1499 flags=None, dataSize="env.dataSize"):
1500 super(Chks, self).__init__(dest,
1501 src1, src2, flags, dataSize)
1502 code = '''
1503 // The selector is in source 1 and can be at most 16 bits.
1504 SegSelector selector = DestReg;
1505 SegDescriptor desc = SrcReg1;
1506 HandyM5Reg m5reg = M5Reg;
1507
1508 switch (imm8)
1509 {
1510 case SegNoCheck:
1511 break;
1512 case SegCSCheck:
1513 // Make sure it's the right type
1514 if (desc.s == 0 || desc.type.codeOrData != 1) {
1515 fault = std::make_shared<GeneralProtection>(0);
1516 } else if (m5reg.cpl != desc.dpl) {
1517 fault = std::make_shared<GeneralProtection>(0);
1518 }
1519 break;
1520 case SegCallGateCheck:
1521 fault = std::make_shared<GenericISA::M5PanicFault>(
1522 "CS checks for far "
1523 "calls/jumps through call gates not implemented.\\n");
1524 break;
1525 case SegSoftIntGateCheck:
1526 // Check permissions.
1527 if (desc.dpl < m5reg.cpl) {
1528 fault = std::make_shared<GeneralProtection>(selector);
1529 break;
1530 }
1431 default:
1432 fault = std::make_shared<GenericISA::M5PanicFault>(
1433 "Unrecognized control register %d.\\n", dest);
1434 }
1435 ControlDest = newVal;
1436 }
1437 '''
1438
1439 # Microops for manipulating segmentation registers
1440 class SegOp(CondRegOp):
1441 abstract = True
1442 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1443 super(SegOp, self).__init__(dest, \
1444 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1445
1446 class Wrbase(SegOp):
1447 code = '''
1448 SegBaseDest = psrc1;
1449 '''
1450
1451 class Wrlimit(SegOp):
1452 code = '''
1453 SegLimitDest = psrc1;
1454 '''
1455
1456 class Wrsel(SegOp):
1457 code = '''
1458 SegSelDest = psrc1;
1459 '''
1460
1461 class WrAttr(SegOp):
1462 code = '''
1463 SegAttrDest = psrc1;
1464 '''
1465
1466 class Rdbase(SegOp):
1467 code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);'
1468 big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);'
1469
1470 class Rdlimit(SegOp):
1471 code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);'
1472 big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);'
1473
1474 class RdAttr(SegOp):
1475 code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);'
1476 big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);'
1477
1478 class Rdsel(SegOp):
1479 code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);'
1480 big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);'
1481
1482 class Rdval(RegOp):
1483 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1484 super(Rdval, self).__init__(dest, src1, \
1485 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1486 code = '''
1487 DestReg = MiscRegSrc1;
1488 '''
1489
1490 class Wrval(RegOp):
1491 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1492 super(Wrval, self).__init__(dest, src1, \
1493 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1494 code = '''
1495 MiscRegDest = SrcReg1;
1496 '''
1497
1498 class Chks(RegOp):
1499 def __init__(self, dest, src1, src2=0,
1500 flags=None, dataSize="env.dataSize"):
1501 super(Chks, self).__init__(dest,
1502 src1, src2, flags, dataSize)
1503 code = '''
1504 // The selector is in source 1 and can be at most 16 bits.
1505 SegSelector selector = DestReg;
1506 SegDescriptor desc = SrcReg1;
1507 HandyM5Reg m5reg = M5Reg;
1508
1509 switch (imm8)
1510 {
1511 case SegNoCheck:
1512 break;
1513 case SegCSCheck:
1514 // Make sure it's the right type
1515 if (desc.s == 0 || desc.type.codeOrData != 1) {
1516 fault = std::make_shared<GeneralProtection>(0);
1517 } else if (m5reg.cpl != desc.dpl) {
1518 fault = std::make_shared<GeneralProtection>(0);
1519 }
1520 break;
1521 case SegCallGateCheck:
1522 fault = std::make_shared<GenericISA::M5PanicFault>(
1523 "CS checks for far "
1524 "calls/jumps through call gates not implemented.\\n");
1525 break;
1526 case SegSoftIntGateCheck:
1527 // Check permissions.
1528 if (desc.dpl < m5reg.cpl) {
1529 fault = std::make_shared<GeneralProtection>(selector);
1530 break;
1531 }
1531 // Fall through on purpose
1532 M5_FALLTHROUGH;
1532 case SegIntGateCheck:
1533 // Make sure the gate's the right type.
1534 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1535 ((desc.type & 0x6) != 0x6)) {
1536 fault = std::make_shared<GeneralProtection>(0);
1537 }
1538 break;
1539 case SegSSCheck:
1540 if (selector.si || selector.ti) {
1541 if (!desc.p) {
1542 fault = std::make_shared<StackFault>(selector);
1543 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 &&
1544 desc.type.w) ||
1545 (desc.dpl != m5reg.cpl) ||
1546 (selector.rpl != m5reg.cpl)) {
1547 fault = std::make_shared<GeneralProtection>(selector);
1548 }
1549 } else if (m5reg.submode != SixtyFourBitMode ||
1550 m5reg.cpl == 3) {
1551 fault = std::make_shared<GeneralProtection>(selector);
1552 }
1553 break;
1554 case SegIretCheck:
1555 {
1556 if ((!selector.si && !selector.ti) ||
1557 (selector.rpl < m5reg.cpl) ||
1558 !(desc.s == 1 && desc.type.codeOrData == 1) ||
1559 (!desc.type.c && desc.dpl != selector.rpl) ||
1560 (desc.type.c && desc.dpl > selector.rpl)) {
1561 fault = std::make_shared<GeneralProtection>(selector);
1562 } else if (!desc.p) {
1563 fault = std::make_shared<SegmentNotPresent>(selector);
1564 }
1565 break;
1566 }
1567 case SegIntCSCheck:
1568 if (m5reg.mode == LongMode) {
1569 if (desc.l != 1 || desc.d != 0) {
1570 fault = std::make_shared<GeneralProtection>(selector);
1571 }
1572 } else {
1573 fault = std::make_shared<GenericISA::M5PanicFault>(
1574 "Interrupt CS "
1575 "checks not implemented in legacy mode.\\n");
1576 }
1577 break;
1578 case SegTRCheck:
1579 if (!selector.si || selector.ti) {
1580 fault = std::make_shared<GeneralProtection>(selector);
1581 }
1582 break;
1583 case SegTSSCheck:
1584 if (!desc.p) {
1585 fault = std::make_shared<SegmentNotPresent>(selector);
1586 } else if (!(desc.type == 0x9 ||
1587 (desc.type == 1 &&
1588 m5reg.mode != LongMode))) {
1589 fault = std::make_shared<GeneralProtection>(selector);
1590 }
1591 break;
1592 case SegInGDTCheck:
1593 if (selector.ti) {
1594 fault = std::make_shared<GeneralProtection>(selector);
1595 }
1596 break;
1597 case SegLDTCheck:
1598 if (!desc.p) {
1599 fault = std::make_shared<SegmentNotPresent>(selector);
1600 } else if (desc.type != 0x2) {
1601 fault = std::make_shared<GeneralProtection>(selector);
1602 }
1603 break;
1604 default:
1605 fault = std::make_shared<GenericISA::M5PanicFault>(
1606 "Undefined segment check type.\\n");
1607 }
1608 '''
1609 flag_code = '''
1610 // Check for a NULL selector and set ZF,EZF appropriately.
1611 PredccFlagBits = PredccFlagBits & ~(ext & ZFBit);
1612 PredezfBit = PredezfBit & ~(ext & EZFBit);
1613
1614 if (!selector.si && !selector.ti) {
1615 PredccFlagBits = PredccFlagBits | (ext & ZFBit);
1616 PredezfBit = PredezfBit | (ext & EZFBit);
1617 }
1618 '''
1619
1620 class Wrdh(RegOp):
1621 code = '''
1622 SegDescriptor desc = SrcReg1;
1623
1624 uint64_t target = bits(SrcReg2, 31, 0) << 32;
1625 switch(desc.type) {
1626 case LDT64:
1627 case AvailableTSS64:
1628 case BusyTSS64:
1629 replaceBits(target, 23, 0, desc.baseLow);
1630 replaceBits(target, 31, 24, desc.baseHigh);
1631 break;
1632 case CallGate64:
1633 case IntGate64:
1634 case TrapGate64:
1635 replaceBits(target, 15, 0, bits(desc, 15, 0));
1636 replaceBits(target, 31, 16, bits(desc, 63, 48));
1637 break;
1638 default:
1639 fault = std::make_shared<GenericISA::M5PanicFault>(
1640 "Wrdh used with wrong descriptor type!\\n");
1641 }
1642 DestReg = target;
1643 '''
1644
1645 class Wrtsc(WrRegOp):
1646 code = '''
1647 TscOp = psrc1;
1648 '''
1649
1650 class Rdtsc(RdRegOp):
1651 code = '''
1652 DestReg = TscOp;
1653 '''
1654
1655 class Rdm5reg(RdRegOp):
1656 code = '''
1657 DestReg = M5Reg;
1658 '''
1659
1660 class Wrdl(RegOp):
1661 code = '''
1662 SegDescriptor desc = SrcReg1;
1663 SegSelector selector = SrcReg2;
1664 // This while loop is so we can use break statements in the code
1665 // below to skip the rest of this section without a bunch of
1666 // nesting.
1667 while (true) {
1668 if (selector.si || selector.ti) {
1669 if (!desc.p) {
1670 fault = std::make_shared<GenericISA::M5PanicFault>(
1671 "Segment not present.\\n");
1672 break;
1673 }
1674 SegAttr attr = 0;
1675 attr.dpl = desc.dpl;
1676 attr.unusable = 0;
1677 attr.defaultSize = desc.d;
1678 attr.longMode = desc.l;
1679 attr.avl = desc.avl;
1680 attr.granularity = desc.g;
1681 attr.present = desc.p;
1682 attr.system = desc.s;
1683 attr.type = desc.type;
1684 if (!desc.s) {
1685 // The expand down bit happens to be set for gates.
1686 if (desc.type.e) {
1687 fault = std::make_shared<GenericISA::M5PanicFault>(
1688 "Gate descriptor encountered.\\n");
1689 break;
1690 }
1691 attr.readable = 1;
1692 attr.writable = 1;
1693 attr.expandDown = 0;
1694 } else {
1695 if (desc.type.codeOrData) {
1696 attr.expandDown = 0;
1697 attr.readable = desc.type.r;
1698 attr.writable = 0;
1699 } else {
1700 attr.expandDown = desc.type.e;
1701 attr.readable = 1;
1702 attr.writable = desc.type.w;
1703 }
1704 }
1705 Addr base = desc.baseLow | (desc.baseHigh << 24);
1706 Addr limit = desc.limitLow | (desc.limitHigh << 16);
1707 if (desc.g)
1708 limit = (limit << 12) | mask(12);
1709 SegBaseDest = base;
1710 SegLimitDest = limit;
1711 SegAttrDest = attr;
1712 } else {
1713 SegBaseDest = SegBaseDest;
1714 SegLimitDest = SegLimitDest;
1715 SegAttrDest = SegAttrDest;
1716 }
1717 break;
1718 }
1719 '''
1720
1721 class Wrxftw(WrRegOp):
1722 def __init__(self, src1, **kwargs):
1723 super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \
1724 **kwargs)
1725
1726 code = '''
1727 FTW = X86ISA::convX87XTagsToTags(SrcReg1);
1728 '''
1729
1730 class Rdxftw(RdRegOp):
1731 code = '''
1732 DestReg = X86ISA::convX87TagsToXTags(FTW);
1733 '''
1734}};
1533 case SegIntGateCheck:
1534 // Make sure the gate's the right type.
1535 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1536 ((desc.type & 0x6) != 0x6)) {
1537 fault = std::make_shared<GeneralProtection>(0);
1538 }
1539 break;
1540 case SegSSCheck:
1541 if (selector.si || selector.ti) {
1542 if (!desc.p) {
1543 fault = std::make_shared<StackFault>(selector);
1544 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 &&
1545 desc.type.w) ||
1546 (desc.dpl != m5reg.cpl) ||
1547 (selector.rpl != m5reg.cpl)) {
1548 fault = std::make_shared<GeneralProtection>(selector);
1549 }
1550 } else if (m5reg.submode != SixtyFourBitMode ||
1551 m5reg.cpl == 3) {
1552 fault = std::make_shared<GeneralProtection>(selector);
1553 }
1554 break;
1555 case SegIretCheck:
1556 {
1557 if ((!selector.si && !selector.ti) ||
1558 (selector.rpl < m5reg.cpl) ||
1559 !(desc.s == 1 && desc.type.codeOrData == 1) ||
1560 (!desc.type.c && desc.dpl != selector.rpl) ||
1561 (desc.type.c && desc.dpl > selector.rpl)) {
1562 fault = std::make_shared<GeneralProtection>(selector);
1563 } else if (!desc.p) {
1564 fault = std::make_shared<SegmentNotPresent>(selector);
1565 }
1566 break;
1567 }
1568 case SegIntCSCheck:
1569 if (m5reg.mode == LongMode) {
1570 if (desc.l != 1 || desc.d != 0) {
1571 fault = std::make_shared<GeneralProtection>(selector);
1572 }
1573 } else {
1574 fault = std::make_shared<GenericISA::M5PanicFault>(
1575 "Interrupt CS "
1576 "checks not implemented in legacy mode.\\n");
1577 }
1578 break;
1579 case SegTRCheck:
1580 if (!selector.si || selector.ti) {
1581 fault = std::make_shared<GeneralProtection>(selector);
1582 }
1583 break;
1584 case SegTSSCheck:
1585 if (!desc.p) {
1586 fault = std::make_shared<SegmentNotPresent>(selector);
1587 } else if (!(desc.type == 0x9 ||
1588 (desc.type == 1 &&
1589 m5reg.mode != LongMode))) {
1590 fault = std::make_shared<GeneralProtection>(selector);
1591 }
1592 break;
1593 case SegInGDTCheck:
1594 if (selector.ti) {
1595 fault = std::make_shared<GeneralProtection>(selector);
1596 }
1597 break;
1598 case SegLDTCheck:
1599 if (!desc.p) {
1600 fault = std::make_shared<SegmentNotPresent>(selector);
1601 } else if (desc.type != 0x2) {
1602 fault = std::make_shared<GeneralProtection>(selector);
1603 }
1604 break;
1605 default:
1606 fault = std::make_shared<GenericISA::M5PanicFault>(
1607 "Undefined segment check type.\\n");
1608 }
1609 '''
1610 flag_code = '''
1611 // Check for a NULL selector and set ZF,EZF appropriately.
1612 PredccFlagBits = PredccFlagBits & ~(ext & ZFBit);
1613 PredezfBit = PredezfBit & ~(ext & EZFBit);
1614
1615 if (!selector.si && !selector.ti) {
1616 PredccFlagBits = PredccFlagBits | (ext & ZFBit);
1617 PredezfBit = PredezfBit | (ext & EZFBit);
1618 }
1619 '''
1620
1621 class Wrdh(RegOp):
1622 code = '''
1623 SegDescriptor desc = SrcReg1;
1624
1625 uint64_t target = bits(SrcReg2, 31, 0) << 32;
1626 switch(desc.type) {
1627 case LDT64:
1628 case AvailableTSS64:
1629 case BusyTSS64:
1630 replaceBits(target, 23, 0, desc.baseLow);
1631 replaceBits(target, 31, 24, desc.baseHigh);
1632 break;
1633 case CallGate64:
1634 case IntGate64:
1635 case TrapGate64:
1636 replaceBits(target, 15, 0, bits(desc, 15, 0));
1637 replaceBits(target, 31, 16, bits(desc, 63, 48));
1638 break;
1639 default:
1640 fault = std::make_shared<GenericISA::M5PanicFault>(
1641 "Wrdh used with wrong descriptor type!\\n");
1642 }
1643 DestReg = target;
1644 '''
1645
1646 class Wrtsc(WrRegOp):
1647 code = '''
1648 TscOp = psrc1;
1649 '''
1650
1651 class Rdtsc(RdRegOp):
1652 code = '''
1653 DestReg = TscOp;
1654 '''
1655
1656 class Rdm5reg(RdRegOp):
1657 code = '''
1658 DestReg = M5Reg;
1659 '''
1660
1661 class Wrdl(RegOp):
1662 code = '''
1663 SegDescriptor desc = SrcReg1;
1664 SegSelector selector = SrcReg2;
1665 // This while loop is so we can use break statements in the code
1666 // below to skip the rest of this section without a bunch of
1667 // nesting.
1668 while (true) {
1669 if (selector.si || selector.ti) {
1670 if (!desc.p) {
1671 fault = std::make_shared<GenericISA::M5PanicFault>(
1672 "Segment not present.\\n");
1673 break;
1674 }
1675 SegAttr attr = 0;
1676 attr.dpl = desc.dpl;
1677 attr.unusable = 0;
1678 attr.defaultSize = desc.d;
1679 attr.longMode = desc.l;
1680 attr.avl = desc.avl;
1681 attr.granularity = desc.g;
1682 attr.present = desc.p;
1683 attr.system = desc.s;
1684 attr.type = desc.type;
1685 if (!desc.s) {
1686 // The expand down bit happens to be set for gates.
1687 if (desc.type.e) {
1688 fault = std::make_shared<GenericISA::M5PanicFault>(
1689 "Gate descriptor encountered.\\n");
1690 break;
1691 }
1692 attr.readable = 1;
1693 attr.writable = 1;
1694 attr.expandDown = 0;
1695 } else {
1696 if (desc.type.codeOrData) {
1697 attr.expandDown = 0;
1698 attr.readable = desc.type.r;
1699 attr.writable = 0;
1700 } else {
1701 attr.expandDown = desc.type.e;
1702 attr.readable = 1;
1703 attr.writable = desc.type.w;
1704 }
1705 }
1706 Addr base = desc.baseLow | (desc.baseHigh << 24);
1707 Addr limit = desc.limitLow | (desc.limitHigh << 16);
1708 if (desc.g)
1709 limit = (limit << 12) | mask(12);
1710 SegBaseDest = base;
1711 SegLimitDest = limit;
1712 SegAttrDest = attr;
1713 } else {
1714 SegBaseDest = SegBaseDest;
1715 SegLimitDest = SegLimitDest;
1716 SegAttrDest = SegAttrDest;
1717 }
1718 break;
1719 }
1720 '''
1721
1722 class Wrxftw(WrRegOp):
1723 def __init__(self, src1, **kwargs):
1724 super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \
1725 **kwargs)
1726
1727 code = '''
1728 FTW = X86ISA::convX87XTagsToTags(SrcReg1);
1729 '''
1730
1731 class Rdxftw(RdRegOp):
1732 code = '''
1733 DestReg = X86ISA::convX87TagsToXTags(FTW);
1734 '''
1735}};