1 // Copyright (c) 2007 The Hewlett-Packard Development Company
2 // All rights reserved.
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:
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.
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
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.
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.
54 // Authors: Gabe Black
56 //////////////////////////////////////////////////////////////////////////
58 // FpOp Microop templates
60 //////////////////////////////////////////////////////////////////////////
62 def template MicroFpOpExecute {{
63 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
64 Trace::InstRecord *traceData) const
66 Fault fault = NoFault;
68 DPRINTF(X86, "The data size is %d\n", dataSize);
83 //Write the resulting state to the execution context
92 def template MicroFpOpDeclare {{
93 class %(class_name)s : public %(base_class)s
99 %(class_name)s(ExtMachInst _machInst,
100 const char * instMnem,
101 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
102 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
103 uint8_t _dataSize, int8_t _spm);
105 %(class_name)s(ExtMachInst _machInst,
106 const char * instMnem,
107 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
108 uint8_t _dataSize, int8_t _spm);
114 def template MicroFpOpConstructor {{
116 inline void %(class_name)s::buildMe()
121 inline %(class_name)s::%(class_name)s(
122 ExtMachInst machInst, const char * instMnem,
123 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
124 uint8_t _dataSize, int8_t _spm) :
125 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
126 false, false, false, false,
127 _src1, _src2, _dest, _dataSize, _spm,
133 inline %(class_name)s::%(class_name)s(
134 ExtMachInst machInst, const char * instMnem,
135 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
136 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
137 uint8_t _dataSize, int8_t _spm) :
138 %(base_class)s(machInst, "%(mnemonic)s", instMnem,
139 isMicro, isDelayed, isFirst, isLast,
140 _src1, _src2, _dest, _dataSize, _spm,
148 # Make these empty strings so that concatenating onto
149 # them will always work.
154 class FpOpMeta(type):
155 def buildCppClasses(self, name, Name, suffix, \
156 code, flag_code, cond_check, else_code):
158 # Globals to stick the output in
160 global decoder_output
163 # Stick all the code together so it can be searched at once
164 allCode = "|".join((code, flag_code, cond_check, else_code))
166 # If there's something optional to do with flags, generate
167 # a version without it and fix up this version to use it.
168 if flag_code is not "" or cond_check is not "true":
169 self.buildCppClasses(name, Name, suffix,
170 code, "", "true", else_code)
171 suffix = "Flags" + suffix
173 base = "X86ISA::FpOp"
175 # Get everything ready for the substitution
176 iop_top = InstObjParams(name, Name + suffix + "Top", base,
178 "flag_code" : flag_code,
179 "cond_check" : cond_check,
180 "else_code" : else_code,
181 "top_code" : "TOP = (TOP + spm + 8) % 8;"})
182 iop = InstObjParams(name, Name + suffix, base,
184 "flag_code" : flag_code,
185 "cond_check" : cond_check,
186 "else_code" : else_code,
189 # Generate the actual code (finally!)
190 header_output += MicroFpOpDeclare.subst(iop_top)
191 decoder_output += MicroFpOpConstructor.subst(iop_top)
192 exec_output += MicroFpOpExecute.subst(iop_top)
193 header_output += MicroFpOpDeclare.subst(iop)
194 decoder_output += MicroFpOpConstructor.subst(iop)
195 exec_output += MicroFpOpExecute.subst(iop)
198 def __new__(mcls, Name, bases, dict):
201 if "abstract" in dict:
202 abstract = dict['abstract']
205 cls = super(FpOpMeta, mcls).__new__(mcls, Name, bases, dict)
210 flag_code = cls.flag_code
211 cond_check = cls.cond_check
212 else_code = cls.else_code
214 # Set up the C++ classes
215 mcls.buildCppClasses(cls, name, Name, "",
216 code, flag_code, cond_check, else_code)
218 # Hook into the microassembler dict
219 global microopClasses
220 microopClasses[name] = cls
225 class FpOp(X86Microop):
226 __metaclass__ = FpOpMeta
227 # This class itself doesn't act as a microop
230 # Default template parameter values
235 def __init__(self, dest, src1, src2, spm=0, \
236 SetStatus=False, dataSize="env.dataSize"):
241 self.dataSize = dataSize
243 self.className += "Flags"
245 self.className += "Top"
247 def getAllocator(self, *microFlags):
248 return '''new %(class_name)s(machInst, macrocodeBlock
249 %(flags)s, %(src1)s, %(src2)s, %(dest)s,
250 %(dataSize)s, %(spm)d)''' % {
251 "class_name" : self.className,
252 "flags" : self.microFlagsText(microFlags),
253 "src1" : self.src1, "src2" : self.src2,
255 "dataSize" : self.dataSize,
259 def __init__(self, dest, src1, spm=0, \
260 SetStatus=False, dataSize="env.dataSize"):
261 super(Movfp, self).__init__(dest, src1, "InstRegIndex(0)", \
262 spm, SetStatus, dataSize)
263 code = 'FpDestReg.uqw = FpSrcReg1.uqw;'
264 else_code = 'FpDestReg.uqw = FpDestReg.uqw;'
265 cond_check = "checkCondition(ccFlagBits, src2)"
268 code = 'FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw;'
271 code = 'FpDestReg = sqrt(FpSrcReg2);'
273 # Conversion microops
276 def __init__(self, dest, src1):
277 super(ConvOp, self).__init__(dest, src1, \
278 "InstRegIndex(FLOATREG_MICROFP0)")
280 # These probably shouldn't look at the ExtMachInst directly to figure
281 # out what size to use and should instead delegate that to the macroop's
282 # constructor. That would be more efficient, and it would make the
283 # microops a little more modular.
284 class cvtf_i2d(ConvOp):
286 X86IntReg intReg = SSrcReg1;
288 FpDestReg = intReg.SR;
290 FpDestReg = intReg.SE;
293 class cvtf_i2d_hi(ConvOp):
294 code = 'FpDestReg = bits(SSrcReg1, 63, 32);'
296 class cvtf_d2i(ConvOp):
298 int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
300 SDestReg = intSrcReg1;
302 SDestReg = merge(SDestReg, intSrcReg1, 4);
305 # These need to consider size at some point. They'll always use doubles
308 code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
311 code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
314 code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
317 code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
320 def __init__(self, src1, src2, spm=0, setStatus=False, \
321 dataSize="env.dataSize"):
322 super(Compfp, self).__init__("InstRegIndex(FLOATREG_MICROFP0)", \
323 src1, src2, spm, setStatus, dataSize)
324 # This class sets the condition codes in rflags according to the
325 # rules for comparing floating point.
329 // Greater than 0 0 0
333 ccFlagBits = ccFlagBits & ~(OFBit | SFBit | AFBit |
334 ZFBit | PFBit | CFBit);
335 if (isnan(FpSrcReg1) || isnan(FpSrcReg2))
336 ccFlagBits = ccFlagBits | (ZFBit | PFBit | CFBit);
337 else if(FpSrcReg1 < FpSrcReg2)
338 ccFlagBits = ccFlagBits | CFBit;
339 else if(FpSrcReg1 == FpSrcReg2)
340 ccFlagBits = ccFlagBits | ZFBit;