regop.isa (5062:4c98f8cdcc11) regop.isa (5063:8eb72b1bd3c6)
1// Copyright (c) 2007 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,
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,
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,
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,
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,
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,
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,
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,
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
230let {{
231 # Make these empty strings so that concatenating onto
232 # them will always work.
233 header_output = ""
234 decoder_output = ""
235 exec_output = ""
236
237 immTemplates = (
238 MicroRegOpImmDeclare,
239 MicroRegOpImmConstructor,
240 MicroRegOpImmExecute)
241
242 regTemplates = (
243 MicroRegOpDeclare,
244 MicroRegOpConstructor,
245 MicroRegOpExecute)
246
247 class RegOpMeta(type):
248 def buildCppClasses(self, name, Name, suffix, \
249 code, flag_code, cond_check, else_code):
250
251 # Globals to stick the output in
252 global header_output
253 global decoder_output
254 global exec_output
255
256 # Stick all the code together so it can be searched at once
257 allCode = "|".join((code, flag_code, cond_check, else_code))
258
259 # If op2 is used anywhere, make register and immediate versions
260 # of this code.
261 matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
262 match = matcher.search(allCode)
263 if match:
264 typeQual = ""
265 if match.group("typeQual"):
266 typeQual = match.group("typeQual")
267 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
268 self.buildCppClasses(name, Name, suffix,
269 matcher.sub(src2_name, code),
270 matcher.sub(src2_name, flag_code),
271 matcher.sub(src2_name, cond_check),
272 matcher.sub(src2_name, else_code))
273 self.buildCppClasses(name + "i", Name, suffix + "Imm",
274 matcher.sub("imm8", code),
275 matcher.sub("imm8", flag_code),
276 matcher.sub("imm8", cond_check),
277 matcher.sub("imm8", else_code))
278 return
279
280 # If there's something optional to do with flags, generate
281 # a version without it and fix up this version to use it.
282 if flag_code is not "" or cond_check is not "true":
283 self.buildCppClasses(name, Name, suffix,
284 code, "", "true", else_code)
285 suffix = "Flags" + suffix
286
287 # If psrc1 or psrc2 is used, we need to actually insert code to
288 # compute it.
289 matcher = re.compile("(?<!\w)psrc1(?!\w)")
290 if matcher.search(allCode):
291 code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code
292 matcher = re.compile("(?<!\w)psrc2(?!\w)")
293 if matcher.search(allCode):
294 code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code
295 # Also make available versions which do sign extension
296 matcher = re.compile("(?<!\w)spsrc1(?!\w)")
297 if matcher.search(allCode):
298 code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code
299 matcher = re.compile("(?<!\w)spsrc2(?!\w)")
300 if matcher.search(allCode):
301 code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code
302
303 base = "X86ISA::RegOp"
304
305 # If imm8 shows up in the code, use the immediate templates, if
306 # not, hopefully the register ones will be correct.
307 templates = regTemplates
308 matcher = re.compile("(?<!\w)imm8(?!\w)")
309 if matcher.search(allCode):
310 base += "Imm"
311 templates = immTemplates
312
313 # Get everything ready for the substitution
314 iop = InstObjParams(name, Name + suffix, base,
315 {"code" : code,
316 "flag_code" : flag_code,
317 "cond_check" : cond_check,
318 "else_code" : else_code})
319
320 # Generate the actual code (finally!)
321 header_output += templates[0].subst(iop)
322 decoder_output += templates[1].subst(iop)
323 exec_output += templates[2].subst(iop)
324
325
326 def __new__(mcls, Name, bases, dict):
327 abstract = False
328 name = Name.lower()
329 if "abstract" in dict:
330 abstract = dict['abstract']
331 del dict['abstract']
332
333 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
334 if not abstract:
335 cls.className = Name
336 cls.base_mnemonic = name
337 code = cls.code
338 flag_code = cls.flag_code
339 cond_check = cls.cond_check
340 else_code = cls.else_code
341
342 # Set up the C++ classes
343 mcls.buildCppClasses(cls, name, Name, "",
344 code, flag_code, cond_check, else_code)
345
346 # Hook into the microassembler dict
347 global microopClasses
348 microopClasses[name] = cls
349
350 allCode = "|".join((code, flag_code, cond_check, else_code))
351
352 # If op2 is used anywhere, make register and immediate versions
353 # of this code.
354 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
355 if matcher.search(allCode):
356 microopClasses[name + 'i'] = cls
357 return cls
358
359
360 class RegOp(X86Microop):
361 __metaclass__ = RegOpMeta
362 # This class itself doesn't act as a microop
363 abstract = True
364
365 # Default template parameter values
366 flag_code = ""
367 cond_check = "true"
368 else_code = ";"
369
370 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
371 self.dest = dest
372 self.src1 = src1
373 self.op2 = op2
374 self.flags = flags
375 self.dataSize = dataSize
376 if flags is None:
377 self.ext = 0
378 else:
379 if not isinstance(flags, (list, tuple)):
380 raise Exception, "flags must be a list or tuple of flags"
381 self.ext = " | ".join(flags)
382 self.className += "Flags"
383
384 def getAllocator(self, *microFlags):
385 className = self.className
386 if self.mnemonic == self.base_mnemonic + 'i':
387 className += "Imm"
388 allocator = '''new %(class_name)s(machInst, mnemonic
389 %(flags)s, %(src1)s, %(op2)s, %(dest)s,
390 %(dataSize)s, %(ext)s)''' % {
391 "class_name" : className,
392 "flags" : self.microFlagsText(microFlags),
393 "src1" : self.src1, "op2" : self.op2,
394 "dest" : self.dest,
395 "dataSize" : self.dataSize,
396 "ext" : self.ext}
397 return allocator
398
399 class LogicRegOp(RegOp):
400 abstract = True
401 flag_code = '''
402 //Don't have genFlags handle the OF or CF bits
403 uint64_t mask = CFBit | OFBit;
404 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
405 //If a logic microop wants to set these, it wants to set them to 0.
406 ccFlagBits &= ~(CFBit & ext);
407 ccFlagBits &= ~(OFBit & ext);
408 '''
409
410 class FlagRegOp(RegOp):
411 abstract = True
412 flag_code = \
413 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
414
415 class SubRegOp(RegOp):
416 abstract = True
417 flag_code = \
418 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
419
420 class CondRegOp(RegOp):
421 abstract = True
422 cond_check = "checkCondition(ccFlagBits)"
423
1// Copyright (c) 2007 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,
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,
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,
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,
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,
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,
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,
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,
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
230let {{
231 # Make these empty strings so that concatenating onto
232 # them will always work.
233 header_output = ""
234 decoder_output = ""
235 exec_output = ""
236
237 immTemplates = (
238 MicroRegOpImmDeclare,
239 MicroRegOpImmConstructor,
240 MicroRegOpImmExecute)
241
242 regTemplates = (
243 MicroRegOpDeclare,
244 MicroRegOpConstructor,
245 MicroRegOpExecute)
246
247 class RegOpMeta(type):
248 def buildCppClasses(self, name, Name, suffix, \
249 code, flag_code, cond_check, else_code):
250
251 # Globals to stick the output in
252 global header_output
253 global decoder_output
254 global exec_output
255
256 # Stick all the code together so it can be searched at once
257 allCode = "|".join((code, flag_code, cond_check, else_code))
258
259 # If op2 is used anywhere, make register and immediate versions
260 # of this code.
261 matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
262 match = matcher.search(allCode)
263 if match:
264 typeQual = ""
265 if match.group("typeQual"):
266 typeQual = match.group("typeQual")
267 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
268 self.buildCppClasses(name, Name, suffix,
269 matcher.sub(src2_name, code),
270 matcher.sub(src2_name, flag_code),
271 matcher.sub(src2_name, cond_check),
272 matcher.sub(src2_name, else_code))
273 self.buildCppClasses(name + "i", Name, suffix + "Imm",
274 matcher.sub("imm8", code),
275 matcher.sub("imm8", flag_code),
276 matcher.sub("imm8", cond_check),
277 matcher.sub("imm8", else_code))
278 return
279
280 # If there's something optional to do with flags, generate
281 # a version without it and fix up this version to use it.
282 if flag_code is not "" or cond_check is not "true":
283 self.buildCppClasses(name, Name, suffix,
284 code, "", "true", else_code)
285 suffix = "Flags" + suffix
286
287 # If psrc1 or psrc2 is used, we need to actually insert code to
288 # compute it.
289 matcher = re.compile("(?<!\w)psrc1(?!\w)")
290 if matcher.search(allCode):
291 code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code
292 matcher = re.compile("(?<!\w)psrc2(?!\w)")
293 if matcher.search(allCode):
294 code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code
295 # Also make available versions which do sign extension
296 matcher = re.compile("(?<!\w)spsrc1(?!\w)")
297 if matcher.search(allCode):
298 code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code
299 matcher = re.compile("(?<!\w)spsrc2(?!\w)")
300 if matcher.search(allCode):
301 code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code
302
303 base = "X86ISA::RegOp"
304
305 # If imm8 shows up in the code, use the immediate templates, if
306 # not, hopefully the register ones will be correct.
307 templates = regTemplates
308 matcher = re.compile("(?<!\w)imm8(?!\w)")
309 if matcher.search(allCode):
310 base += "Imm"
311 templates = immTemplates
312
313 # Get everything ready for the substitution
314 iop = InstObjParams(name, Name + suffix, base,
315 {"code" : code,
316 "flag_code" : flag_code,
317 "cond_check" : cond_check,
318 "else_code" : else_code})
319
320 # Generate the actual code (finally!)
321 header_output += templates[0].subst(iop)
322 decoder_output += templates[1].subst(iop)
323 exec_output += templates[2].subst(iop)
324
325
326 def __new__(mcls, Name, bases, dict):
327 abstract = False
328 name = Name.lower()
329 if "abstract" in dict:
330 abstract = dict['abstract']
331 del dict['abstract']
332
333 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
334 if not abstract:
335 cls.className = Name
336 cls.base_mnemonic = name
337 code = cls.code
338 flag_code = cls.flag_code
339 cond_check = cls.cond_check
340 else_code = cls.else_code
341
342 # Set up the C++ classes
343 mcls.buildCppClasses(cls, name, Name, "",
344 code, flag_code, cond_check, else_code)
345
346 # Hook into the microassembler dict
347 global microopClasses
348 microopClasses[name] = cls
349
350 allCode = "|".join((code, flag_code, cond_check, else_code))
351
352 # If op2 is used anywhere, make register and immediate versions
353 # of this code.
354 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
355 if matcher.search(allCode):
356 microopClasses[name + 'i'] = cls
357 return cls
358
359
360 class RegOp(X86Microop):
361 __metaclass__ = RegOpMeta
362 # This class itself doesn't act as a microop
363 abstract = True
364
365 # Default template parameter values
366 flag_code = ""
367 cond_check = "true"
368 else_code = ";"
369
370 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
371 self.dest = dest
372 self.src1 = src1
373 self.op2 = op2
374 self.flags = flags
375 self.dataSize = dataSize
376 if flags is None:
377 self.ext = 0
378 else:
379 if not isinstance(flags, (list, tuple)):
380 raise Exception, "flags must be a list or tuple of flags"
381 self.ext = " | ".join(flags)
382 self.className += "Flags"
383
384 def getAllocator(self, *microFlags):
385 className = self.className
386 if self.mnemonic == self.base_mnemonic + 'i':
387 className += "Imm"
388 allocator = '''new %(class_name)s(machInst, mnemonic
389 %(flags)s, %(src1)s, %(op2)s, %(dest)s,
390 %(dataSize)s, %(ext)s)''' % {
391 "class_name" : className,
392 "flags" : self.microFlagsText(microFlags),
393 "src1" : self.src1, "op2" : self.op2,
394 "dest" : self.dest,
395 "dataSize" : self.dataSize,
396 "ext" : self.ext}
397 return allocator
398
399 class LogicRegOp(RegOp):
400 abstract = True
401 flag_code = '''
402 //Don't have genFlags handle the OF or CF bits
403 uint64_t mask = CFBit | OFBit;
404 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
405 //If a logic microop wants to set these, it wants to set them to 0.
406 ccFlagBits &= ~(CFBit & ext);
407 ccFlagBits &= ~(OFBit & ext);
408 '''
409
410 class FlagRegOp(RegOp):
411 abstract = True
412 flag_code = \
413 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
414
415 class SubRegOp(RegOp):
416 abstract = True
417 flag_code = \
418 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
419
420 class CondRegOp(RegOp):
421 abstract = True
422 cond_check = "checkCondition(ccFlagBits)"
423
424 class RdRegOp(RegOp):
425 abstract = True
426 def __init__(self, dest, src1=None, dataSize="env.dataSize"):
427 if not src1:
428 src1 = dest
429 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
430
431 class WrRegOp(RegOp):
432 abstract = True
433 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
434 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
435
424 class Add(FlagRegOp):
425 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
426
427 class Or(LogicRegOp):
428 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
429
430 class Adc(FlagRegOp):
431 code = '''
432 CCFlagBits flags = ccFlagBits;
433 DestReg = merge(DestReg, psrc1 + op2 + flags.CF, dataSize);
434 '''
435
436 class Sbb(SubRegOp):
437 code = '''
438 CCFlagBits flags = ccFlagBits;
439 DestReg = merge(DestReg, psrc1 - op2 - flags.CF, dataSize);
440 '''
441
442 class And(LogicRegOp):
443 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
444
445 class Sub(SubRegOp):
446 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
447
448 class Xor(LogicRegOp):
449 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
450
436 class Add(FlagRegOp):
437 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
438
439 class Or(LogicRegOp):
440 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
441
442 class Adc(FlagRegOp):
443 code = '''
444 CCFlagBits flags = ccFlagBits;
445 DestReg = merge(DestReg, psrc1 + op2 + flags.CF, dataSize);
446 '''
447
448 class Sbb(SubRegOp):
449 code = '''
450 CCFlagBits flags = ccFlagBits;
451 DestReg = merge(DestReg, psrc1 - op2 - flags.CF, dataSize);
452 '''
453
454 class And(LogicRegOp):
455 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
456
457 class Sub(SubRegOp):
458 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
459
460 class Xor(LogicRegOp):
461 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
462
451 class Mul1s(FlagRegOp):
463 class Mul1s(WrRegOp):
452 code = '''
464 code = '''
453 int signPos = (dataSize * 8) / 2 - 1;
454 IntReg srcVal1 = psrc1 | (-bits(psrc1, signPos) << signPos);
455 IntReg srcVal2 = op2 | (-bits(psrc1, signPos) << signPos);
456 DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize)
465 ProdLow = psrc1 * op2;
466 int halfSize = (dataSize * 8) / 2;
467 int64_t spsrc1_h = spsrc1 >> halfSize;
468 int64_t spsrc1_l = spsrc1 & mask(halfSize);
469 int64_t spsrc2_h = sop2 >> halfSize;
470 int64_t spsrc2_l = sop2 & mask(halfSize);
471 ProdHi = ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l +
472 ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) +
473 spsrc1_h * spsrc2_h;
457 '''
458
474 '''
475
459 class Mul1u(FlagRegOp):
476 class Mul1u(WrRegOp):
460 code = '''
477 code = '''
478 ProdLow = psrc1 * op2;
461 int halfSize = (dataSize * 8) / 2;
479 int halfSize = (dataSize * 8) / 2;
462 IntReg srcVal1 = psrc1 & mask(halfSize);
463 IntReg srcVal2 = op2 & mask(halfSize);
464 DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize)
480 uint64_t psrc1_h = psrc1 >> halfSize;
481 uint64_t psrc1_l = psrc1 & mask(halfSize);
482 uint64_t psrc2_h = op2 >> halfSize;
483 uint64_t psrc2_l = op2 & mask(halfSize);
484 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
485 ((psrc1_l * psrc2_l) >> halfSize)) >> halfSize) +
486 psrc1_h * psrc2_h;
465 '''
466
487 '''
488
467 class Mulel(FlagRegOp):
468 code = 'DestReg = merge(DestReg, psrc1 * op2, dataSize);'
489 class Mulel(RdRegOp):
490 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
469
470 # Neither of these is quite correct because it assumes that right shifting
471 # a signed or unsigned value does sign or zero extension respectively.
472 # The C standard says that what happens on a right shift with a 1 in the
473 # MSB position is undefined. On x86 and under likely most compilers the
474 # "right thing" happens, but this isn't a guarantee.
491
492 # Neither of these is quite correct because it assumes that right shifting
493 # a signed or unsigned value does sign or zero extension respectively.
494 # The C standard says that what happens on a right shift with a 1 in the
495 # MSB position is undefined. On x86 and under likely most compilers the
496 # "right thing" happens, but this isn't a guarantee.
475 class Muleh(FlagRegOp):
476 code = '''
477 int halfSize = (dataSize * 8) / 2;
478 uint64_t psrc1_h = psrc1 >> halfSize;
479 uint64_t psrc1_l = psrc1 & mask(halfSize);
480 uint64_t psrc2_h = op2 >> halfSize;
481 uint64_t psrc2_l = op2 & mask(halfSize);
482 uint64_t result =
483 ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
484 ((psrc1_l * psrc2_l) >> halfSize)) >> halfSize) +
485 psrc1_h * psrc2_h;
486 DestReg = merge(DestReg, result, dataSize);
487 '''
497 class Muleh(RdRegOp):
498 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
499 if not src1:
500 src1 = dest
501 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", flags, dataSize)
502 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
503 flag_code = '''
504 if (ProdHi)
505 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
506 else
507 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
508 '''
488
509
489 class Mulehs(FlagRegOp):
490 code = '''
491 int halfSize = (dataSize * 8) / 2;
492 int64_t spsrc1_h = spsrc1 >> halfSize;
493 int64_t spsrc1_l = spsrc1 & mask(halfSize);
494 int64_t spsrc2_h = sop2 >> halfSize;
495 int64_t spsrc2_l = sop2 & mask(halfSize);
496 int64_t result =
497 ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l +
498 ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) +
499 spsrc1_h * spsrc2_h;
500 DestReg = merge(DestReg, result, dataSize);
501 '''
502
503 class Div1(FlagRegOp):
504 code = '''
505 int halfSize = (dataSize * 8) / 2;
506 IntReg quotient = (psrc1 / op2) & mask(halfSize);
507 IntReg remainder = (psrc1 % op2) & mask(halfSize);
508 IntReg result = quotient | (remainder << halfSize);
509 DestReg = merge(DestReg, result, dataSize);
510 '''
511
512 class Divq(FlagRegOp):
513 code = 'DestReg = merge(DestReg, psrc1 / op2, dataSize);'
514
515 class Divr(FlagRegOp):
516 code = 'DestReg = merge(DestReg, psrc1 % op2, dataSize);'
517
518 class Mov(CondRegOp):
519 code = 'DestReg = merge(SrcReg1, op2, dataSize)'
520 else_code = 'DestReg=DestReg;'
521
522 # Shift instructions
523
524 class Sll(FlagRegOp):
525 code = '''
526 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
527 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
528 '''
529
530 class Srl(FlagRegOp):
531 code = '''
532 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
533 // Because what happens to the bits shift -in- on a right shift
534 // is not defined in the C/C++ standard, we have to mask them out
535 // to be sure they're zero.
536 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
537 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
538 '''
539
540 class Sra(FlagRegOp):
541 code = '''
542 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
543 // Because what happens to the bits shift -in- on a right shift
544 // is not defined in the C/C++ standard, we have to sign extend
545 // them manually to be sure.
546 uint64_t arithMask =
547 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
548 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
549 '''
550
551 class Ror(FlagRegOp):
552 code = '''
553 uint8_t shiftAmt =
554 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
555 if(shiftAmt)
556 {
557 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt);
558 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
559 DestReg = merge(DestReg, top | bottom, dataSize);
560 }
561 else
562 DestReg = DestReg;
563 '''
564
565 class Rcr(FlagRegOp):
566 code = '''
567 uint8_t shiftAmt =
568 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
569 if(shiftAmt)
570 {
571 CCFlagBits flags = ccFlagBits;
572 uint64_t top = flags.CF << (dataSize * 8 - shiftAmt);
573 if(shiftAmt > 1)
574 top |= psrc1 << (dataSize * 8 - shiftAmt - 1);
575 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
576 DestReg = merge(DestReg, top | bottom, dataSize);
577 }
578 else
579 DestReg = DestReg;
580 '''
581
582 class Rol(FlagRegOp):
583 code = '''
584 uint8_t shiftAmt =
585 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
586 if(shiftAmt)
587 {
588 uint64_t top = psrc1 << shiftAmt;
589 uint64_t bottom =
590 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt);
591 DestReg = merge(DestReg, top | bottom, dataSize);
592 }
593 else
594 DestReg = DestReg;
595 '''
596
597 class Rcl(FlagRegOp):
598 code = '''
599 uint8_t shiftAmt =
600 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
601 if(shiftAmt)
602 {
603 CCFlagBits flags = ccFlagBits;
604 uint64_t top = psrc1 << shiftAmt;
605 uint64_t bottom = flags.CF << (shiftAmt - 1);
606 if(shiftAmt > 1)
607 bottom |=
608 bits(psrc1, dataSize * 8 - 1,
609 dataSize * 8 - shiftAmt + 1);
610 DestReg = merge(DestReg, top | bottom, dataSize);
611 }
612 else
613 DestReg = DestReg;
614 '''
615
510 class Div1(FlagRegOp):
511 code = '''
512 int halfSize = (dataSize * 8) / 2;
513 IntReg quotient = (psrc1 / op2) & mask(halfSize);
514 IntReg remainder = (psrc1 % op2) & mask(halfSize);
515 IntReg result = quotient | (remainder << halfSize);
516 DestReg = merge(DestReg, result, dataSize);
517 '''
518
519 class Divq(FlagRegOp):
520 code = 'DestReg = merge(DestReg, psrc1 / op2, dataSize);'
521
522 class Divr(FlagRegOp):
523 code = 'DestReg = merge(DestReg, psrc1 % op2, dataSize);'
524
525 class Mov(CondRegOp):
526 code = 'DestReg = merge(SrcReg1, op2, dataSize)'
527 else_code = 'DestReg=DestReg;'
528
529 # Shift instructions
530
531 class Sll(FlagRegOp):
532 code = '''
533 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
534 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
535 '''
536
537 class Srl(FlagRegOp):
538 code = '''
539 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
540 // Because what happens to the bits shift -in- on a right shift
541 // is not defined in the C/C++ standard, we have to mask them out
542 // to be sure they're zero.
543 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
544 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
545 '''
546
547 class Sra(FlagRegOp):
548 code = '''
549 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
550 // Because what happens to the bits shift -in- on a right shift
551 // is not defined in the C/C++ standard, we have to sign extend
552 // them manually to be sure.
553 uint64_t arithMask =
554 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
555 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
556 '''
557
558 class Ror(FlagRegOp):
559 code = '''
560 uint8_t shiftAmt =
561 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
562 if(shiftAmt)
563 {
564 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt);
565 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
566 DestReg = merge(DestReg, top | bottom, dataSize);
567 }
568 else
569 DestReg = DestReg;
570 '''
571
572 class Rcr(FlagRegOp):
573 code = '''
574 uint8_t shiftAmt =
575 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
576 if(shiftAmt)
577 {
578 CCFlagBits flags = ccFlagBits;
579 uint64_t top = flags.CF << (dataSize * 8 - shiftAmt);
580 if(shiftAmt > 1)
581 top |= psrc1 << (dataSize * 8 - shiftAmt - 1);
582 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
583 DestReg = merge(DestReg, top | bottom, dataSize);
584 }
585 else
586 DestReg = DestReg;
587 '''
588
589 class Rol(FlagRegOp):
590 code = '''
591 uint8_t shiftAmt =
592 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
593 if(shiftAmt)
594 {
595 uint64_t top = psrc1 << shiftAmt;
596 uint64_t bottom =
597 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt);
598 DestReg = merge(DestReg, top | bottom, dataSize);
599 }
600 else
601 DestReg = DestReg;
602 '''
603
604 class Rcl(FlagRegOp):
605 code = '''
606 uint8_t shiftAmt =
607 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
608 if(shiftAmt)
609 {
610 CCFlagBits flags = ccFlagBits;
611 uint64_t top = psrc1 << shiftAmt;
612 uint64_t bottom = flags.CF << (shiftAmt - 1);
613 if(shiftAmt > 1)
614 bottom |=
615 bits(psrc1, dataSize * 8 - 1,
616 dataSize * 8 - shiftAmt + 1);
617 DestReg = merge(DestReg, top | bottom, dataSize);
618 }
619 else
620 DestReg = DestReg;
621 '''
622
616 class WrRegOp(RegOp):
617 abstract = True
618 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
619 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
620
621 class Wrip(WrRegOp, CondRegOp):
622 code = 'RIP = psrc1 + op2'
623 else_code="RIP = RIP;"
624
625 class Br(WrRegOp, CondRegOp):
626 code = 'nuIP = psrc1 + op2;'
627 else_code='nuIP = nuIP;'
628
629 class Wruflags(WrRegOp):
630 code = 'ccFlagBits = psrc1 ^ op2'
631
623 class Wrip(WrRegOp, CondRegOp):
624 code = 'RIP = psrc1 + op2'
625 else_code="RIP = RIP;"
626
627 class Br(WrRegOp, CondRegOp):
628 code = 'nuIP = psrc1 + op2;'
629 else_code='nuIP = nuIP;'
630
631 class Wruflags(WrRegOp):
632 code = 'ccFlagBits = psrc1 ^ op2'
633
632 class RdRegOp(RegOp):
633 abstract = True
634 def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
635 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
636
637 class Rdip(RdRegOp):
638 code = 'DestReg = RIP'
639
640 class Ruflags(RdRegOp):
641 code = 'DestReg = ccFlagBits'
642
643 class Ruflag(RegOp):
644 code = '''
645 int flag = bits(ccFlagBits, imm8 + 0*psrc1);
646 DestReg = merge(DestReg, flag, dataSize);
647 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
648 (ccFlagBits & ~EZFBit);
649 '''
650 def __init__(self, dest, imm, flags=None, \
651 dataSize="env.dataSize"):
652 super(Ruflag, self).__init__(dest, \
653 "NUM_INTREGS", imm, flags, dataSize)
654
655 class Sext(RegOp):
656 code = '''
657 IntReg val = psrc1;
658 int sign_bit = bits(val, imm8-1, imm8-1);
659 uint64_t maskVal = mask(imm8);
660 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
661 DestReg = merge(DestReg, val, dataSize);
662 '''
663
664 class Zext(RegOp):
665 code = 'DestReg = bits(psrc1, imm8-1, 0);'
666
667 class Compfp(WrRegOp):
668 # This class sets the condition codes in rflags according to the
669 # rules for comparing floating point.
670 code = '''
671 // ZF PF CF
672 // Unordered 1 1 1
673 // Greater than 0 0 0
674 // Less than 0 0 1
675 // Equal 1 0 0
676 // OF = SF = AF = 0
677 ccFlagBits = ccFlagBits & ~(OFBit | SFBit | AFBit |
678 ZFBit | PFBit | CFBit);
679 if (isnan(FpSrcReg1) || isnan(FpSrcReg2))
680 ccFlagBits = ccFlagBits | (ZFBit | PFBit | CFBit);
681 else if(FpSrcReg1 < FpSrcReg2)
682 ccFlagBits = ccFlagBits | CFBit;
683 else if(FpSrcReg1 == FpSrcReg2)
684 ccFlagBits = ccFlagBits | ZFBit;
685 '''
686
687 class Xorfp(RegOp):
688 code = 'FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw;'
689
690 class Sqrtfp(RegOp):
691 code = 'FpDestReg = sqrt(FpSrcReg2);'
692
693 class Movfp(CondRegOp):
694 code = 'FpDestReg.uqw = FpSrcReg2.uqw;'
695 else_code = 'FpDestReg.uqw = FpDestReg.uqw;'
696
697 # Conversion microops
698 class ConvOp(RegOp):
699 abstract = True
700 def __init__(self, dest, src1):
701 super(ConvOp, self).__init__(dest, src1, "NUM_INTREGS")
702
703 #FIXME This needs to always use 32 bits unless REX.W is present
704 class cvtf_i2d(ConvOp):
705 code = 'FpDestReg = spsrc1;'
706
707 class cvtf_i2d_hi(ConvOp):
708 code = 'FpDestReg = bits(SrcReg1, 63, 32);'
709
710 class cvtf_d2i(ConvOp):
711 code = '''
712 int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
713 DestReg = merge(DestReg, intSrcReg1, dataSize);
714 '''
715
716 # These need to consider size at some point. They'll always use doubles
717 # for the moment.
718 class addfp(RegOp):
719 code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
720
721 class mulfp(RegOp):
722 code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
723
724 class divfp(RegOp):
725 code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
726
727 class subfp(RegOp):
728 code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
729}};
634 class Rdip(RdRegOp):
635 code = 'DestReg = RIP'
636
637 class Ruflags(RdRegOp):
638 code = 'DestReg = ccFlagBits'
639
640 class Ruflag(RegOp):
641 code = '''
642 int flag = bits(ccFlagBits, imm8 + 0*psrc1);
643 DestReg = merge(DestReg, flag, dataSize);
644 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
645 (ccFlagBits & ~EZFBit);
646 '''
647 def __init__(self, dest, imm, flags=None, \
648 dataSize="env.dataSize"):
649 super(Ruflag, self).__init__(dest, \
650 "NUM_INTREGS", imm, flags, dataSize)
651
652 class Sext(RegOp):
653 code = '''
654 IntReg val = psrc1;
655 int sign_bit = bits(val, imm8-1, imm8-1);
656 uint64_t maskVal = mask(imm8);
657 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
658 DestReg = merge(DestReg, val, dataSize);
659 '''
660
661 class Zext(RegOp):
662 code = 'DestReg = bits(psrc1, imm8-1, 0);'
663
664 class Compfp(WrRegOp):
665 # This class sets the condition codes in rflags according to the
666 # rules for comparing floating point.
667 code = '''
668 // ZF PF CF
669 // Unordered 1 1 1
670 // Greater than 0 0 0
671 // Less than 0 0 1
672 // Equal 1 0 0
673 // OF = SF = AF = 0
674 ccFlagBits = ccFlagBits & ~(OFBit | SFBit | AFBit |
675 ZFBit | PFBit | CFBit);
676 if (isnan(FpSrcReg1) || isnan(FpSrcReg2))
677 ccFlagBits = ccFlagBits | (ZFBit | PFBit | CFBit);
678 else if(FpSrcReg1 < FpSrcReg2)
679 ccFlagBits = ccFlagBits | CFBit;
680 else if(FpSrcReg1 == FpSrcReg2)
681 ccFlagBits = ccFlagBits | ZFBit;
682 '''
683
684 class Xorfp(RegOp):
685 code = 'FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw;'
686
687 class Sqrtfp(RegOp):
688 code = 'FpDestReg = sqrt(FpSrcReg2);'
689
690 class Movfp(CondRegOp):
691 code = 'FpDestReg.uqw = FpSrcReg2.uqw;'
692 else_code = 'FpDestReg.uqw = FpDestReg.uqw;'
693
694 # Conversion microops
695 class ConvOp(RegOp):
696 abstract = True
697 def __init__(self, dest, src1):
698 super(ConvOp, self).__init__(dest, src1, "NUM_INTREGS")
699
700 #FIXME This needs to always use 32 bits unless REX.W is present
701 class cvtf_i2d(ConvOp):
702 code = 'FpDestReg = spsrc1;'
703
704 class cvtf_i2d_hi(ConvOp):
705 code = 'FpDestReg = bits(SrcReg1, 63, 32);'
706
707 class cvtf_d2i(ConvOp):
708 code = '''
709 int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
710 DestReg = merge(DestReg, intSrcReg1, dataSize);
711 '''
712
713 # These need to consider size at some point. They'll always use doubles
714 # for the moment.
715 class addfp(RegOp):
716 code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
717
718 class mulfp(RegOp):
719 code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
720
721 class divfp(RegOp):
722 code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
723
724 class subfp(RegOp):
725 code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
726}};