fp64.isa revision 12110:c24ee249b8ba
1// -*- mode:c++ -*-
2
3// Copyright (c) 2012-2013, 2016 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Thomas Grocutt
39//          Edmund Grimley Evans
40
41let {{
42
43    header_output = ""
44    decoder_output = ""
45    exec_output = ""
46
47    fmovImmSCode = vfp64EnabledCheckCode + '''
48        AA64FpDestP0_uw = bits(imm, 31, 0);
49        AA64FpDestP1_uw = 0;
50        AA64FpDestP2_uw = 0;
51        AA64FpDestP3_uw = 0;
52    '''
53    fmovImmSIop = InstObjParams("fmov", "FmovImmS", "FpRegImmOp",
54                                { "code": fmovImmSCode,
55                                  "op_class": "FloatMiscOp" }, [])
56    header_output  += FpRegImmOpDeclare.subst(fmovImmSIop);
57    decoder_output += FpRegImmOpConstructor.subst(fmovImmSIop);
58    exec_output    += BasicExecute.subst(fmovImmSIop);
59
60    fmovImmDCode = vfp64EnabledCheckCode + '''
61        AA64FpDestP0_uw = bits(imm, 31, 0);
62        AA64FpDestP1_uw = bits(imm, 63, 32);
63        AA64FpDestP2_uw = 0;
64        AA64FpDestP3_uw = 0;
65    '''
66    fmovImmDIop = InstObjParams("fmov", "FmovImmD", "FpRegImmOp",
67                                { "code": fmovImmDCode,
68                                  "op_class": "FloatMiscOp" }, [])
69    header_output  += FpRegImmOpDeclare.subst(fmovImmDIop);
70    decoder_output += AA64FpRegImmOpConstructor.subst(fmovImmDIop);
71    exec_output    += BasicExecute.subst(fmovImmDIop);
72
73    fmovRegSCode = vfp64EnabledCheckCode + '''
74        AA64FpDestP0_uw = AA64FpOp1P0_uw;
75        AA64FpDestP1_uw = 0;
76        AA64FpDestP2_uw = 0;
77        AA64FpDestP3_uw = 0;
78    '''
79    fmovRegSIop = InstObjParams("fmov", "FmovRegS", "FpRegRegOp",
80                                { "code": fmovRegSCode,
81                                  "op_class": "FloatMiscOp" }, [])
82    header_output  += FpRegRegOpDeclare.subst(fmovRegSIop);
83    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegSIop);
84    exec_output    += BasicExecute.subst(fmovRegSIop);
85
86    fmovRegDCode = vfp64EnabledCheckCode + '''
87        AA64FpDestP0_uw = AA64FpOp1P0_uw;
88        AA64FpDestP1_uw = AA64FpOp1P1_uw;
89        AA64FpDestP2_uw = 0;
90        AA64FpDestP3_uw = 0;
91    '''
92    fmovRegDIop = InstObjParams("fmov", "FmovRegD", "FpRegRegOp",
93                                { "code": fmovRegDCode,
94                                  "op_class": "FloatMiscOp" }, [])
95    header_output  += FpRegRegOpDeclare.subst(fmovRegDIop);
96    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegDIop);
97    exec_output    += BasicExecute.subst(fmovRegDIop);
98
99    fmovCoreRegWCode = vfp64EnabledCheckCode + '''
100        AA64FpDestP0_uw = WOp1_uw;
101        AA64FpDestP1_uw = 0;
102        AA64FpDestP2_uw = 0;
103        AA64FpDestP3_uw = 0;
104    '''
105    fmovCoreRegWIop = InstObjParams("fmov", "FmovCoreRegW", "FpRegRegOp",
106                                    { "code": fmovCoreRegWCode,
107                                      "op_class": "FloatMiscOp" }, [])
108    header_output  += FpRegRegOpDeclare.subst(fmovCoreRegWIop);
109    decoder_output += AA64FpRegRegOpConstructor.subst(fmovCoreRegWIop);
110    exec_output    += BasicExecute.subst(fmovCoreRegWIop);
111
112    fmovCoreRegXCode = vfp64EnabledCheckCode + '''
113        AA64FpDestP0_uw = XOp1_ud;
114        AA64FpDestP1_uw = XOp1_ud >> 32;
115        AA64FpDestP2_uw = 0;
116        AA64FpDestP3_uw = 0;
117    '''
118    fmovCoreRegXIop = InstObjParams("fmov", "FmovCoreRegX", "FpRegRegOp",
119                                    { "code": fmovCoreRegXCode,
120                                      "op_class": "FloatMiscOp" }, [])
121    header_output  += FpRegRegOpDeclare.subst(fmovCoreRegXIop);
122    decoder_output += AA64FpRegRegOpConstructor.subst(fmovCoreRegXIop);
123    exec_output    += BasicExecute.subst(fmovCoreRegXIop);
124
125    fmovUCoreRegXCode = vfp64EnabledCheckCode + '''
126        /* Explicitly merge with previous value */
127        AA64FpDestP0_uw = AA64FpDestP0_uw;
128        AA64FpDestP1_uw = AA64FpDestP1_uw;
129        AA64FpDestP2_uw = XOp1_ud;
130        AA64FpDestP3_uw = XOp1_ud >> 32;'''
131    fmovUCoreRegXIop = InstObjParams("fmov", "FmovUCoreRegX", "FpRegRegOp",
132                                    { "code": fmovUCoreRegXCode,
133                                      "op_class": "FloatMiscOp" }, [])
134    header_output  += FpRegRegOpDeclare.subst(fmovUCoreRegXIop);
135    decoder_output += AA64FpRegRegOpConstructor.subst(fmovUCoreRegXIop);
136    exec_output    += BasicExecute.subst(fmovUCoreRegXIop);
137
138    fmovRegCoreWCode = vfp64EnabledCheckCode + '''
139        WDest = AA64FpOp1P0_uw;
140    '''
141    fmovRegCoreWIop = InstObjParams("fmov", "FmovRegCoreW", "FpRegRegOp",
142                                     { "code": fmovRegCoreWCode,
143                                       "op_class": "FloatMiscOp" }, [])
144    header_output  += FpRegRegOpDeclare.subst(fmovRegCoreWIop);
145    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegCoreWIop);
146    exec_output    += BasicExecute.subst(fmovRegCoreWIop);
147
148    fmovRegCoreXCode = vfp64EnabledCheckCode + '''
149        XDest = ( ((uint64_t) AA64FpOp1P1_uw) << 32) | AA64FpOp1P0_uw;
150    '''
151    fmovRegCoreXIop = InstObjParams("fmov", "FmovRegCoreX", "FpRegRegOp",
152                                     { "code": fmovRegCoreXCode,
153                                       "op_class": "FloatMiscOp" }, [])
154    header_output  += FpRegRegOpDeclare.subst(fmovRegCoreXIop);
155    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegCoreXIop);
156    exec_output    += BasicExecute.subst(fmovRegCoreXIop);
157
158    fmovURegCoreXCode = vfp64EnabledCheckCode + '''
159        XDest = ( ((uint64_t) AA64FpOp1P3_uw) << 32) | AA64FpOp1P2_uw;
160    '''
161    fmovURegCoreXIop = InstObjParams("fmov", "FmovURegCoreX", "FpRegRegOp",
162                                    { "code":     fmovURegCoreXCode,
163                                      "op_class": "FloatMiscOp" }, [])
164    header_output  += FpRegRegOpDeclare.subst(fmovURegCoreXIop);
165    decoder_output += AA64FpRegRegOpConstructor.subst(fmovURegCoreXIop);
166    exec_output    += BasicExecute.subst(fmovURegCoreXIop);
167}};
168
169let {{
170
171    header_output = ""
172    decoder_output = ""
173    exec_output = ""
174
175    singleIntConvCode = vfp64EnabledCheckCode + '''
176        FPSCR fpscr = (FPSCR) FpscrExc;
177        uint32_t cOp1  = AA64FpOp1P0_uw;
178        uint32_t cDest = %(op)s;
179        AA64FpDestP0_uw = cDest;
180        AA64FpDestP1_uw = 0;
181        AA64FpDestP2_uw = 0;
182        AA64FpDestP3_uw = 0;
183        FpscrExc = fpscr;
184    '''
185
186    singleIntConvCode2 = vfp64EnabledCheckCode + '''
187        FPSCR fpscr = (FPSCR) FpscrExc;
188        uint32_t cOp1  = AA64FpOp1P0_uw;
189        uint32_t cOp2  = AA64FpOp2P0_uw;
190        uint32_t cDest = %(op)s;
191        AA64FpDestP0_uw = cDest;
192        AA64FpDestP1_uw = 0;
193        AA64FpDestP2_uw = 0;
194        AA64FpDestP3_uw = 0;
195        FpscrExc = fpscr;
196    '''
197
198    singleBinOp = "binaryOp(fpscr, AA64FpOp1P0, AA64FpOp2P0," + \
199                "%(func)s, fpscr.fz, fpscr.dn, fpscr.rMode)"
200    singleUnaryOp = "unaryOp(fpscr, AA64FpOp1P0, %(func)s, fpscr.fz, fpscr.rMode)"
201
202    doubleIntConvCode = vfp64EnabledCheckCode + '''
203        FPSCR fpscr = (FPSCR) FpscrExc;
204        uint64_t cOp1  = ((uint64_t) AA64FpOp1P1_uw) << 32 | AA64FpOp1P0_uw;
205        uint64_t cDest = %(op)s;
206        AA64FpDestP0_uw = cDest & 0xFFFFFFFF;
207        AA64FpDestP1_uw = cDest >> 32;
208        AA64FpDestP2_uw = 0;
209        AA64FpDestP3_uw = 0;
210        FpscrExc = fpscr;
211    '''
212
213    doubleIntConvCode2 = vfp64EnabledCheckCode + '''
214        FPSCR fpscr = (FPSCR) FpscrExc;
215        uint64_t cOp1  = ((uint64_t) AA64FpOp1P1_uw) << 32 | AA64FpOp1P0_uw;
216        uint64_t cOp2  = ((uint64_t) AA64FpOp2P1_uw) << 32 | AA64FpOp2P0_uw;
217        uint64_t cDest = %(op)s;
218        AA64FpDestP0_uw = cDest & 0xFFFFFFFF;
219        AA64FpDestP1_uw = cDest >> 32;
220        AA64FpDestP2_uw = 0;
221        AA64FpDestP3_uw = 0;
222        FpscrExc = fpscr;
223    '''
224
225    doubleBinOp = '''
226        binaryOp(fpscr, dbl(AA64FpOp1P0_uw, AA64FpOp1P1_uw),
227                        dbl(AA64FpOp2P0_uw, AA64FpOp2P1_uw),
228                        %(func)s, fpscr.fz, fpscr.dn, fpscr.rMode);
229    '''
230    doubleUnaryOp = '''
231        unaryOp(fpscr, dbl(AA64FpOp1P0_uw, AA64FpOp1P1_uw), %(func)s,
232                fpscr.fz, fpscr.rMode)
233    '''
234
235    def buildTernaryFpOp(name, opClass, sOp, dOp):
236        global header_output, decoder_output, exec_output
237        for isDouble in True, False:
238            code = vfp64EnabledCheckCode + '''
239                FPSCR fpscr = (FPSCR) FpscrExc;
240            '''
241            if isDouble:
242                code += '''
243                    uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
244                    uint64_t cOp2 = AA64FpOp2P0_uw | (uint64_t)AA64FpOp2P1_uw << 32;
245                    uint64_t cOp3 = AA64FpOp3P0_uw | (uint64_t)AA64FpOp3P1_uw << 32;
246                    uint64_t cDest;
247                ''' "cDest = " + dOp + ";" + '''
248                    AA64FpDestP0_uw = cDest;
249                    AA64FpDestP1_uw = cDest >> 32;
250                '''
251            else:
252                code += '''
253                    uint32_t cOp1 = AA64FpOp1P0_uw;
254                    uint32_t cOp2 = AA64FpOp2P0_uw;
255                    uint32_t cOp3 = AA64FpOp3P0_uw;
256                    uint32_t cDest;
257                ''' "cDest = " + sOp + ";" + '''
258                    AA64FpDestP0_uw = cDest;
259                    AA64FpDestP1_uw = 0;
260                '''
261            code += '''
262                AA64FpDestP2_uw = 0;
263                AA64FpDestP3_uw = 0;
264                FpscrExc = fpscr;
265            '''
266
267            iop = InstObjParams(name.lower(), name + ("D" if isDouble else "S"),
268                                "FpRegRegRegRegOp",
269                                { "code": code, "op_class": opClass }, [])
270
271            header_output  += AA64FpRegRegRegRegOpDeclare.subst(iop)
272            decoder_output += AA64FpRegRegRegRegOpConstructor.subst(iop)
273            exec_output    += BasicExecute.subst(iop)
274
275    buildTernaryFpOp("FMAdd", "FloatMultAccOp",
276                     "fplibMulAdd<uint32_t>(cOp3, cOp1, cOp2, fpscr)",
277                     "fplibMulAdd<uint64_t>(cOp3, cOp1, cOp2, fpscr)" )
278    buildTernaryFpOp("FMSub", "FloatMultAccOp",
279                     "fplibMulAdd<uint32_t>(cOp3, fplibNeg<uint32_t>(cOp1), cOp2, fpscr)",
280                     "fplibMulAdd<uint64_t>(cOp3, fplibNeg<uint64_t>(cOp1), cOp2, fpscr)" )
281    buildTernaryFpOp("FNMAdd", "FloatMultAccOp",
282                     "fplibMulAdd<uint32_t>(fplibNeg<uint32_t>(cOp3), fplibNeg<uint32_t>(cOp1), cOp2, fpscr)",
283                     "fplibMulAdd<uint64_t>(fplibNeg<uint64_t>(cOp3), fplibNeg<uint64_t>(cOp1), cOp2, fpscr)" )
284    buildTernaryFpOp("FNMSub", "FloatMultAccOp",
285                     "fplibMulAdd<uint32_t>(fplibNeg<uint32_t>(cOp3), cOp1, cOp2, fpscr)",
286                     "fplibMulAdd<uint64_t>(fplibNeg<uint64_t>(cOp3), cOp1, cOp2, fpscr)" )
287
288    def buildBinFpOp(name, Name, base, opClass, singleOp, doubleOp):
289        global header_output, decoder_output, exec_output
290
291        code = singleIntConvCode2 % { "op": singleOp }
292        sIop = InstObjParams(name, Name + "S", base,
293                { "code": code,
294                  "op_class": opClass }, [])
295
296        code = doubleIntConvCode2 % { "op": doubleOp }
297        dIop = InstObjParams(name, Name + "D", base,
298                { "code": code,
299                  "op_class": opClass }, [])
300
301        declareTempl     = eval(         base + "Declare");
302        constructorTempl = eval("AA64" + base + "Constructor");
303
304        for iop in sIop, dIop:
305            header_output  += declareTempl.subst(iop)
306            decoder_output += constructorTempl.subst(iop)
307            exec_output    += BasicExecute.subst(iop)
308
309    buildBinFpOp("fadd", "FAdd", "FpRegRegRegOp", "FloatAddOp",
310                 "fplibAdd<uint32_t>(cOp1, cOp2, fpscr)",
311                 "fplibAdd<uint64_t>(cOp1, cOp2, fpscr)")
312    buildBinFpOp("fsub", "FSub", "FpRegRegRegOp", "FloatAddOp",
313                 "fplibSub<uint32_t>(cOp1, cOp2, fpscr)",
314                 "fplibSub<uint64_t>(cOp1, cOp2, fpscr)")
315    buildBinFpOp("fdiv", "FDiv", "FpRegRegRegOp", "FloatDivOp",
316                 "fplibDiv<uint32_t>(cOp1, cOp2, fpscr)",
317                 "fplibDiv<uint64_t>(cOp1, cOp2, fpscr)")
318    buildBinFpOp("fmul", "FMul", "FpRegRegRegOp", "FloatMultOp",
319                 "fplibMul<uint32_t>(cOp1, cOp2, fpscr)",
320                 "fplibMul<uint64_t>(cOp1, cOp2, fpscr)")
321    buildBinFpOp("fnmul", "FNMul", "FpRegRegRegOp", "FloatMultOp",
322                 "fplibNeg<uint32_t>(fplibMul<uint32_t>(cOp1, cOp2, fpscr))",
323                 "fplibNeg<uint64_t>(fplibMul<uint64_t>(cOp1, cOp2, fpscr))")
324    buildBinFpOp("fmin", "FMin", "FpRegRegRegOp", "FloatCmpOp",
325                 "fplibMin<uint32_t>(cOp1, cOp2, fpscr)",
326                 "fplibMin<uint64_t>(cOp1, cOp2, fpscr)")
327    buildBinFpOp("fmax", "FMax", "FpRegRegRegOp", "FloatCmpOp",
328                 "fplibMax<uint32_t>(cOp1, cOp2, fpscr)",
329                 "fplibMax<uint64_t>(cOp1, cOp2, fpscr)")
330    buildBinFpOp("fminnm", "FMinNM", "FpRegRegRegOp", "FloatCmpOp",
331                 "fplibMinNum<uint32_t>(cOp1, cOp2, fpscr)",
332                 "fplibMinNum<uint64_t>(cOp1, cOp2, fpscr)")
333    buildBinFpOp("fmaxnm", "FMaxNM", "FpRegRegRegOp", "FloatCmpOp",
334                 "fplibMaxNum<uint32_t>(cOp1, cOp2, fpscr)",
335                 "fplibMaxNum<uint64_t>(cOp1, cOp2, fpscr)")
336
337    def buildUnaryFpOp(name, Name, base, opClass, singleOp, doubleOp = None):
338        if doubleOp is None:
339            doubleOp = singleOp
340        global header_output, decoder_output, exec_output
341
342        code = singleIntConvCode % { "op": singleOp }
343        sIop = InstObjParams(name, Name + "S", base,
344                { "code": code,
345                  "op_class": opClass }, [])
346        code = doubleIntConvCode % { "op": doubleOp }
347        dIop = InstObjParams(name, Name + "D", base,
348                { "code": code,
349                  "op_class": opClass }, [])
350
351        declareTempl     = eval(         base + "Declare");
352        constructorTempl = eval("AA64" + base + "Constructor");
353
354        for iop in sIop, dIop:
355            header_output  += declareTempl.subst(iop)
356            decoder_output += constructorTempl.subst(iop)
357            exec_output    += BasicExecute.subst(iop)
358
359    buildUnaryFpOp("fsqrt", "FSqrt", "FpRegRegOp", "FloatSqrtOp",
360                   "fplibSqrt<uint32_t>(cOp1, fpscr)", "fplibSqrt<uint64_t>(cOp1, fpscr)")
361
362    def buildSimpleUnaryFpOp(name, Name, base, opClass, singleOp,
363                             doubleOp = None, isIntConv = True):
364        if doubleOp is None:
365            doubleOp = singleOp
366        global header_output, decoder_output, exec_output
367
368        if isIntConv:
369            sCode = singleIntConvCode
370            dCode = doubleIntConvCode
371        else:
372            sCode = singleCode
373            dCode = doubleCode
374
375        for code, op, suffix in [[sCode, singleOp, "S"],
376                                 [dCode, doubleOp, "D"]]:
377            iop = InstObjParams(name, Name + suffix, base,
378                { "code": code % { "op": op },
379                  "op_class": opClass }, [])
380
381            declareTempl     = eval(         base + "Declare");
382            constructorTempl = eval("AA64" + base + "Constructor");
383
384            header_output  += declareTempl.subst(iop)
385            decoder_output += constructorTempl.subst(iop)
386            exec_output    += BasicExecute.subst(iop)
387
388    buildSimpleUnaryFpOp("fneg", "FNeg", "FpRegRegOp", "FloatMiscOp",
389                         "fplibNeg<uint32_t>(cOp1)", "fplibNeg<uint64_t>(cOp1)")
390    buildSimpleUnaryFpOp("fabs", "FAbs", "FpRegRegOp", "FloatMiscOp",
391                         "fplibAbs<uint32_t>(cOp1)", "fplibAbs<uint64_t>(cOp1)")
392    buildSimpleUnaryFpOp("frintn", "FRIntN", "FpRegRegOp", "FloatMiscOp",
393                         "fplibRoundInt<uint32_t>(cOp1, FPRounding_TIEEVEN, false, fpscr)",
394                         "fplibRoundInt<uint64_t>(cOp1, FPRounding_TIEEVEN, false, fpscr)")
395    buildSimpleUnaryFpOp("frintp", "FRIntP", "FpRegRegOp", "FloatMiscOp",
396                         "fplibRoundInt<uint32_t>(cOp1, FPRounding_POSINF, false, fpscr)",
397                         "fplibRoundInt<uint64_t>(cOp1, FPRounding_POSINF, false, fpscr)")
398    buildSimpleUnaryFpOp("frintm", "FRIntM", "FpRegRegOp", "FloatMiscOp",
399                         "fplibRoundInt<uint32_t>(cOp1, FPRounding_NEGINF, false, fpscr)",
400                         "fplibRoundInt<uint64_t>(cOp1, FPRounding_NEGINF, false, fpscr)")
401    buildSimpleUnaryFpOp("frintz", "FRIntZ", "FpRegRegOp", "FloatMiscOp",
402                         "fplibRoundInt<uint32_t>(cOp1, FPRounding_ZERO, false, fpscr)",
403                         "fplibRoundInt<uint64_t>(cOp1, FPRounding_ZERO, false, fpscr)")
404    buildSimpleUnaryFpOp("frinta", "FRIntA", "FpRegRegOp", "FloatMiscOp",
405                         "fplibRoundInt<uint32_t>(cOp1, FPRounding_TIEAWAY, false, fpscr)",
406                         "fplibRoundInt<uint64_t>(cOp1, FPRounding_TIEAWAY, false, fpscr)")
407    buildSimpleUnaryFpOp("frinti", "FRIntI", "FpRegRegOp", "FloatMiscOp",
408                         "fplibRoundInt<uint32_t>(cOp1, FPCRRounding(fpscr), false, fpscr)",
409                         "fplibRoundInt<uint64_t>(cOp1, FPCRRounding(fpscr), false, fpscr)")
410    buildSimpleUnaryFpOp("frintx", "FRIntX", "FpRegRegOp", "FloatMiscOp",
411                         "fplibRoundInt<uint32_t>(cOp1, FPCRRounding(fpscr), true, fpscr)",
412                         "fplibRoundInt<uint64_t>(cOp1, FPCRRounding(fpscr), true, fpscr)")
413}};
414
415let {{
416
417    header_output = ""
418    decoder_output = ""
419    exec_output = ""
420
421    # Creates the integer to floating point instructions, including variants for
422    # signed/unsigned, float/double, etc
423    for regL, regOpL, width in [["W", "w", 32],
424                                ["X", "d", 64]]:
425        for isDouble in True, False:
426            for us, usCode in [["U", "uint%d_t cSrc = %sOp1_u%s;" %(width, regL, regOpL)],
427                               ["S", "int%d_t  cSrc = %sOp1_u%s;" %(width, regL, regOpL)]]:
428                fcvtIntFpDCode = vfp64EnabledCheckCode + '''
429                    FPSCR fpscr = (FPSCR) FpscrExc;
430                    %s
431                ''' %(usCode)
432
433                if isDouble:
434                    fcvtIntFpDCode += '''
435                        uint64_t cDest = fplibFixedToFP<uint64_t>(cSrc, 0,
436                            %s, FPCRRounding(fpscr), fpscr);
437                        AA64FpDestP0_uw = cDest;
438                        AA64FpDestP1_uw = cDest >> 32;
439                    ''' % ("true" if us == "U" else "false")
440                else:
441                    fcvtIntFpDCode += '''
442                        uint32_t cDest = fplibFixedToFP<uint32_t>(cSrc, 0,
443                            %s, FPCRRounding(fpscr), fpscr);
444                        AA64FpDestP0_uw = cDest;
445                        AA64FpDestP1_uw = 0;
446                    ''' % ("true" if us == "U" else "false")
447                fcvtIntFpDCode += '''
448                    AA64FpDestP2_uw = 0;
449                    AA64FpDestP3_uw = 0;
450                    FpscrExc = fpscr;
451                '''
452
453                instName = "Fcvt%s%sIntFp%s" %(regL, us, "D" if isDouble else "S")
454                mnem     = "%scvtf" %(us.lower())
455                fcvtIntFpDIop = InstObjParams(mnem, instName, "FpRegRegOp",
456                                              { "code": fcvtIntFpDCode,
457                                                "op_class": "FloatCvtOp" }, [])
458                header_output  += FpRegRegOpDeclare.subst(fcvtIntFpDIop);
459                decoder_output += AA64FpRegRegOpConstructor.subst(fcvtIntFpDIop);
460                exec_output    += BasicExecute.subst(fcvtIntFpDIop);
461
462    # Generates the floating point to integer conversion instructions in various
463    # variants, eg signed/unsigned
464    def buildFpCvtIntOp(isDouble, isSigned, isXReg):
465        global header_output, decoder_output, exec_output
466
467        for rmode, roundingMode in [["N", "FPRounding_TIEEVEN"],
468                                    ["P", "FPRounding_POSINF"],
469                                    ["M", "FPRounding_NEGINF"],
470                                    ["Z", "FPRounding_ZERO"],
471                                    ["A", "FPRounding_TIEAWAY"]]:
472            fcvtFpIntCode = vfp64EnabledCheckCode + '''
473                FPSCR fpscr = (FPSCR) FpscrExc;'''
474            if isDouble:
475                fcvtFpIntCode += '''
476                uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
477                '''
478            else:
479                fcvtFpIntCode += "uint32_t cOp1 = AA64FpOp1P0_uw;"
480
481            fcvtFpIntCode += '''
482                %sDest = fplibFPToFixed<uint%s_t, uint%s_t>(cOp1, 0, %s, %s, fpscr);
483                FpscrExc = fpscr;
484            ''' %("X"      if isXReg   else "W",
485                  "64"     if isDouble else "32",
486                  "64"     if isXReg   else "32",
487                  "false"  if isSigned else "true",
488                  roundingMode)
489
490            instName = "FcvtFp%sInt%s%s%s" %("S" if isSigned else "U",
491                                             "X" if isXReg   else "W",
492                                             "D" if isDouble else "S", rmode)
493            mnem     = "fcvt%s%s" %(rmode, "s" if isSigned else "u")
494            fcvtFpIntIop = InstObjParams(mnem, instName, "FpRegRegOp",
495                                        { "code": fcvtFpIntCode,
496                                        "op_class": "FloatCvtOp" }, [])
497            header_output  += FpRegRegOpDeclare.subst(fcvtFpIntIop);
498            decoder_output += FpRegRegOpConstructor.subst(fcvtFpIntIop);
499            exec_output    += BasicExecute.subst(fcvtFpIntIop);
500
501    # Now actually do the building with the different variants
502    for isDouble in True, False:
503       for isSigned in True, False:
504           for isXReg in True, False:
505             buildFpCvtIntOp(isDouble, isSigned, isXReg)
506
507    fcvtFpSFpDCode = vfp64EnabledCheckCode + '''
508        FPSCR fpscr = (FPSCR) FpscrExc;
509        uint64_t cDest = fplibConvert<uint32_t, uint64_t>(AA64FpOp1P0_uw,
510            FPCRRounding(fpscr), fpscr);
511        AA64FpDestP0_uw = cDest;
512        AA64FpDestP1_uw = cDest >> 32;
513        AA64FpDestP2_uw = 0;
514        AA64FpDestP3_uw = 0;
515        FpscrExc = fpscr;
516    '''
517    fcvtFpSFpDIop = InstObjParams("fcvt", "FCvtFpSFpD", "FpRegRegOp",
518                                     { "code": fcvtFpSFpDCode,
519                                       "op_class": "FloatCvtOp" }, [])
520    header_output  += FpRegRegOpDeclare.subst(fcvtFpSFpDIop);
521    decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpSFpDIop);
522    exec_output    += BasicExecute.subst(fcvtFpSFpDIop);
523
524    fcvtFpDFpSCode = vfp64EnabledCheckCode + '''
525        FPSCR fpscr = (FPSCR) FpscrExc;
526        uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
527        AA64FpDestP0_uw = fplibConvert<uint64_t, uint32_t>(cOp1,
528            FPCRRounding(fpscr), fpscr);
529        AA64FpDestP1_uw = 0;
530        AA64FpDestP2_uw = 0;
531        AA64FpDestP3_uw = 0;
532        FpscrExc = fpscr;
533    '''
534    fcvtFpDFpSIop = InstObjParams("fcvt", "FcvtFpDFpS", "FpRegRegOp",
535                                 {"code":     fcvtFpDFpSCode,
536                                  "op_class": "FloatCvtOp" }, [])
537    header_output  += FpRegRegOpDeclare.subst(fcvtFpDFpSIop);
538    decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpDFpSIop);
539    exec_output    += BasicExecute.subst(fcvtFpDFpSIop);
540
541    # Half precision to single or double precision conversion
542    for isDouble in True, False:
543        code = vfp64EnabledCheckCode + '''
544            FPSCR fpscr = (FPSCR) FpscrExc;
545            %s cDest = fplibConvert<uint16_t, uint%s_t>(AA64FpOp1P0_uw,
546                FPCRRounding(fpscr), fpscr);
547        ''' % ("uint64_t" if isDouble else "uint32_t",
548               "64" if isDouble else "32")
549        if isDouble:
550            code += '''
551                AA64FpDestP0_uw = cDest;
552                AA64FpDestP1_uw = cDest >> 32;
553            '''
554        else:
555            code += '''
556                AA64FpDestP0_uw = cDest;
557                AA64FpDestP1_uw = 0;
558            '''
559        code += '''
560            AA64FpDestP2_uw = 0;
561            AA64FpDestP3_uw = 0;
562            FpscrExc = fpscr;
563        '''
564
565        instName = "FcvtFpHFp%s" %("D" if isDouble else "S")
566        fcvtFpHFpIop = InstObjParams("fcvt", instName, "FpRegRegOp",
567                                     { "code": code,
568                                       "op_class": "FloatCvtOp" }, [])
569        header_output  += FpRegRegOpDeclare.subst(fcvtFpHFpIop);
570        decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpHFpIop);
571        exec_output    += BasicExecute.subst(fcvtFpHFpIop);
572
573    # single or double precision to Half precision conversion
574    for isDouble in True, False:
575        code = vfp64EnabledCheckCode + '''
576            FPSCR fpscr = (FPSCR) FpscrExc;
577            %s;
578            AA64FpDestP0_uw = fplibConvert<uint%s_t, uint16_t>(cOp1,
579                FPCRRounding(fpscr), fpscr);
580            AA64FpDestP1_uw = 0;
581            AA64FpDestP2_uw = 0;
582            AA64FpDestP3_uw = 0;
583            FpscrExc = fpscr;
584        ''' % ("uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32"
585               if isDouble else "uint32_t cOp1 = AA64FpOp1P0_uw",
586               "64" if isDouble else "32")
587
588        instName = "FcvtFp%sFpH" %("D" if isDouble else "S")
589        fcvtFpFpHIop = InstObjParams("fcvt", instName, "FpRegRegOp",
590                                     { "code": code,
591                                       "op_class": "FloatCvtOp" }, [])
592        header_output  += FpRegRegOpDeclare.subst(fcvtFpFpHIop);
593        decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpFpHIop);
594        exec_output    += BasicExecute.subst(fcvtFpFpHIop);
595
596    # Build the various versions of the floating point compare instructions
597    def buildFCmpOp(isQuiet, isDouble, isImm):
598        global header_output, decoder_output, exec_output
599
600        fcmpCode = vfp64EnabledCheckCode + '''
601            FPSCR fpscr = (FPSCR) FpscrExc;
602            %s cOp1 = %s;
603        ''' % ("uint64_t" if isDouble else "uint32_t",
604               "AA64FpDestP0_uw | (uint64_t)AA64FpDestP1_uw << 32"
605               if isDouble else "AA64FpDestP0_uw")
606        if isImm:
607            fcmpCode += '''
608                %s cOp2 = imm;
609            ''' % ("uint64_t" if isDouble else "uint32_t")
610        else:
611            fcmpCode += '''
612                %s cOp2  = %s;
613            ''' % ("uint64_t" if isDouble else "uint32_t",
614                   "AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32"
615                   if isDouble else "AA64FpOp1P0_uw")
616        fcmpCode += '''
617            int cc = fplibCompare<uint%s_t>(cOp1, cOp2, %s, fpscr);
618            CondCodesNZ = cc >> 2 & 3;
619            CondCodesC = cc >> 1 & 1;
620            CondCodesV = cc & 1;
621            FpCondCodes = fpscr & FpCondCodesMask;
622            FpscrExc    = fpscr;
623        ''' % ("64" if isDouble else "32", "false" if isQuiet else "true")
624
625        typeName = "Imm" if isImm else "Reg"
626        instName = "FCmp%s%s%s" %(""  if isQuiet  else "E", typeName,
627                                  "D" if isDouble else "S")
628        fcmpIop = InstObjParams("fcmp%s" %(""  if isQuiet else "e"), instName,
629                                "FpReg%sOp" %(typeName),
630                               {"code":     fcmpCode,
631                                "op_class": "FloatCmpOp"}, [])
632
633        declareTemp     = eval("FpReg%sOpDeclare"         %(typeName));
634        constructorTemp = eval("AA64FpReg%sOpConstructor" %(typeName));
635        header_output  += declareTemp.subst(fcmpIop);
636        decoder_output += constructorTemp.subst(fcmpIop);
637        exec_output    += BasicExecute.subst(fcmpIop);
638
639    for isQuiet in True, False:
640        for isDouble in True, False:
641            for isImm in True, False:
642                buildFCmpOp(isQuiet, isDouble, isImm)
643
644    # Build the various versions of the conditional floating point compare
645    # instructions
646    def buildFCCmpOp(isQuiet, isDouble):
647        global header_output, decoder_output, exec_output
648
649        fccmpCode = vfp64EnabledCheckCode + '''
650            FPSCR fpscr = (FPSCR) FpscrExc;
651            if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
652                %s cOp1 = %s;
653                %s cOp2 = %s;
654                int cc = fplibCompare<uint%s_t>(cOp1, cOp2, %s, fpscr);
655                CondCodesNZ = cc >> 2 & 3;
656                CondCodesC = cc >> 1 & 1;
657                CondCodesV = cc & 1;
658            } else {
659                CondCodesNZ = (defCc >> 2) & 0x3;
660                CondCodesC  = (defCc >> 1) & 0x1;
661                CondCodesV  = defCc & 0x1;
662            }
663            FpCondCodes = fpscr & FpCondCodesMask;
664            FpscrExc    = fpscr;
665        ''' % ("uint64_t" if isDouble else "uint32_t",
666               "AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32"
667               if isDouble else "AA64FpOp1P0_uw",
668               "uint64_t" if isDouble else "uint32_t",
669               "AA64FpOp2P0_uw | (uint64_t)AA64FpOp2P1_uw << 32"
670               if isDouble else "AA64FpOp2P0_uw",
671               "64" if isDouble else "32", "false" if isQuiet else "true")
672
673        instName = "FCCmp%sReg%s" %(""  if isQuiet  else "E",
674                                    "D" if isDouble else "S")
675        fccmpIop = InstObjParams("fccmp%s" %(""  if isQuiet  else "e"),
676                                 instName, "FpCondCompRegOp",
677                                {"code":           fccmpCode,
678                                 "op_class":       "FloatCmpOp"}, [])
679        header_output  += DataXCondCompRegDeclare.subst(fccmpIop);
680        decoder_output += DataXCondCompRegConstructor.subst(fccmpIop);
681        exec_output    += BasicExecute.subst(fccmpIop);
682
683    for isQuiet in True, False:
684        for isDouble in True, False:
685            buildFCCmpOp(isQuiet, isDouble)
686
687}};
688
689let {{
690
691    header_output = ""
692    decoder_output = ""
693    exec_output = ""
694
695    # Generates the variants of the floating to fixed point instructions
696    def buildFpCvtFixedOp(isSigned, isDouble, isXReg):
697        global header_output, decoder_output, exec_output
698
699        fcvtFpFixedCode = vfp64EnabledCheckCode + '''
700            FPSCR fpscr = (FPSCR) FpscrExc;
701        '''
702        if isDouble:
703            fcvtFpFixedCode += '''
704                uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
705            '''
706        else:
707            fcvtFpFixedCode += "uint32_t cOp1 = AA64FpOp1P0_uw;"
708        fcvtFpFixedCode += '''
709            %sDest = fplibFPToFixed<uint%s_t, uint%s_t>(cOp1, 64 - imm, %s,
710                FPRounding_ZERO, fpscr);
711            FpscrExc = fpscr;
712        ''' %("X"      if isXReg   else "W",
713              "64"     if isDouble else "32",
714              "64"     if isXReg   else "32",
715              "false"  if isSigned else "true")
716
717        instName = "FcvtFp%sFixed%s%s" %("S" if isSigned else "U",
718                                         "D" if isDouble else "S",
719                                         "X" if isXReg   else "W")
720        mnem = "fcvtz%s" %("s" if isSigned else "u")
721        fcvtFpFixedIop = InstObjParams(mnem, instName, "FpRegRegImmOp",
722                                       { "code": fcvtFpFixedCode,
723                                         "op_class": "FloatCvtOp" }, [])
724        header_output  += FpRegRegImmOpDeclare.subst(fcvtFpFixedIop);
725        decoder_output += AA64FpRegRegImmOpConstructor.subst(fcvtFpFixedIop);
726        exec_output    += BasicExecute.subst(fcvtFpFixedIop);
727
728    # Generates the variants of the fixed to floating point instructions
729    def buildFixedCvtFpOp(isSigned, isDouble, isXReg):
730        global header_output, decoder_output, exec_output
731
732        srcRegType = "X" if isXReg   else "W"
733        fcvtFixedFpCode = vfp64EnabledCheckCode + '''
734            FPSCR fpscr = (FPSCR) FpscrExc;
735            %s result = fplibFixedToFP<uint%s_t>((%s%s_t)%sOp1, 64 - imm,
736                %s, FPCRRounding(fpscr), fpscr);
737        ''' %("uint64_t" if isDouble else "uint32_t",
738              "64" if isDouble else "32",
739              "int" if isSigned else "uint", "64" if isXReg else "32",
740              srcRegType,
741              "false" if isSigned else "true")
742        if isDouble:
743            fcvtFixedFpCode += '''
744                AA64FpDestP0_uw = result;
745                AA64FpDestP1_uw = result >> 32;
746            '''
747        else:
748            fcvtFixedFpCode += '''
749                AA64FpDestP0_uw = result;
750                AA64FpDestP1_uw = 0;
751            '''
752        fcvtFixedFpCode += '''
753            AA64FpDestP2_uw = 0;
754            AA64FpDestP3_uw = 0;
755            FpscrExc = fpscr;
756        '''
757
758        instName = "Fcvt%sFixedFp%s%s" %("S" if isSigned else "U",
759                                         "D" if isDouble else "S",
760                                         srcRegType)
761        mnem = "%scvtf" %("s" if isSigned else "u")
762        fcvtFixedFpIop = InstObjParams(mnem, instName, "FpRegRegImmOp",
763                                       { "code":     fcvtFixedFpCode,
764                                         "op_class": "FloatCvtOp" }, [])
765        header_output  += FpRegRegImmOpDeclare.subst(fcvtFixedFpIop);
766        decoder_output += FpRegRegImmOpConstructor.subst(fcvtFixedFpIop);
767        exec_output    += BasicExecute.subst(fcvtFixedFpIop);
768
769    # loop over the variants building the instructions for each
770    for isXReg in True, False:
771        for isDouble in True, False:
772            for isSigned in True, False:
773                buildFpCvtFixedOp(isSigned, isDouble, isXReg)
774                buildFixedCvtFpOp(isSigned, isDouble, isXReg)
775}};
776
777let {{
778
779    header_output  = ""
780    decoder_output = ""
781    exec_output    = ""
782
783    for isDouble in True, False:
784        code = '''
785            if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
786                AA64FpDestP0_uw = AA64FpOp1P0_uw;
787        '''
788        if isDouble:
789            code += '''
790                    AA64FpDestP1_uw = AA64FpOp1P1_uw;
791                } else {
792                    AA64FpDestP0_uw = AA64FpOp2P0_uw;
793                    AA64FpDestP1_uw = AA64FpOp2P1_uw;
794                }
795            '''
796        else:
797            code += '''
798                } else {
799                    AA64FpDestP0_uw = AA64FpOp2P0_uw;
800                }
801                AA64FpDestP1_uw = 0;
802            '''
803        code += '''
804            AA64FpDestP2_uw = 0;
805            AA64FpDestP3_uw = 0;
806        '''
807
808        iop = InstObjParams("fcsel", "FCSel%s" %("D" if isDouble else "S"),
809                            "FpCondSelOp", { "code":     code,
810                                             "op_class": "FloatCvtOp" })
811        header_output  += DataXCondSelDeclare.subst(iop)
812        decoder_output += DataXCondSelConstructor.subst(iop)
813        exec_output    += BasicExecute.subst(iop)
814}};
815