1// -*- mode:c++ -*-
2
3// Copyright (c) 2012-2013, 2016-2018 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    zeroSveVecRegUpperPartCode = '''
48        ArmISA::ISA::zeroSveVecRegUpperPart(%s,
49            ArmStaticInst::getCurSveVecLen<uint64_t>(xc->tcBase()));
50    '''
51
52    fmovImmSCode = vfp64EnabledCheckCode + '''
53        AA64FpDestP0_uw = bits(imm, 31, 0);
54        AA64FpDestP1_uw = 0;
55        AA64FpDestP2_uw = 0;
56        AA64FpDestP3_uw = 0;
57    '''
58    fmovImmSIop = InstObjParams("fmov", "FmovImmS", "FpRegImmOp",
59                                { "code": fmovImmSCode,
60                                  "op_class": "FloatMiscOp" }, [])
61    fmovImmSIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
62    header_output  += FpRegImmOpDeclare.subst(fmovImmSIop);
63    decoder_output += FpRegImmOpConstructor.subst(fmovImmSIop);
64    exec_output    += BasicExecute.subst(fmovImmSIop);
65
66    fmovImmDCode = vfp64EnabledCheckCode + '''
67        AA64FpDestP0_uw = bits(imm, 31, 0);
68        AA64FpDestP1_uw = bits(imm, 63, 32);
69        AA64FpDestP2_uw = 0;
70        AA64FpDestP3_uw = 0;
71    '''
72    fmovImmDIop = InstObjParams("fmov", "FmovImmD", "FpRegImmOp",
73                                { "code": fmovImmDCode,
74                                  "op_class": "FloatMiscOp" }, [])
75    fmovImmDIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
76    header_output  += FpRegImmOpDeclare.subst(fmovImmDIop);
77    decoder_output += AA64FpRegImmOpConstructor.subst(fmovImmDIop);
78    exec_output    += BasicExecute.subst(fmovImmDIop);
79
80    fmovRegSCode = vfp64EnabledCheckCode + '''
81        AA64FpDestP0_uw = AA64FpOp1P0_uw;
82        AA64FpDestP1_uw = 0;
83        AA64FpDestP2_uw = 0;
84        AA64FpDestP3_uw = 0;
85    '''
86    fmovRegSIop = InstObjParams("fmov", "FmovRegS", "FpRegRegOp",
87                                { "code": fmovRegSCode,
88                                  "op_class": "FloatMiscOp" }, [])
89    fmovRegSIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
90    header_output  += FpRegRegOpDeclare.subst(fmovRegSIop);
91    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegSIop);
92    exec_output    += BasicExecute.subst(fmovRegSIop);
93
94    fmovRegDCode = vfp64EnabledCheckCode + '''
95        AA64FpDestP0_uw = AA64FpOp1P0_uw;
96        AA64FpDestP1_uw = AA64FpOp1P1_uw;
97        AA64FpDestP2_uw = 0;
98        AA64FpDestP3_uw = 0;
99    '''
100    fmovRegDIop = InstObjParams("fmov", "FmovRegD", "FpRegRegOp",
101                                { "code": fmovRegDCode,
102                                  "op_class": "FloatMiscOp" }, [])
103    fmovRegDIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
104    header_output  += FpRegRegOpDeclare.subst(fmovRegDIop);
105    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegDIop);
106    exec_output    += BasicExecute.subst(fmovRegDIop);
107
108    fmovCoreRegWCode = vfp64EnabledCheckCode + '''
109        AA64FpDestP0_uw = WOp1_uw;
110        AA64FpDestP1_uw = 0;
111        AA64FpDestP2_uw = 0;
112        AA64FpDestP3_uw = 0;
113    '''
114    fmovCoreRegWIop = InstObjParams("fmov", "FmovCoreRegW", "FpRegRegOp",
115                                    { "code": fmovCoreRegWCode,
116                                      "op_class": "FloatMiscOp" }, [])
117    fmovCoreRegWIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
118        "AA64FpDest"
119    header_output  += FpRegRegOpDeclare.subst(fmovCoreRegWIop);
120    decoder_output += AA64FpRegRegOpConstructor.subst(fmovCoreRegWIop);
121    exec_output    += BasicExecute.subst(fmovCoreRegWIop);
122
123    fmovCoreRegXCode = vfp64EnabledCheckCode + '''
124        AA64FpDestP0_uw = XOp1_ud;
125        AA64FpDestP1_uw = XOp1_ud >> 32;
126        AA64FpDestP2_uw = 0;
127        AA64FpDestP3_uw = 0;
128    '''
129    fmovCoreRegXIop = InstObjParams("fmov", "FmovCoreRegX", "FpRegRegOp",
130                                    { "code": fmovCoreRegXCode,
131                                      "op_class": "FloatMiscOp" }, [])
132    fmovCoreRegXIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
133        "AA64FpDest"
134    header_output  += FpRegRegOpDeclare.subst(fmovCoreRegXIop);
135    decoder_output += AA64FpRegRegOpConstructor.subst(fmovCoreRegXIop);
136    exec_output    += BasicExecute.subst(fmovCoreRegXIop);
137
138    fmovUCoreRegXCode = vfp64EnabledCheckCode + '''
139        /* Explicitly merge with previous value */
140        AA64FpDestP0_uw = AA64FpDestP0_uw;
141        AA64FpDestP1_uw = AA64FpDestP1_uw;
142        AA64FpDestP2_uw = XOp1_ud;
143        AA64FpDestP3_uw = XOp1_ud >> 32;'''
144    fmovUCoreRegXIop = InstObjParams("fmov", "FmovUCoreRegX", "FpRegRegOp",
145                                    { "code": fmovUCoreRegXCode,
146                                      "op_class": "FloatMiscOp" }, [])
147    fmovUCoreRegXIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
148        "AA64FpDest"
149    header_output  += FpRegRegOpDeclare.subst(fmovUCoreRegXIop);
150    decoder_output += AA64FpRegRegOpConstructor.subst(fmovUCoreRegXIop);
151    exec_output    += BasicExecute.subst(fmovUCoreRegXIop);
152
153    fmovRegCoreWCode = vfp64EnabledCheckCode + '''
154        WDest = AA64FpOp1P0_uw;
155    '''
156    fmovRegCoreWIop = InstObjParams("fmov", "FmovRegCoreW", "FpRegRegOp",
157                                     { "code": fmovRegCoreWCode,
158                                       "op_class": "FloatMiscOp" }, [])
159    header_output  += FpRegRegOpDeclare.subst(fmovRegCoreWIop);
160    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegCoreWIop);
161    exec_output    += BasicExecute.subst(fmovRegCoreWIop);
162
163    fmovRegCoreXCode = vfp64EnabledCheckCode + '''
164        XDest = ( ((uint64_t) AA64FpOp1P1_uw) << 32) | AA64FpOp1P0_uw;
165    '''
166    fmovRegCoreXIop = InstObjParams("fmov", "FmovRegCoreX", "FpRegRegOp",
167                                     { "code": fmovRegCoreXCode,
168                                       "op_class": "FloatMiscOp" }, [])
169    header_output  += FpRegRegOpDeclare.subst(fmovRegCoreXIop);
170    decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegCoreXIop);
171    exec_output    += BasicExecute.subst(fmovRegCoreXIop);
172
173    fmovURegCoreXCode = vfp64EnabledCheckCode + '''
174        XDest = ( ((uint64_t) AA64FpOp1P3_uw) << 32) | AA64FpOp1P2_uw;
175    '''
176    fmovURegCoreXIop = InstObjParams("fmov", "FmovURegCoreX", "FpRegRegOp",
177                                    { "code":     fmovURegCoreXCode,
178                                      "op_class": "FloatMiscOp" }, [])
179    header_output  += FpRegRegOpDeclare.subst(fmovURegCoreXIop);
180    decoder_output += AA64FpRegRegOpConstructor.subst(fmovURegCoreXIop);
181    exec_output    += BasicExecute.subst(fmovURegCoreXIop);
182}};
183
184let {{
185
186    header_output = ""
187    decoder_output = ""
188    exec_output = ""
189
190    halfIntConvCode = vfp64EnabledCheckCode + '''
191        FPSCR fpscr = (FPSCR) FpscrExc;
192        uint16_t cOp1  = AA64FpOp1P0_uw;
193        uint16_t cDest = %(op)s;
194        AA64FpDestP0_uw = cDest;
195        AA64FpDestP1_uw = 0;
196        AA64FpDestP2_uw = 0;
197        AA64FpDestP3_uw = 0;
198        FpscrExc = fpscr;
199    '''
200
201    halfIntConvCode2 = vfp64EnabledCheckCode + '''
202        FPSCR fpscr = (FPSCR) FpscrExc;
203        uint16_t cOp1  = AA64FpOp1P0_uw;
204        uint16_t cOp2  = AA64FpOp2P0_uw;
205        uint16_t cDest = %(op)s;
206        AA64FpDestP0_uw = cDest;
207        AA64FpDestP1_uw = 0;
208        AA64FpDestP2_uw = 0;
209        AA64FpDestP3_uw = 0;
210        FpscrExc = fpscr;
211    '''
212
213    halfBinOp = "binaryOp(fpscr, AA64FpOp1P0, AA64FpOp2P0," + \
214                "%(func)s, fpscr.fz, fpscr.dn, fpscr.rMode)"
215    halfUnaryOp = "unaryOp(fpscr, AA64FpOp1P0," + \
216                  "%(func)s, fpscr.fz, fpscr.rMode)"
217
218    singleIntConvCode = vfp64EnabledCheckCode + '''
219        FPSCR fpscr = (FPSCR) FpscrExc;
220        uint32_t cOp1  = AA64FpOp1P0_uw;
221        uint32_t cDest = %(op)s;
222        AA64FpDestP0_uw = cDest;
223        AA64FpDestP1_uw = 0;
224        AA64FpDestP2_uw = 0;
225        AA64FpDestP3_uw = 0;
226        FpscrExc = fpscr;
227    '''
228
229    singleIntConvCode2 = vfp64EnabledCheckCode + '''
230        FPSCR fpscr = (FPSCR) FpscrExc;
231        uint32_t cOp1  = AA64FpOp1P0_uw;
232        uint32_t cOp2  = AA64FpOp2P0_uw;
233        uint32_t cDest = %(op)s;
234        AA64FpDestP0_uw = cDest;
235        AA64FpDestP1_uw = 0;
236        AA64FpDestP2_uw = 0;
237        AA64FpDestP3_uw = 0;
238        FpscrExc = fpscr;
239    '''
240
241    singleBinOp = "binaryOp(fpscr, AA64FpOp1P0, AA64FpOp2P0," + \
242                "%(func)s, fpscr.fz, fpscr.dn, fpscr.rMode)"
243    singleUnaryOp = "unaryOp(fpscr, AA64FpOp1P0, %(func)s, fpscr.fz, fpscr.rMode)"
244
245    doubleIntConvCode = vfp64EnabledCheckCode + '''
246        FPSCR fpscr = (FPSCR) FpscrExc;
247        uint64_t cOp1  = ((uint64_t) AA64FpOp1P1_uw) << 32 | AA64FpOp1P0_uw;
248        uint64_t cDest = %(op)s;
249        AA64FpDestP0_uw = cDest & 0xFFFFFFFF;
250        AA64FpDestP1_uw = cDest >> 32;
251        AA64FpDestP2_uw = 0;
252        AA64FpDestP3_uw = 0;
253        FpscrExc = fpscr;
254    '''
255
256    doubleIntConvCode2 = vfp64EnabledCheckCode + '''
257        FPSCR fpscr = (FPSCR) FpscrExc;
258        uint64_t cOp1  = ((uint64_t) AA64FpOp1P1_uw) << 32 | AA64FpOp1P0_uw;
259        uint64_t cOp2  = ((uint64_t) AA64FpOp2P1_uw) << 32 | AA64FpOp2P0_uw;
260        uint64_t cDest = %(op)s;
261        AA64FpDestP0_uw = cDest & 0xFFFFFFFF;
262        AA64FpDestP1_uw = cDest >> 32;
263        AA64FpDestP2_uw = 0;
264        AA64FpDestP3_uw = 0;
265        FpscrExc = fpscr;
266    '''
267
268    doubleBinOp = '''
269        binaryOp(fpscr, dbl(AA64FpOp1P0_uw, AA64FpOp1P1_uw),
270                        dbl(AA64FpOp2P0_uw, AA64FpOp2P1_uw),
271                        %(func)s, fpscr.fz, fpscr.dn, fpscr.rMode);
272    '''
273    doubleUnaryOp = '''
274        unaryOp(fpscr, dbl(AA64FpOp1P0_uw, AA64FpOp1P1_uw), %(func)s,
275                fpscr.fz, fpscr.rMode)
276    '''
277
278    def buildTernaryFpOp(name, opClass, hOp, sOp, dOp):
279        global header_output, decoder_output, exec_output
280        for suffix in "D", "S", "H":
281            code = vfp64EnabledCheckCode + '''
282                FPSCR fpscr = (FPSCR) FpscrExc;
283            '''
284            if suffix == "H":
285                code += '''
286                    uint16_t cOp1 = AA64FpOp1P0_uw;
287                    uint16_t cOp2 = AA64FpOp2P0_uw;
288                    uint16_t cOp3 = AA64FpOp3P0_uw;
289                    uint16_t cDest;
290                ''' "cDest = " + hOp + ";" + '''
291                    AA64FpDestP0_uw = cDest;
292                    AA64FpDestP1_uw = 0;
293                '''
294            elif suffix == "S":
295                code += '''
296                    uint32_t cOp1 = AA64FpOp1P0_uw;
297                    uint32_t cOp2 = AA64FpOp2P0_uw;
298                    uint32_t cOp3 = AA64FpOp3P0_uw;
299                    uint32_t cDest;
300                ''' "cDest = " + sOp + ";" + '''
301                    AA64FpDestP0_uw = cDest;
302                    AA64FpDestP1_uw = 0;
303                '''
304            elif suffix == "D":
305                code += '''
306                    uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
307                    uint64_t cOp2 = AA64FpOp2P0_uw | (uint64_t)AA64FpOp2P1_uw << 32;
308                    uint64_t cOp3 = AA64FpOp3P0_uw | (uint64_t)AA64FpOp3P1_uw << 32;
309                    uint64_t cDest;
310                ''' "cDest = " + dOp + ";" + '''
311                    AA64FpDestP0_uw = cDest;
312                    AA64FpDestP1_uw = cDest >> 32;
313                '''
314            code += '''
315                AA64FpDestP2_uw = 0;
316                AA64FpDestP3_uw = 0;
317                FpscrExc = fpscr;
318            '''
319
320            iop = InstObjParams(name.lower(), name + suffix,
321                                "FpRegRegRegRegOp",
322                                { "code": code, "op_class": opClass }, [])
323            iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
324
325            header_output  += AA64FpRegRegRegRegOpDeclare.subst(iop)
326            decoder_output += AA64FpRegRegRegRegOpConstructor.subst(iop)
327            exec_output    += BasicExecute.subst(iop)
328
329    buildTernaryFpOp("FMAdd", "FloatMultAccOp",
330                     "fplibMulAdd<uint16_t>(cOp3, cOp1, cOp2, fpscr)",
331                     "fplibMulAdd<uint32_t>(cOp3, cOp1, cOp2, fpscr)",
332                     "fplibMulAdd<uint64_t>(cOp3, cOp1, cOp2, fpscr)" )
333    buildTernaryFpOp("FMSub", "FloatMultAccOp",
334        "fplibMulAdd<uint16_t>(cOp3, fplibNeg<uint32_t>(cOp1), cOp2, fpscr)",
335        "fplibMulAdd<uint32_t>(cOp3, fplibNeg<uint32_t>(cOp1), cOp2, fpscr)",
336        "fplibMulAdd<uint64_t>(cOp3, fplibNeg<uint64_t>(cOp1), cOp2, fpscr)" )
337    buildTernaryFpOp("FNMAdd", "FloatMultAccOp",
338                     "fplibMulAdd<uint16_t>(fplibNeg<uint16_t>(cOp3), " +
339                     "fplibNeg<uint16_t>(cOp1), cOp2, fpscr)",
340                     "fplibMulAdd<uint32_t>(fplibNeg<uint32_t>(cOp3), " +
341                     "fplibNeg<uint32_t>(cOp1), cOp2, fpscr)",
342                     "fplibMulAdd<uint64_t>(fplibNeg<uint64_t>(cOp3), " +
343                     "fplibNeg<uint64_t>(cOp1), cOp2, fpscr)" )
344    buildTernaryFpOp("FNMSub", "FloatMultAccOp",
345        "fplibMulAdd<uint16_t>(fplibNeg<uint32_t>(cOp3), cOp1, cOp2, fpscr)",
346        "fplibMulAdd<uint32_t>(fplibNeg<uint32_t>(cOp3), cOp1, cOp2, fpscr)",
347        "fplibMulAdd<uint64_t>(fplibNeg<uint64_t>(cOp3), cOp1, cOp2, fpscr)" )
348
349    def buildBinFpOp(name, Name, base, opClass, halfOp, singleOp, doubleOp):
350        global header_output, decoder_output, exec_output
351
352        code = halfIntConvCode2 % { "op": halfOp }
353        hIop = InstObjParams(name, Name + "H", base,
354                { "code": code,
355                  "op_class": opClass }, [])
356        hIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
357
358        code = singleIntConvCode2 % { "op": singleOp }
359        sIop = InstObjParams(name, Name + "S", base,
360                { "code": code,
361                  "op_class": opClass }, [])
362        sIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
363
364        code = doubleIntConvCode2 % { "op": doubleOp }
365        dIop = InstObjParams(name, Name + "D", base,
366                { "code": code,
367                  "op_class": opClass }, [])
368        dIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
369
370        declareTempl     = eval(         base + "Declare");
371        constructorTempl = eval("AA64" + base + "Constructor");
372
373        for iop in hIop, sIop, dIop:
374            header_output  += declareTempl.subst(iop)
375            decoder_output += constructorTempl.subst(iop)
376            exec_output    += BasicExecute.subst(iop)
377
378    buildBinFpOp("fadd", "FAdd", "FpRegRegRegOp", "FloatAddOp",
379                 "fplibAdd<uint16_t>(cOp1, cOp2, fpscr)",
380                 "fplibAdd<uint32_t>(cOp1, cOp2, fpscr)",
381                 "fplibAdd<uint64_t>(cOp1, cOp2, fpscr)")
382    buildBinFpOp("fsub", "FSub", "FpRegRegRegOp", "FloatAddOp",
383                 "fplibSub<uint16_t>(cOp1, cOp2, fpscr)",
384                 "fplibSub<uint32_t>(cOp1, cOp2, fpscr)",
385                 "fplibSub<uint64_t>(cOp1, cOp2, fpscr)")
386    buildBinFpOp("fdiv", "FDiv", "FpRegRegRegOp", "FloatDivOp",
387                 "fplibDiv<uint16_t>(cOp1, cOp2, fpscr)",
388                 "fplibDiv<uint32_t>(cOp1, cOp2, fpscr)",
389                 "fplibDiv<uint64_t>(cOp1, cOp2, fpscr)")
390    buildBinFpOp("fmul", "FMul", "FpRegRegRegOp", "FloatMultOp",
391                 "fplibMul<uint16_t>(cOp1, cOp2, fpscr)",
392                 "fplibMul<uint32_t>(cOp1, cOp2, fpscr)",
393                 "fplibMul<uint64_t>(cOp1, cOp2, fpscr)")
394    buildBinFpOp("fnmul", "FNMul", "FpRegRegRegOp", "FloatMultOp",
395                 "fplibNeg<uint16_t>(fplibMul<uint32_t>(cOp1, cOp2, fpscr))",
396                 "fplibNeg<uint32_t>(fplibMul<uint32_t>(cOp1, cOp2, fpscr))",
397                 "fplibNeg<uint64_t>(fplibMul<uint64_t>(cOp1, cOp2, fpscr))")
398    buildBinFpOp("fmin", "FMin", "FpRegRegRegOp", "FloatCmpOp",
399                 "fplibMin<uint16_t>(cOp1, cOp2, fpscr)",
400                 "fplibMin<uint32_t>(cOp1, cOp2, fpscr)",
401                 "fplibMin<uint64_t>(cOp1, cOp2, fpscr)")
402    buildBinFpOp("fmax", "FMax", "FpRegRegRegOp", "FloatCmpOp",
403                 "fplibMax<uint16_t>(cOp1, cOp2, fpscr)",
404                 "fplibMax<uint32_t>(cOp1, cOp2, fpscr)",
405                 "fplibMax<uint64_t>(cOp1, cOp2, fpscr)")
406    buildBinFpOp("fminnm", "FMinNM", "FpRegRegRegOp", "FloatCmpOp",
407                 "fplibMinNum<uint16_t>(cOp1, cOp2, fpscr)",
408                 "fplibMinNum<uint32_t>(cOp1, cOp2, fpscr)",
409                 "fplibMinNum<uint64_t>(cOp1, cOp2, fpscr)")
410    buildBinFpOp("fmaxnm", "FMaxNM", "FpRegRegRegOp", "FloatCmpOp",
411                 "fplibMaxNum<uint16_t>(cOp1, cOp2, fpscr)",
412                 "fplibMaxNum<uint32_t>(cOp1, cOp2, fpscr)",
413                 "fplibMaxNum<uint64_t>(cOp1, cOp2, fpscr)")
414
415    def buildUnaryFpOp(name, Name, base, opClass,
416                       halfOp, singleOp, doubleOp = None):
417        if doubleOp is None:
418            doubleOp = singleOp
419        global header_output, decoder_output, exec_output
420
421        code = halfIntConvCode % { "op": halfOp }
422        hIop = InstObjParams(name, Name + "H", base,
423                { "code": code,
424                  "op_class": opClass }, [])
425        hIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
426        code = singleIntConvCode % { "op": singleOp }
427        sIop = InstObjParams(name, Name + "S", base,
428                { "code": code,
429                  "op_class": opClass }, [])
430        sIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
431        code = doubleIntConvCode % { "op": doubleOp }
432        dIop = InstObjParams(name, Name + "D", base,
433                { "code": code,
434                  "op_class": opClass }, [])
435        dIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
436
437        declareTempl     = eval(         base + "Declare");
438        constructorTempl = eval("AA64" + base + "Constructor");
439
440        for iop in hIop, sIop, dIop:
441            header_output  += declareTempl.subst(iop)
442            decoder_output += constructorTempl.subst(iop)
443            exec_output    += BasicExecute.subst(iop)
444
445    buildUnaryFpOp("fsqrt", "FSqrt", "FpRegRegOp", "FloatSqrtOp",
446                   "fplibSqrt<uint16_t>(cOp1, fpscr)",
447                   "fplibSqrt<uint32_t>(cOp1, fpscr)",
448                   "fplibSqrt<uint64_t>(cOp1, fpscr)")
449
450    def buildSimpleUnaryFpOp(name, Name, base, opClass, halfOp, singleOp,
451                             doubleOp = None, isIntConv = True):
452        if doubleOp is None:
453            doubleOp = singleOp
454        global header_output, decoder_output, exec_output
455
456        if isIntConv:
457            hCode = halfIntConvCode
458            sCode = singleIntConvCode
459            dCode = doubleIntConvCode
460        else:
461            hCode = halfCode
462            sCode = singleCode
463            dCode = doubleCode
464
465        for code, op, suffix in [[hCode, halfOp, "H"],
466                                 [sCode, singleOp, "S"],
467                                 [dCode, doubleOp, "D"]]:
468            iop = InstObjParams(name, Name + suffix, base,
469                { "code": code % { "op": op },
470                  "op_class": opClass }, [])
471            iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
472
473            declareTempl     = eval(         base + "Declare");
474            constructorTempl = eval("AA64" + base + "Constructor");
475
476            header_output  += declareTempl.subst(iop)
477            decoder_output += constructorTempl.subst(iop)
478            exec_output    += BasicExecute.subst(iop)
479
480    buildSimpleUnaryFpOp("fneg", "FNeg", "FpRegRegOp", "FloatMiscOp",
481                         "fplibNeg<uint16_t>(cOp1)",
482                         "fplibNeg<uint32_t>(cOp1)",
483                         "fplibNeg<uint64_t>(cOp1)")
484    buildSimpleUnaryFpOp("fabs", "FAbs", "FpRegRegOp", "FloatMiscOp",
485                         "fplibAbs<uint16_t>(cOp1)",
486                         "fplibAbs<uint32_t>(cOp1)",
487                         "fplibAbs<uint64_t>(cOp1)")
488    buildSimpleUnaryFpOp("frintn", "FRIntN", "FpRegRegOp", "FloatMiscOp",
489        "fplibRoundInt<uint16_t>(cOp1, FPRounding_TIEEVEN, false, fpscr)",
490        "fplibRoundInt<uint32_t>(cOp1, FPRounding_TIEEVEN, false, fpscr)",
491        "fplibRoundInt<uint64_t>(cOp1, FPRounding_TIEEVEN, false, fpscr)")
492    buildSimpleUnaryFpOp("frintp", "FRIntP", "FpRegRegOp", "FloatMiscOp",
493        "fplibRoundInt<uint16_t>(cOp1, FPRounding_POSINF, false, fpscr)",
494        "fplibRoundInt<uint32_t>(cOp1, FPRounding_POSINF, false, fpscr)",
495        "fplibRoundInt<uint64_t>(cOp1, FPRounding_POSINF, false, fpscr)")
496    buildSimpleUnaryFpOp("frintm", "FRIntM", "FpRegRegOp", "FloatMiscOp",
497        "fplibRoundInt<uint16_t>(cOp1, FPRounding_NEGINF, false, fpscr)",
498        "fplibRoundInt<uint32_t>(cOp1, FPRounding_NEGINF, false, fpscr)",
499        "fplibRoundInt<uint64_t>(cOp1, FPRounding_NEGINF, false, fpscr)")
500    buildSimpleUnaryFpOp("frintz", "FRIntZ", "FpRegRegOp", "FloatMiscOp",
501        "fplibRoundInt<uint16_t>(cOp1, FPRounding_ZERO, false, fpscr)",
502        "fplibRoundInt<uint32_t>(cOp1, FPRounding_ZERO, false, fpscr)",
503        "fplibRoundInt<uint64_t>(cOp1, FPRounding_ZERO, false, fpscr)")
504    buildSimpleUnaryFpOp("frinta", "FRIntA", "FpRegRegOp", "FloatMiscOp",
505        "fplibRoundInt<uint16_t>(cOp1, FPRounding_TIEAWAY, false, fpscr)",
506        "fplibRoundInt<uint32_t>(cOp1, FPRounding_TIEAWAY, false, fpscr)",
507        "fplibRoundInt<uint64_t>(cOp1, FPRounding_TIEAWAY, false, fpscr)")
508    buildSimpleUnaryFpOp("frinti", "FRIntI", "FpRegRegOp", "FloatMiscOp",
509        "fplibRoundInt<uint16_t>(cOp1, FPCRRounding(fpscr), false, fpscr)",
510        "fplibRoundInt<uint32_t>(cOp1, FPCRRounding(fpscr), false, fpscr)",
511        "fplibRoundInt<uint64_t>(cOp1, FPCRRounding(fpscr), false, fpscr)")
512    buildSimpleUnaryFpOp("frintx", "FRIntX", "FpRegRegOp", "FloatMiscOp",
513        "fplibRoundInt<uint16_t>(cOp1, FPCRRounding(fpscr), true, fpscr)",
514        "fplibRoundInt<uint32_t>(cOp1, FPCRRounding(fpscr), true, fpscr)",
515        "fplibRoundInt<uint64_t>(cOp1, FPCRRounding(fpscr), true, fpscr)")
516}};
517
518let {{
519
520    header_output = ""
521    decoder_output = ""
522    exec_output = ""
523
524    # Creates the integer to floating point instructions, including variants for
525    # signed/unsigned, float/double, etc
526    for regL, regOpL, width in [["W", "w", 32],
527                                ["X", "d", 64]]:
528        for isDouble in True, False:
529            for us, usCode in [["U", "uint%d_t cSrc = %sOp1_u%s;" %(width, regL, regOpL)],
530                               ["S", "int%d_t  cSrc = %sOp1_u%s;" %(width, regL, regOpL)]]:
531                fcvtIntFpDCode = vfp64EnabledCheckCode + '''
532                    FPSCR fpscr = (FPSCR) FpscrExc;
533                    %s
534                ''' %(usCode)
535
536                if isDouble:
537                    fcvtIntFpDCode += '''
538                        uint64_t cDest = fplibFixedToFP<uint64_t>(cSrc, 0,
539                            %s, FPCRRounding(fpscr), fpscr);
540                        AA64FpDestP0_uw = cDest;
541                        AA64FpDestP1_uw = cDest >> 32;
542                    ''' % ("true" if us == "U" else "false")
543                else:
544                    fcvtIntFpDCode += '''
545                        uint32_t cDest = fplibFixedToFP<uint32_t>(cSrc, 0,
546                            %s, FPCRRounding(fpscr), fpscr);
547                        AA64FpDestP0_uw = cDest;
548                        AA64FpDestP1_uw = 0;
549                    ''' % ("true" if us == "U" else "false")
550                fcvtIntFpDCode += '''
551                    AA64FpDestP2_uw = 0;
552                    AA64FpDestP3_uw = 0;
553                    FpscrExc = fpscr;
554                '''
555
556                instName = "Fcvt%s%sIntFp%s" %(regL, us, "D" if isDouble else "S")
557                mnem     = "%scvtf" %(us.lower())
558                fcvtIntFpDIop = InstObjParams(mnem, instName, "FpRegRegOp",
559                                              { "code": fcvtIntFpDCode,
560                                                "op_class": "FloatCvtOp" }, [])
561                fcvtIntFpDIop.snippets["code"] += \
562                        zeroSveVecRegUpperPartCode % "AA64FpDest"
563
564                header_output  += FpRegRegOpDeclare.subst(fcvtIntFpDIop);
565                decoder_output += AA64FpRegRegOpConstructor.subst(fcvtIntFpDIop);
566                exec_output    += BasicExecute.subst(fcvtIntFpDIop);
567
568    # Generates the floating point to integer conversion instructions in various
569    # variants, eg signed/unsigned
570    def buildFpCvtIntOp(isDouble, isSigned, isXReg):
571        global header_output, decoder_output, exec_output
572
573        for rmode, roundingMode in [["N", "FPRounding_TIEEVEN"],
574                                    ["P", "FPRounding_POSINF"],
575                                    ["M", "FPRounding_NEGINF"],
576                                    ["Z", "FPRounding_ZERO"],
577                                    ["A", "FPRounding_TIEAWAY"]]:
578            fcvtFpIntCode = vfp64EnabledCheckCode + '''
579                FPSCR fpscr = (FPSCR) FpscrExc;'''
580            if isDouble:
581                fcvtFpIntCode += '''
582                uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
583                '''
584            else:
585                fcvtFpIntCode += "uint32_t cOp1 = AA64FpOp1P0_uw;"
586
587            fcvtFpIntCode += '''
588                %sDest = fplibFPToFixed<uint%s_t, uint%s_t>(cOp1, 0, %s, %s, fpscr);
589                FpscrExc = fpscr;
590            ''' %("X"      if isXReg   else "W",
591                  "64"     if isDouble else "32",
592                  "64"     if isXReg   else "32",
593                  "false"  if isSigned else "true",
594                  roundingMode)
595
596            instName = "FcvtFp%sInt%s%s%s" %("S" if isSigned else "U",
597                                             "X" if isXReg   else "W",
598                                             "D" if isDouble else "S", rmode)
599            mnem     = "fcvt%s%s" %(rmode, "s" if isSigned else "u")
600            fcvtFpIntIop = InstObjParams(mnem, instName, "FpRegRegOp",
601                                        { "code": fcvtFpIntCode,
602                                        "op_class": "FloatCvtOp" }, [])
603            header_output  += FpRegRegOpDeclare.subst(fcvtFpIntIop);
604            decoder_output += FpRegRegOpConstructor.subst(fcvtFpIntIop);
605            exec_output    += BasicExecute.subst(fcvtFpIntIop);
606
607    # Now actually do the building with the different variants
608    for isDouble in True, False:
609       for isSigned in True, False:
610           for isXReg in True, False:
611             buildFpCvtIntOp(isDouble, isSigned, isXReg)
612
613    fcvtFpSFpDCode = vfp64EnabledCheckCode + '''
614        FPSCR fpscr = (FPSCR) FpscrExc;
615        uint64_t cDest = fplibConvert<uint32_t, uint64_t>(AA64FpOp1P0_uw,
616            FPCRRounding(fpscr), fpscr);
617        AA64FpDestP0_uw = cDest;
618        AA64FpDestP1_uw = cDest >> 32;
619        AA64FpDestP2_uw = 0;
620        AA64FpDestP3_uw = 0;
621        FpscrExc = fpscr;
622    '''
623    fcvtFpSFpDIop = InstObjParams("fcvt", "FCvtFpSFpD", "FpRegRegOp",
624                                     { "code": fcvtFpSFpDCode,
625                                       "op_class": "FloatCvtOp" }, [])
626    fcvtFpSFpDIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
627    header_output  += FpRegRegOpDeclare.subst(fcvtFpSFpDIop);
628    decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpSFpDIop);
629    exec_output    += BasicExecute.subst(fcvtFpSFpDIop);
630
631    fcvtFpDFpSCode = vfp64EnabledCheckCode + '''
632        FPSCR fpscr = (FPSCR) FpscrExc;
633        uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
634        AA64FpDestP0_uw = fplibConvert<uint64_t, uint32_t>(cOp1,
635            FPCRRounding(fpscr), fpscr);
636        AA64FpDestP1_uw = 0;
637        AA64FpDestP2_uw = 0;
638        AA64FpDestP3_uw = 0;
639        FpscrExc = fpscr;
640    '''
641    fcvtFpDFpSIop = InstObjParams("fcvt", "FcvtFpDFpS", "FpRegRegOp",
642                                 {"code":     fcvtFpDFpSCode,
643                                  "op_class": "FloatCvtOp" }, [])
644    fcvtFpDFpSIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
645    header_output  += FpRegRegOpDeclare.subst(fcvtFpDFpSIop);
646    decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpDFpSIop);
647    exec_output    += BasicExecute.subst(fcvtFpDFpSIop);
648
649    # Half precision to single or double precision conversion
650    for isDouble in True, False:
651        code = vfp64EnabledCheckCode + '''
652            FPSCR fpscr = (FPSCR) FpscrExc;
653            %s cDest = fplibConvert<uint16_t, uint%s_t>(AA64FpOp1P0_uw,
654                FPCRRounding(fpscr), fpscr);
655        ''' % ("uint64_t" if isDouble else "uint32_t",
656               "64" if isDouble else "32")
657        if isDouble:
658            code += '''
659                AA64FpDestP0_uw = cDest;
660                AA64FpDestP1_uw = cDest >> 32;
661            '''
662        else:
663            code += '''
664                AA64FpDestP0_uw = cDest;
665                AA64FpDestP1_uw = 0;
666            '''
667        code += '''
668            AA64FpDestP2_uw = 0;
669            AA64FpDestP3_uw = 0;
670            FpscrExc = fpscr;
671        '''
672
673        instName = "FcvtFpHFp%s" %("D" if isDouble else "S")
674        fcvtFpHFpIop = InstObjParams("fcvt", instName, "FpRegRegOp",
675                                     { "code": code,
676                                       "op_class": "FloatCvtOp" }, [])
677        fcvtFpHFpIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
678                "AA64FpDest"
679        header_output  += FpRegRegOpDeclare.subst(fcvtFpHFpIop);
680        decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpHFpIop);
681        exec_output    += BasicExecute.subst(fcvtFpHFpIop);
682
683    # single or double precision to Half precision conversion
684    for isDouble in True, False:
685        code = vfp64EnabledCheckCode + '''
686            FPSCR fpscr = (FPSCR) FpscrExc;
687            %s;
688            AA64FpDestP0_uw = fplibConvert<uint%s_t, uint16_t>(cOp1,
689                FPCRRounding(fpscr), fpscr);
690            AA64FpDestP1_uw = 0;
691            AA64FpDestP2_uw = 0;
692            AA64FpDestP3_uw = 0;
693            FpscrExc = fpscr;
694        ''' % ("uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32"
695               if isDouble else "uint32_t cOp1 = AA64FpOp1P0_uw",
696               "64" if isDouble else "32")
697
698        instName = "FcvtFp%sFpH" %("D" if isDouble else "S")
699        fcvtFpFpHIop = InstObjParams("fcvt", instName, "FpRegRegOp",
700                                     { "code": code,
701                                       "op_class": "FloatCvtOp" }, [])
702        fcvtFpFpHIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
703                "AA64FpDest"
704        header_output  += FpRegRegOpDeclare.subst(fcvtFpFpHIop);
705        decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpFpHIop);
706        exec_output    += BasicExecute.subst(fcvtFpFpHIop);
707
708    # Build the various versions of the floating point compare instructions
709    def buildFCmpOp(isQuiet, isDouble, isImm):
710        global header_output, decoder_output, exec_output
711
712        fcmpCode = vfp64EnabledCheckCode + '''
713            FPSCR fpscr = (FPSCR) FpscrExc;
714            %s cOp1 = %s;
715        ''' % ("uint64_t" if isDouble else "uint32_t",
716               "AA64FpDestP0_uw | (uint64_t)AA64FpDestP1_uw << 32"
717               if isDouble else "AA64FpDestP0_uw")
718        if isImm:
719            fcmpCode += '''
720                %s cOp2 = imm;
721            ''' % ("uint64_t" if isDouble else "uint32_t")
722        else:
723            fcmpCode += '''
724                %s cOp2  = %s;
725            ''' % ("uint64_t" if isDouble else "uint32_t",
726                   "AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32"
727                   if isDouble else "AA64FpOp1P0_uw")
728        fcmpCode += '''
729            int cc = fplibCompare<uint%s_t>(cOp1, cOp2, %s, fpscr);
730            CondCodesNZ = cc >> 2 & 3;
731            CondCodesC = cc >> 1 & 1;
732            CondCodesV = cc & 1;
733            FpCondCodes = fpscr & FpCondCodesMask;
734            FpscrExc    = fpscr;
735        ''' % ("64" if isDouble else "32", "false" if isQuiet else "true")
736
737        typeName = "Imm" if isImm else "Reg"
738        instName = "FCmp%s%s%s" %(""  if isQuiet  else "E", typeName,
739                                  "D" if isDouble else "S")
740        fcmpIop = InstObjParams("fcmp%s" %(""  if isQuiet else "e"), instName,
741                                "FpReg%sOp" %(typeName),
742                               {"code":     fcmpCode,
743                                "op_class": "FloatCmpOp"}, [])
744
745        declareTemp     = eval("FpReg%sOpDeclare"         %(typeName));
746        constructorTemp = eval("AA64FpReg%sOpConstructor" %(typeName));
747        header_output  += declareTemp.subst(fcmpIop);
748        decoder_output += constructorTemp.subst(fcmpIop);
749        exec_output    += BasicExecute.subst(fcmpIop);
750
751    for isQuiet in True, False:
752        for isDouble in True, False:
753            for isImm in True, False:
754                buildFCmpOp(isQuiet, isDouble, isImm)
755
756    # Build the various versions of the conditional floating point compare
757    # instructions
758    def buildFCCmpOp(isQuiet, isDouble):
759        global header_output, decoder_output, exec_output
760
761        fccmpCode = vfp64EnabledCheckCode + '''
762            FPSCR fpscr = (FPSCR) FpscrExc;
763            if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
764                %s cOp1 = %s;
765                %s cOp2 = %s;
766                int cc = fplibCompare<uint%s_t>(cOp1, cOp2, %s, fpscr);
767                CondCodesNZ = cc >> 2 & 3;
768                CondCodesC = cc >> 1 & 1;
769                CondCodesV = cc & 1;
770            } else {
771                CondCodesNZ = (defCc >> 2) & 0x3;
772                CondCodesC  = (defCc >> 1) & 0x1;
773                CondCodesV  = defCc & 0x1;
774            }
775            FpCondCodes = fpscr & FpCondCodesMask;
776            FpscrExc    = fpscr;
777        ''' % ("uint64_t" if isDouble else "uint32_t",
778               "AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32"
779               if isDouble else "AA64FpOp1P0_uw",
780               "uint64_t" if isDouble else "uint32_t",
781               "AA64FpOp2P0_uw | (uint64_t)AA64FpOp2P1_uw << 32"
782               if isDouble else "AA64FpOp2P0_uw",
783               "64" if isDouble else "32", "false" if isQuiet else "true")
784
785        instName = "FCCmp%sReg%s" %(""  if isQuiet  else "E",
786                                    "D" if isDouble else "S")
787        fccmpIop = InstObjParams("fccmp%s" %(""  if isQuiet  else "e"),
788                                 instName, "FpCondCompRegOp",
789                                {"code":           fccmpCode,
790                                 "op_class":       "FloatCmpOp"}, [])
791        header_output  += DataXCondCompRegDeclare.subst(fccmpIop);
792        decoder_output += DataXCondCompRegConstructor.subst(fccmpIop);
793        exec_output    += BasicExecute.subst(fccmpIop);
794
795    for isQuiet in True, False:
796        for isDouble in True, False:
797            buildFCCmpOp(isQuiet, isDouble)
798
799}};
800
801let {{
802
803    header_output = ""
804    decoder_output = ""
805    exec_output = ""
806
807    # Generates the variants of the floating to fixed point instructions
808    def buildFpCvtFixedOp(isSigned, isDouble, isXReg):
809        global header_output, decoder_output, exec_output
810
811        fcvtFpFixedCode = vfp64EnabledCheckCode + '''
812            FPSCR fpscr = (FPSCR) FpscrExc;
813        '''
814        if isDouble:
815            fcvtFpFixedCode += '''
816                uint64_t cOp1 = AA64FpOp1P0_uw | (uint64_t)AA64FpOp1P1_uw << 32;
817            '''
818        else:
819            fcvtFpFixedCode += "uint32_t cOp1 = AA64FpOp1P0_uw;"
820        fcvtFpFixedCode += '''
821            %sDest = fplibFPToFixed<uint%s_t, uint%s_t>(cOp1, 64 - imm, %s,
822                FPRounding_ZERO, fpscr);
823            FpscrExc = fpscr;
824        ''' %("X"      if isXReg   else "W",
825              "64"     if isDouble else "32",
826              "64"     if isXReg   else "32",
827              "false"  if isSigned else "true")
828
829        instName = "FcvtFp%sFixed%s%s" %("S" if isSigned else "U",
830                                         "D" if isDouble else "S",
831                                         "X" if isXReg   else "W")
832        mnem = "fcvtz%s" %("s" if isSigned else "u")
833        fcvtFpFixedIop = InstObjParams(mnem, instName, "FpRegRegImmOp",
834                                       { "code": fcvtFpFixedCode,
835                                         "op_class": "FloatCvtOp" }, [])
836        header_output  += FpRegRegImmOpDeclare.subst(fcvtFpFixedIop);
837        decoder_output += AA64FpRegRegImmOpConstructor.subst(fcvtFpFixedIop);
838        exec_output    += BasicExecute.subst(fcvtFpFixedIop);
839
840    # Generates the variants of the fixed to floating point instructions
841    def buildFixedCvtFpOp(isSigned, isDouble, isXReg):
842        global header_output, decoder_output, exec_output
843
844        srcRegType = "X" if isXReg   else "W"
845        fcvtFixedFpCode = vfp64EnabledCheckCode + '''
846            FPSCR fpscr = (FPSCR) FpscrExc;
847            %s result = fplibFixedToFP<uint%s_t>((%s%s_t)%sOp1, 64 - imm,
848                %s, FPCRRounding(fpscr), fpscr);
849        ''' %("uint64_t" if isDouble else "uint32_t",
850              "64" if isDouble else "32",
851              "int" if isSigned else "uint", "64" if isXReg else "32",
852              srcRegType,
853              "false" if isSigned else "true")
854        if isDouble:
855            fcvtFixedFpCode += '''
856                AA64FpDestP0_uw = result;
857                AA64FpDestP1_uw = result >> 32;
858            '''
859        else:
860            fcvtFixedFpCode += '''
861                AA64FpDestP0_uw = result;
862                AA64FpDestP1_uw = 0;
863            '''
864        fcvtFixedFpCode += '''
865            AA64FpDestP2_uw = 0;
866            AA64FpDestP3_uw = 0;
867            FpscrExc = fpscr;
868        '''
869
870        instName = "Fcvt%sFixedFp%s%s" %("S" if isSigned else "U",
871                                         "D" if isDouble else "S",
872                                         srcRegType)
873        mnem = "%scvtf" %("s" if isSigned else "u")
874        fcvtFixedFpIop = InstObjParams(mnem, instName, "FpRegRegImmOp",
875                                       { "code":     fcvtFixedFpCode,
876                                         "op_class": "FloatCvtOp" }, [])
877        fcvtFixedFpIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
878                "AA64FpDest"
879        header_output  += FpRegRegImmOpDeclare.subst(fcvtFixedFpIop);
880        decoder_output += FpRegRegImmOpConstructor.subst(fcvtFixedFpIop);
881        exec_output    += BasicExecute.subst(fcvtFixedFpIop);
882
883    # loop over the variants building the instructions for each
884    for isXReg in True, False:
885        for isDouble in True, False:
886            for isSigned in True, False:
887                buildFpCvtFixedOp(isSigned, isDouble, isXReg)
888                buildFixedCvtFpOp(isSigned, isDouble, isXReg)
889}};
890
891let {{
892
893    header_output  = ""
894    decoder_output = ""
895    exec_output    = ""
896
897    for isDouble in True, False:
898        code = '''
899            if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
900                AA64FpDestP0_uw = AA64FpOp1P0_uw;
901        '''
902        if isDouble:
903            code += '''
904                    AA64FpDestP1_uw = AA64FpOp1P1_uw;
905                } else {
906                    AA64FpDestP0_uw = AA64FpOp2P0_uw;
907                    AA64FpDestP1_uw = AA64FpOp2P1_uw;
908                }
909            '''
910        else:
911            code += '''
912                } else {
913                    AA64FpDestP0_uw = AA64FpOp2P0_uw;
914                }
915                AA64FpDestP1_uw = 0;
916            '''
917        code += '''
918            AA64FpDestP2_uw = 0;
919            AA64FpDestP3_uw = 0;
920        '''
921
922        iop = InstObjParams("fcsel", "FCSel%s" %("D" if isDouble else "S"),
923                            "FpCondSelOp", { "code":     code,
924                                             "op_class": "FloatCvtOp" })
925        iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
926        header_output  += DataXCondSelDeclare.subst(iop)
927        decoder_output += DataXCondSelConstructor.subst(iop)
928        exec_output    += BasicExecute.subst(iop)
929}};
930