regop.isa (5040:126e4510b5bb) regop.isa (5042:bc2c08abe249)
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
287 matcher = re.compile("(?<!\w)psrc2(?!\w)")
288 if matcher.search(allCode):
289 code = "IntReg psrc2 = pick(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):
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
287 matcher = re.compile("(?<!\w)psrc2(?!\w)")
288 if matcher.search(allCode):
289 code = "IntReg psrc2 = pick(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)'
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) >> halfSize) +
467 ((psrc1_h * psrc2_l) >> 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 class Movfp(CondRegOp):
492 code = 'FpDestReg = FpSrcReg2'
493 else_code = 'FpDestReg = FpDestReg;'
494
495 # Shift instructions
496
497 class Sll(FlagRegOp):
498 code = '''
499 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
500 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
501 '''
502
503 class Srl(FlagRegOp):
504 code = '''
505 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
506 // Because what happens to the bits shift -in- on a right shift
507 // is not defined in the C/C++ standard, we have to mask them out
508 // to be sure they're zero.
509 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
510 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
511 '''
512
513 class Sra(FlagRegOp):
514 code = '''
515 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
516 // Because what happens to the bits shift -in- on a right shift
517 // is not defined in the C/C++ standard, we have to sign extend
518 // them manually to be sure.
519 uint64_t arithMask =
520 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
521 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
522 '''
523
524 class Ror(FlagRegOp):
525 code = '''
526 uint8_t shiftAmt =
527 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
528 if(shiftAmt)
529 {
530 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt);
531 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
532 DestReg = merge(DestReg, top | bottom, dataSize);
533 }
534 else
535 DestReg = DestReg;
536 '''
537
538 class Rcr(FlagRegOp):
539 code = '''
540 uint8_t shiftAmt =
541 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
542 if(shiftAmt)
543 {
544 CCFlagBits flags = ccFlagBits;
545 uint64_t top = flags.CF << (dataSize * 8 - shiftAmt);
546 if(shiftAmt > 1)
547 top |= psrc1 << (dataSize * 8 - shiftAmt - 1);
548 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
549 DestReg = merge(DestReg, top | bottom, dataSize);
550 }
551 else
552 DestReg = DestReg;
553 '''
554
555 class Rol(FlagRegOp):
556 code = '''
557 uint8_t shiftAmt =
558 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
559 if(shiftAmt)
560 {
561 uint64_t top = psrc1 << shiftAmt;
562 uint64_t bottom =
563 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt);
564 DestReg = merge(DestReg, top | bottom, dataSize);
565 }
566 else
567 DestReg = DestReg;
568 '''
569
570 class Rcl(FlagRegOp):
571 code = '''
572 uint8_t shiftAmt =
573 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
574 if(shiftAmt)
575 {
576 CCFlagBits flags = ccFlagBits;
577 uint64_t top = psrc1 << shiftAmt;
578 uint64_t bottom = flags.CF << (shiftAmt - 1);
579 if(shiftAmt > 1)
580 bottom |=
581 bits(psrc1, dataSize * 8 - 1,
582 dataSize * 8 - shiftAmt + 1);
583 DestReg = merge(DestReg, top | bottom, dataSize);
584 }
585 else
586 DestReg = DestReg;
587 '''
588
589 class WrRegOp(RegOp):
590 abstract = True
591 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
592 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
593
594 class Wrip(WrRegOp, CondRegOp):
595 code = 'RIP = psrc1 + op2'
596 else_code="RIP = RIP;"
597
598 class Br(WrRegOp, CondRegOp):
599 code = 'nuIP = psrc1 + op2;'
600 else_code='nuIP = nuIP;'
601
602 class Wruflags(WrRegOp):
603 code = 'ccFlagBits = psrc1 ^ op2'
604
605 class RdRegOp(RegOp):
606 abstract = True
607 def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
608 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
609
610 class Rdip(RdRegOp):
611 code = 'DestReg = RIP'
612
613 class Ruflags(RdRegOp):
614 code = 'DestReg = ccFlagBits'
615
616 class Ruflag(RegOp):
617 code = '''
618 int flag = bits(ccFlagBits, imm8 + 0*psrc1);
619 DestReg = merge(DestReg, flag, dataSize);
620 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
621 (ccFlagBits & ~EZFBit);
622 '''
623 def __init__(self, dest, imm, flags=None, \
624 dataSize="env.dataSize"):
625 super(Ruflag, self).__init__(dest, \
626 "NUM_INTREGS", imm, flags, dataSize)
627
628 class Sext(RegOp):
629 code = '''
630 IntReg val = psrc1;
631 int sign_bit = bits(val, imm8-1, imm8-1);
632 uint64_t maskVal = mask(imm8);
633 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
634 DestReg = merge(DestReg, val, dataSize);
635 '''
636
637 class Zext(RegOp):
638 code = 'DestReg = bits(psrc1, imm8-1, 0);'
639}};
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) >> halfSize) +
467 ((psrc1_h * psrc2_l) >> 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 class Movfp(CondRegOp):
492 code = 'FpDestReg = FpSrcReg2'
493 else_code = 'FpDestReg = FpDestReg;'
494
495 # Shift instructions
496
497 class Sll(FlagRegOp):
498 code = '''
499 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
500 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
501 '''
502
503 class Srl(FlagRegOp):
504 code = '''
505 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
506 // Because what happens to the bits shift -in- on a right shift
507 // is not defined in the C/C++ standard, we have to mask them out
508 // to be sure they're zero.
509 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
510 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
511 '''
512
513 class Sra(FlagRegOp):
514 code = '''
515 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
516 // Because what happens to the bits shift -in- on a right shift
517 // is not defined in the C/C++ standard, we have to sign extend
518 // them manually to be sure.
519 uint64_t arithMask =
520 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
521 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
522 '''
523
524 class Ror(FlagRegOp):
525 code = '''
526 uint8_t shiftAmt =
527 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
528 if(shiftAmt)
529 {
530 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt);
531 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
532 DestReg = merge(DestReg, top | bottom, dataSize);
533 }
534 else
535 DestReg = DestReg;
536 '''
537
538 class Rcr(FlagRegOp):
539 code = '''
540 uint8_t shiftAmt =
541 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
542 if(shiftAmt)
543 {
544 CCFlagBits flags = ccFlagBits;
545 uint64_t top = flags.CF << (dataSize * 8 - shiftAmt);
546 if(shiftAmt > 1)
547 top |= psrc1 << (dataSize * 8 - shiftAmt - 1);
548 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt);
549 DestReg = merge(DestReg, top | bottom, dataSize);
550 }
551 else
552 DestReg = DestReg;
553 '''
554
555 class Rol(FlagRegOp):
556 code = '''
557 uint8_t shiftAmt =
558 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
559 if(shiftAmt)
560 {
561 uint64_t top = psrc1 << shiftAmt;
562 uint64_t bottom =
563 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt);
564 DestReg = merge(DestReg, top | bottom, dataSize);
565 }
566 else
567 DestReg = DestReg;
568 '''
569
570 class Rcl(FlagRegOp):
571 code = '''
572 uint8_t shiftAmt =
573 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
574 if(shiftAmt)
575 {
576 CCFlagBits flags = ccFlagBits;
577 uint64_t top = psrc1 << shiftAmt;
578 uint64_t bottom = flags.CF << (shiftAmt - 1);
579 if(shiftAmt > 1)
580 bottom |=
581 bits(psrc1, dataSize * 8 - 1,
582 dataSize * 8 - shiftAmt + 1);
583 DestReg = merge(DestReg, top | bottom, dataSize);
584 }
585 else
586 DestReg = DestReg;
587 '''
588
589 class WrRegOp(RegOp):
590 abstract = True
591 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
592 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
593
594 class Wrip(WrRegOp, CondRegOp):
595 code = 'RIP = psrc1 + op2'
596 else_code="RIP = RIP;"
597
598 class Br(WrRegOp, CondRegOp):
599 code = 'nuIP = psrc1 + op2;'
600 else_code='nuIP = nuIP;'
601
602 class Wruflags(WrRegOp):
603 code = 'ccFlagBits = psrc1 ^ op2'
604
605 class RdRegOp(RegOp):
606 abstract = True
607 def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
608 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
609
610 class Rdip(RdRegOp):
611 code = 'DestReg = RIP'
612
613 class Ruflags(RdRegOp):
614 code = 'DestReg = ccFlagBits'
615
616 class Ruflag(RegOp):
617 code = '''
618 int flag = bits(ccFlagBits, imm8 + 0*psrc1);
619 DestReg = merge(DestReg, flag, dataSize);
620 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
621 (ccFlagBits & ~EZFBit);
622 '''
623 def __init__(self, dest, imm, flags=None, \
624 dataSize="env.dataSize"):
625 super(Ruflag, self).__init__(dest, \
626 "NUM_INTREGS", imm, flags, dataSize)
627
628 class Sext(RegOp):
629 code = '''
630 IntReg val = psrc1;
631 int sign_bit = bits(val, imm8-1, imm8-1);
632 uint64_t maskVal = mask(imm8);
633 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
634 DestReg = merge(DestReg, val, dataSize);
635 '''
636
637 class Zext(RegOp):
638 code = 'DestReg = bits(psrc1, imm8-1, 0);'
639}};