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