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