Pull some hard coded base classes out of the isa description.
[gem5.git] / src / arch / x86 / isa / microops / regop.isa
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
62 def 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 %(op_decl)s;
69 %(op_rd)s;
70 %(code)s;
71 %(flag_code)s;
72
73 //Write the resulting state to the execution context
74 if(fault == NoFault)
75 {
76 %(op_wb)s;
77 }
78 return fault;
79 }
80 }};
81
82 def template MicroRegOpImmExecute {{
83 Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc,
84 Trace::InstRecord *traceData) const
85 {
86 Fault fault = NoFault;
87
88 %(op_decl)s;
89 %(op_rd)s;
90 %(code)s;
91 %(flag_code)s;
92
93 //Write the resulting state to the execution context
94 if(fault == NoFault)
95 {
96 %(op_wb)s;
97 }
98 return fault;
99 }
100 }};
101
102 def template MicroRegOpDeclare {{
103 class %(class_name)s : public %(base_class)s
104 {
105 protected:
106 void buildMe();
107
108 public:
109 %(class_name)s(ExtMachInst _machInst,
110 const char * instMnem,
111 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
112 RegIndex _src1, RegIndex _src2, RegIndex _dest,
113 bool _setStatus, uint8_t _dataSize, uint8_t _ext);
114
115 %(class_name)s(ExtMachInst _machInst,
116 const char * instMnem,
117 RegIndex _src1, RegIndex _src2, RegIndex _dest,
118 bool _setStatus, uint8_t _dataSize, uint8_t _ext);
119
120 %(BasicExecDeclare)s
121 };
122 }};
123
124 def template MicroRegOpImmDeclare {{
125
126 class %(class_name)sImm : public %(base_class)s
127 {
128 protected:
129 void buildMe();
130
131 public:
132 %(class_name)sImm(ExtMachInst _machInst,
133 const char * instMnem,
134 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
135 RegIndex _src1, uint8_t _imm8, RegIndex _dest,
136 bool _setStatus, uint8_t _dataSize, uint8_t _ext);
137
138 %(class_name)sImm(ExtMachInst _machInst,
139 const char * instMnem,
140 RegIndex _src1, uint8_t _imm8, RegIndex _dest,
141 bool _setStatus, uint8_t _dataSize, uint8_t _ext);
142
143 %(BasicExecDeclare)s
144 };
145 }};
146
147 def template MicroRegOpConstructor {{
148
149 inline void %(class_name)s::buildMe()
150 {
151 %(constructor)s;
152 }
153
154 inline %(class_name)s::%(class_name)s(
155 ExtMachInst machInst, const char * instMnem,
156 RegIndex _src1, RegIndex _src2, RegIndex _dest,
157 bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
158 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
159 false, false, false, false,
160 _src1, _src2, _dest, _setStatus, _dataSize, _ext,
161 %(op_class)s)
162 {
163 buildMe();
164 }
165
166 inline %(class_name)s::%(class_name)s(
167 ExtMachInst machInst, const char * instMnem,
168 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
169 RegIndex _src1, RegIndex _src2, RegIndex _dest,
170 bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
171 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
172 isMicro, isDelayed, isFirst, isLast,
173 _src1, _src2, _dest, _setStatus, _dataSize, _ext,
174 %(op_class)s)
175 {
176 buildMe();
177 }
178 }};
179
180 def template MicroRegOpImmConstructor {{
181
182 inline void %(class_name)sImm::buildMe()
183 {
184 %(constructor)s;
185 }
186
187 inline %(class_name)sImm::%(class_name)sImm(
188 ExtMachInst machInst, const char * instMnem,
189 RegIndex _src1, uint8_t _imm8, RegIndex _dest,
190 bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
191 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
192 false, false, false, false,
193 _src1, _imm8, _dest, _setStatus, _dataSize, _ext,
194 %(op_class)s)
195 {
196 buildMe();
197 }
198
199 inline %(class_name)sImm::%(class_name)sImm(
200 ExtMachInst machInst, const char * instMnem,
201 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
202 RegIndex _src1, uint8_t _imm8, RegIndex _dest,
203 bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
204 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
205 isMicro, isDelayed, isFirst, isLast,
206 _src1, _imm8, _dest, _setStatus, _dataSize, _ext,
207 %(op_class)s)
208 {
209 buildMe();
210 }
211 }};
212
213 let {{
214 class RegOp(X86Microop):
215 def __init__(self, dest, src1, src2, setStatus):
216 self.dest = dest
217 self.src1 = src1
218 self.src2 = src2
219 self.setStatus = setStatus
220 self.dataSize = "env.dataSize"
221 self.ext = 0
222
223 def getAllocator(self, *microFlags):
224 allocator = '''new %(class_name)s(machInst, mnemonic
225 %(flags)s, %(src1)s, %(src2)s, %(dest)s,
226 %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
227 "class_name" : self.className,
228 "flags" : self.microFlagsText(microFlags),
229 "src1" : self.src1, "src2" : self.src2,
230 "dest" : self.dest,
231 "setStatus" : self.cppBool(self.setStatus),
232 "dataSize" : self.dataSize,
233 "ext" : self.ext}
234 return allocator
235
236 class RegOpImm(X86Microop):
237 def __init__(self, dest, src1, imm8, setStatus):
238 self.dest = dest
239 self.src1 = src1
240 self.imm8 = imm8
241 self.setStatus = setStatus
242 self.dataSize = "env.dataSize"
243 self.ext = 0
244
245 def getAllocator(self, *microFlags):
246 allocator = '''new %(class_name)s(machInst, mnemonic
247 %(flags)s, %(src1)s, %(imm8)s, %(dest)s,
248 %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
249 "class_name" : self.className,
250 "flags" : self.microFlagsText(microFlags),
251 "src1" : self.src1, "imm8" : self.imm8,
252 "dest" : self.dest,
253 "setStatus" : self.cppBool(self.setStatus),
254 "dataSize" : self.dataSize,
255 "ext" : self.ext}
256 return allocator
257 }};
258
259 let {{
260
261 # Make these empty strings so that concatenating onto
262 # them will always work.
263 header_output = ""
264 decoder_output = ""
265 exec_output = ""
266
267 def setUpMicroRegOp(name, Name, base, code, child, flagCode):
268 global header_output
269 global decoder_output
270 global exec_output
271 global microopClasses
272
273 iop = InstObjParams(name, Name, base,
274 {"code" : code,
275 "flag_code" : flagCode})
276 header_output += MicroRegOpDeclare.subst(iop)
277 decoder_output += MicroRegOpConstructor.subst(iop)
278 exec_output += MicroRegOpExecute.subst(iop)
279
280 microopClasses[name] = child
281
282 def defineMicroRegOp(mnemonic, code, flagCode):
283 Name = mnemonic
284 name = mnemonic.lower()
285
286 # Find op2 in each of the instruction definitions. Create two versions
287 # of the code, one with an integer operand, and one with an immediate
288 # operand.
289 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
290 regCode = matcher.sub("SrcReg2", code)
291 immCode = matcher.sub("imm8", code)
292
293 # Build the all register version of this micro op
294 class RegOpChild(RegOp):
295 def __init__(self, dest, src1, src2, setStatus=False):
296 super(RegOpChild, self).__init__(dest, src1, src2, setStatus)
297 self.className = Name
298 self.mnemonic = name
299
300 setUpMicroRegOp(name, Name, "X86ISA::RegOp", \
301 regCode, RegOpChild, flagCode);
302
303 # Build the immediate version of this micro op
304 class RegOpChildImm(RegOpImm):
305 def __init__(self, dest, src1, src2, setStatus=False):
306 super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus)
307 self.className = Name + "Imm"
308 self.mnemonic = name + "i"
309
310 setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \
311 immCode, RegOpChildImm, flagCode);
312
313 defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF
314 defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "")
315 defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF
316 defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF
317 defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "")
318 defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF
319 defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "")
320 defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg
321 defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "")
322
323 # This has it's own function because Wr ops have implicit destinations
324 def defineMicroRegOpWr(mnemonic, code):
325 Name = mnemonic
326 name = mnemonic.lower()
327
328 # Find op2 in each of the instruction definitions. Create two versions
329 # of the code, one with an integer operand, and one with an immediate
330 # operand.
331 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
332 regCode = matcher.sub("SrcReg2", code)
333 immCode = matcher.sub("imm8", code)
334
335 # Build the all register version of this micro op
336 class RegOpChild(RegOp):
337 def __init__(self, src1, src2):
338 super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False)
339 self.className = Name
340 self.mnemonic = name
341
342 setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, RegOpChild, "");
343
344 # Build the immediate version of this micro op
345 class RegOpChildImm(RegOpImm):
346 def __init__(self, src1, src2):
347 super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False)
348 self.className = Name + "Imm"
349 self.mnemonic = name + "i"
350
351 setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \
352 immCode, RegOpChildImm, "");
353
354 defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2')
355
356 # This has it's own function because Rd ops don't always have two parameters
357 def defineMicroRegOpRd(mnemonic, code):
358 Name = mnemonic
359 name = mnemonic.lower()
360
361 class RegOpChild(RegOp):
362 def __init__(self, dest, src1 = "NUM_INTREGS"):
363 super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False)
364 self.className = Name
365 self.mnemonic = name
366
367 setUpMicroRegOp(name, Name, "X86ISA::RegOp", code, RegOpChild, "");
368
369 defineMicroRegOpRd('Rdip', 'DestReg = RIP')
370
371 def defineMicroRegOpImm(mnemonic, code):
372 Name = mnemonic
373 name = mnemonic.lower()
374
375 class RegOpChild(RegOpImm):
376 def __init__(self, dest, src1, src2):
377 super(RegOpChild, self).__init__(dest, src1, src2, False)
378 self.className = Name
379 self.mnemonic = name
380
381 setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, RegOpChild, "");
382
383 defineMicroRegOpImm('Sext', '''
384 IntReg val = SrcReg1;
385 int sign_bit = bits(val, imm8-1, imm8-1);
386 val = sign_bit ? (val | ~mask(imm8)) : val;
387 DestReg = merge(DestReg, val, dataSize);''')
388 }};