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