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