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