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