1// -*- mode:c++ -*-
2
3// Copyright (c) 2010-2013,2016,2018-2019 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: Gabe Black
39
40output header {{
41
42template <class Micro>
43class VfpMacroRegRegOp : public VfpMacroOp
44{
45  public:
46    VfpMacroRegRegOp(ExtMachInst _machInst, IntRegIndex _dest,
47                     IntRegIndex _op1, bool _wide) :
48        VfpMacroOp("VfpMacroRegRegOp", _machInst, No_OpClass, _wide)
49    {
50        numMicroops = machInst.fpscrLen + 1;
51        assert(numMicroops > 1);
52        microOps = new StaticInstPtr[numMicroops];
53        for (unsigned i = 0; i < numMicroops; i++) {
54            VfpMicroMode mode = VfpMicroop;
55            if (i == 0)
56                mode = VfpFirstMicroop;
57            else if (i == numMicroops - 1)
58                mode = VfpLastMicroop;
59            microOps[i] = new Micro(_machInst, _dest, _op1, mode);
60            nextIdxs(_dest, _op1);
61        }
62    }
63};
64
65template <class VfpOp>
66StaticInstPtr
67decodeVfpRegRegOp(ExtMachInst machInst,
68        IntRegIndex dest, IntRegIndex op1, bool wide)
69{
70    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
71        return new VfpOp(machInst, dest, op1);
72    } else {
73        return new VfpMacroRegRegOp<VfpOp>(machInst, dest, op1, wide);
74    }
75}
76
77template <class Micro>
78class VfpMacroRegImmOp : public VfpMacroOp
79{
80  public:
81    VfpMacroRegImmOp(ExtMachInst _machInst, IntRegIndex _dest, uint64_t _imm,
82                     bool _wide) :
83        VfpMacroOp("VfpMacroRegImmOp", _machInst, No_OpClass, _wide)
84    {
85        numMicroops = machInst.fpscrLen + 1;
86        microOps = new StaticInstPtr[numMicroops];
87        for (unsigned i = 0; i < numMicroops; i++) {
88            VfpMicroMode mode = VfpMicroop;
89            if (i == 0)
90                mode = VfpFirstMicroop;
91            else if (i == numMicroops - 1)
92                mode = VfpLastMicroop;
93            microOps[i] = new Micro(_machInst, _dest, _imm, mode);
94            nextIdxs(_dest);
95        }
96    }
97};
98
99template <class VfpOp>
100StaticInstPtr
101decodeVfpRegImmOp(ExtMachInst machInst,
102        IntRegIndex dest, uint64_t imm, bool wide)
103{
104    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
105        return new VfpOp(machInst, dest, imm);
106    } else {
107        return new VfpMacroRegImmOp<VfpOp>(machInst, dest, imm, wide);
108    }
109}
110
111template <class Micro>
112class VfpMacroRegRegImmOp : public VfpMacroOp
113{
114  public:
115    VfpMacroRegRegImmOp(ExtMachInst _machInst, IntRegIndex _dest,
116                        IntRegIndex _op1, uint64_t _imm, bool _wide) :
117        VfpMacroOp("VfpMacroRegRegImmOp", _machInst, No_OpClass, _wide)
118    {
119        numMicroops = machInst.fpscrLen + 1;
120        microOps = new StaticInstPtr[numMicroops];
121        for (unsigned i = 0; i < numMicroops; i++) {
122            VfpMicroMode mode = VfpMicroop;
123            if (i == 0)
124                mode = VfpFirstMicroop;
125            else if (i == numMicroops - 1)
126                mode = VfpLastMicroop;
127            microOps[i] = new Micro(_machInst, _dest, _op1, _imm, mode);
128            nextIdxs(_dest, _op1);
129        }
130    }
131};
132
133template <class VfpOp>
134StaticInstPtr
135decodeVfpRegRegImmOp(ExtMachInst machInst, IntRegIndex dest,
136                     IntRegIndex op1, uint64_t imm, bool wide)
137{
138    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
139        return new VfpOp(machInst, dest, op1, imm);
140    } else {
141        return new VfpMacroRegRegImmOp<VfpOp>(machInst, dest, op1, imm, wide);
142    }
143}
144
145template <class Micro>
146class VfpMacroRegRegRegOp : public VfpMacroOp
147{
148  public:
149    VfpMacroRegRegRegOp(ExtMachInst _machInst, IntRegIndex _dest,
150                        IntRegIndex _op1, IntRegIndex _op2, bool _wide) :
151        VfpMacroOp("VfpMacroRegRegRegOp", _machInst, No_OpClass, _wide)
152    {
153        numMicroops = machInst.fpscrLen + 1;
154        microOps = new StaticInstPtr[numMicroops];
155        for (unsigned i = 0; i < numMicroops; i++) {
156            VfpMicroMode mode = VfpMicroop;
157            if (i == 0)
158                mode = VfpFirstMicroop;
159            else if (i == numMicroops - 1)
160                mode = VfpLastMicroop;
161            microOps[i] = new Micro(_machInst, _dest, _op1, _op2, mode);
162            nextIdxs(_dest, _op1, _op2);
163        }
164    }
165};
166
167template <class VfpOp>
168StaticInstPtr
169decodeVfpRegRegRegOp(ExtMachInst machInst, IntRegIndex dest,
170                     IntRegIndex op1, IntRegIndex op2, bool wide)
171{
172    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
173        return new VfpOp(machInst, dest, op1, op2);
174    } else {
175        return new VfpMacroRegRegRegOp<VfpOp>(machInst, dest, op1, op2, wide);
176    }
177}
178}};
179
180let {{
181
182    header_output = ""
183    decoder_output = ""
184    exec_output = ""
185
186    vmsrCode = vmsrEnabledCheckCode + '''
187    MiscDest = Op1;
188    '''
189
190    vmsrIop = InstObjParams("vmsr", "Vmsr", "FpRegRegImmOp",
191                            { "code": vmsrCode,
192                              "predicate_test": predicateTest,
193                              "op_class": "SimdFloatMiscOp" },
194                             ["IsSerializeAfter","IsNonSpeculative"])
195    header_output += FpRegRegImmOpDeclare.subst(vmsrIop);
196    decoder_output += FpRegRegImmOpConstructor.subst(vmsrIop);
197    exec_output += PredOpExecute.subst(vmsrIop);
198
199    vmsrFpscrCode = vmsrEnabledCheckCode + '''
200    Fpscr = Op1 & ~FpCondCodesMask;
201    FpCondCodes = Op1 & FpCondCodesMask;
202    '''
203    vmsrFpscrIop = InstObjParams("vmsr", "VmsrFpscr", "FpRegRegOp",
204                                 { "code": vmsrFpscrCode,
205                                   "predicate_test": predicateTest,
206                                   "op_class": "SimdFloatMiscOp" },
207                                 ["IsSerializeAfter","IsNonSpeculative",
208                                  "IsSquashAfter"])
209    header_output += FpRegRegOpDeclare.subst(vmsrFpscrIop);
210    decoder_output += FpRegRegOpConstructor.subst(vmsrFpscrIop);
211    exec_output += PredOpExecute.subst(vmsrFpscrIop);
212
213    vmrsCode = vmrsEnabledCheckCode + '''
214    CPSR cpsr = Cpsr;
215    SCR  scr  = Scr;
216    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
217        HCR hcr = Hcr;
218        bool hypTrap = false;
219        switch(xc->tcBase()->flattenRegId(RegId(MiscRegClass, op1)).index()) {
220          case MISCREG_FPSID:
221            hypTrap = hcr.tid0;
222            break;
223          case MISCREG_MVFR0:
224          case MISCREG_MVFR1:
225            hypTrap = hcr.tid3;
226            break;
227        }
228        if (hypTrap) {
229            return std::make_shared<HypervisorTrap>(machInst, imm,
230                EC_TRAPPED_CP10_MRC_VMRS);
231        }
232    }
233    Dest = MiscOp1;
234    '''
235
236    vmrsIop = InstObjParams("vmrs", "Vmrs", "FpRegRegImmOp",
237                            { "code": vmrsCode,
238                              "predicate_test": predicateTest,
239                              "op_class": "SimdFloatMiscOp" },
240                            ["IsSerializeBefore"])
241    header_output += FpRegRegImmOpDeclare.subst(vmrsIop);
242    decoder_output += FpRegRegImmOpConstructor.subst(vmrsIop);
243    exec_output += PredOpExecute.subst(vmrsIop);
244
245    vmrsFpscrIop = InstObjParams("vmrs", "VmrsFpscr", "FpRegRegOp",
246                                 { "code": vmrsEnabledCheckCode + \
247                                           "Dest = Fpscr | FpCondCodes;",
248                                   "predicate_test": predicateTest,
249                                   "op_class": "SimdFloatMiscOp" },
250                                 ["IsSerializeBefore"])
251    header_output += FpRegRegOpDeclare.subst(vmrsFpscrIop);
252    decoder_output += FpRegRegOpConstructor.subst(vmrsFpscrIop);
253    exec_output += PredOpExecute.subst(vmrsFpscrIop);
254
255    vmrsApsrFpscrCode = vfpEnabledCheckCode + '''
256        FPSCR fpscr = FpCondCodes;
257        CondCodesNZ = (fpscr.n << 1) | fpscr.z;
258        CondCodesC = fpscr.c;
259        CondCodesV = fpscr.v;
260    '''
261    vmrsApsrFpscrIop = InstObjParams("vmrs", "VmrsApsrFpscr", "PredOp",
262                                     { "code": vmrsApsrFpscrCode,
263                                       "predicate_test": predicateTest,
264                                       "op_class": "SimdFloatMiscOp" })
265    header_output += BasicDeclare.subst(vmrsApsrFpscrIop);
266    decoder_output += BasicConstructor.subst(vmrsApsrFpscrIop);
267    exec_output += PredOpExecute.subst(vmrsApsrFpscrIop);
268
269    vmovImmSCode = vfpEnabledCheckCode + '''
270        FpDest_uw = bits(imm, 31, 0);
271    '''
272    vmovImmSIop = InstObjParams("vmov", "VmovImmS", "FpRegImmOp",
273                                { "code": vmovImmSCode,
274                                  "predicate_test": predicateTest,
275                                  "op_class": "SimdFloatMiscOp" }, [])
276    header_output += FpRegImmOpDeclare.subst(vmovImmSIop);
277    decoder_output += FpRegImmOpConstructor.subst(vmovImmSIop);
278    exec_output += PredOpExecute.subst(vmovImmSIop);
279
280    vmovImmDCode = vfpEnabledCheckCode + '''
281        FpDestP0_uw = bits(imm, 31, 0);
282        FpDestP1_uw = bits(imm, 63, 32);
283    '''
284    vmovImmDIop = InstObjParams("vmov", "VmovImmD", "FpRegImmOp",
285                                { "code": vmovImmDCode,
286                                  "predicate_test": predicateTest,
287                                  "op_class": "SimdFloatMiscOp" }, [])
288    header_output += FpRegImmOpDeclare.subst(vmovImmDIop);
289    decoder_output += FpRegImmOpConstructor.subst(vmovImmDIop);
290    exec_output += PredOpExecute.subst(vmovImmDIop);
291
292    vmovImmQCode = vfpEnabledCheckCode + '''
293        FpDestP0_uw = bits(imm, 31, 0);
294        FpDestP1_uw = bits(imm, 63, 32);
295        FpDestP2_uw = bits(imm, 31, 0);
296        FpDestP3_uw = bits(imm, 63, 32);
297    '''
298    vmovImmQIop = InstObjParams("vmov", "VmovImmQ", "FpRegImmOp",
299                                { "code": vmovImmQCode,
300                                  "predicate_test": predicateTest,
301                                  "op_class": "SimdFloatMiscOp" }, [])
302    header_output += FpRegImmOpDeclare.subst(vmovImmQIop);
303    decoder_output += FpRegImmOpConstructor.subst(vmovImmQIop);
304    exec_output += PredOpExecute.subst(vmovImmQIop);
305
306    vmovRegSCode = vfpEnabledCheckCode + '''
307        FpDest_uw = FpOp1_uw;
308    '''
309    vmovRegSIop = InstObjParams("vmov", "VmovRegS", "FpRegRegOp",
310                                { "code": vmovRegSCode,
311                                  "predicate_test": predicateTest,
312                                  "op_class": "SimdFloatMiscOp" }, [])
313    header_output += FpRegRegOpDeclare.subst(vmovRegSIop);
314    decoder_output += FpRegRegOpConstructor.subst(vmovRegSIop);
315    exec_output += PredOpExecute.subst(vmovRegSIop);
316
317    vmovRegDCode = vfpEnabledCheckCode + '''
318        FpDestP0_uw = FpOp1P0_uw;
319        FpDestP1_uw = FpOp1P1_uw;
320    '''
321    vmovRegDIop = InstObjParams("vmov", "VmovRegD", "FpRegRegOp",
322                                { "code": vmovRegDCode,
323                                  "predicate_test": predicateTest,
324                                  "op_class": "SimdFloatMiscOp" }, [])
325    header_output += FpRegRegOpDeclare.subst(vmovRegDIop);
326    decoder_output += FpRegRegOpConstructor.subst(vmovRegDIop);
327    exec_output += PredOpExecute.subst(vmovRegDIop);
328
329    vmovRegQCode = vfpEnabledCheckCode + '''
330        FpDestP0_uw = FpOp1P0_uw;
331        FpDestP1_uw = FpOp1P1_uw;
332        FpDestP2_uw = FpOp1P2_uw;
333        FpDestP3_uw = FpOp1P3_uw;
334    '''
335    vmovRegQIop = InstObjParams("vmov", "VmovRegQ", "FpRegRegOp",
336                                { "code": vmovRegQCode,
337                                  "predicate_test": predicateTest,
338                                  "op_class": "SimdFloatMiscOp" }, [])
339    header_output  += FpRegRegOpDeclare.subst(vmovRegQIop);
340    decoder_output  += FpRegRegOpConstructor.subst(vmovRegQIop);
341    exec_output += PredOpExecute.subst(vmovRegQIop);
342
343    vmovCoreRegBCode = simdEnabledCheckCode + '''
344        FpDest_uw = insertBits(FpDest_uw, imm * 8 + 7, imm * 8, Op1_ub);
345    '''
346    vmovCoreRegBIop = InstObjParams("vmov", "VmovCoreRegB", "FpRegRegImmOp",
347                                    { "code": vmovCoreRegBCode,
348                                      "predicate_test": predicateTest,
349                                      "op_class": "SimdFloatMiscOp" }, [])
350    header_output  += FpRegRegImmOpDeclare.subst(vmovCoreRegBIop);
351    decoder_output  += FpRegRegImmOpConstructor.subst(vmovCoreRegBIop);
352    exec_output += PredOpExecute.subst(vmovCoreRegBIop);
353
354    vmovCoreRegHCode = simdEnabledCheckCode + '''
355        FpDest_uw = insertBits(FpDest_uw, imm * 16 + 15, imm * 16, Op1_uh);
356    '''
357    vmovCoreRegHIop = InstObjParams("vmov", "VmovCoreRegH", "FpRegRegImmOp",
358                                    { "code": vmovCoreRegHCode,
359                                      "predicate_test": predicateTest,
360                                      "op_class": "SimdFloatMiscOp" }, [])
361    header_output  += FpRegRegImmOpDeclare.subst(vmovCoreRegHIop);
362    decoder_output  += FpRegRegImmOpConstructor.subst(vmovCoreRegHIop);
363    exec_output += PredOpExecute.subst(vmovCoreRegHIop);
364
365    vmovCoreRegWCode = vfpEnabledCheckCode + '''
366        FpDest_uw = Op1_uw;
367    '''
368    vmovCoreRegWIop = InstObjParams("vmov", "VmovCoreRegW", "FpRegRegOp",
369                                    { "code": vmovCoreRegWCode,
370                                      "predicate_test": predicateTest,
371                                      "op_class": "SimdFloatMiscOp" }, [])
372    header_output  += FpRegRegOpDeclare.subst(vmovCoreRegWIop);
373    decoder_output  += FpRegRegOpConstructor.subst(vmovCoreRegWIop);
374    exec_output += PredOpExecute.subst(vmovCoreRegWIop);
375
376    vmovRegCoreUBCode = vfpEnabledCheckCode + '''
377        assert(imm < 4);
378        Dest = bits(FpOp1_uw, imm * 8 + 7, imm * 8);
379    '''
380    vmovRegCoreUBIop = InstObjParams("vmov", "VmovRegCoreUB", "FpRegRegImmOp",
381                                     { "code": vmovRegCoreUBCode,
382                                       "predicate_test": predicateTest,
383                                       "op_class": "SimdFloatMiscOp" }, [])
384    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreUBIop);
385    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreUBIop);
386    exec_output += PredOpExecute.subst(vmovRegCoreUBIop);
387
388    vmovRegCoreUHCode = vfpEnabledCheckCode + '''
389        assert(imm < 2);
390        Dest = bits(FpOp1_uw, imm * 16 + 15, imm * 16);
391    '''
392    vmovRegCoreUHIop = InstObjParams("vmov", "VmovRegCoreUH", "FpRegRegImmOp",
393                                     { "code": vmovRegCoreUHCode,
394                                       "predicate_test": predicateTest,
395                                       "op_class": "SimdFloatMiscOp" }, [])
396    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreUHIop);
397    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreUHIop);
398    exec_output += PredOpExecute.subst(vmovRegCoreUHIop);
399
400    vmovRegCoreSBCode = vfpEnabledCheckCode + '''
401        assert(imm < 4);
402        Dest = sext<8>(bits(FpOp1_uw, imm * 8 + 7, imm * 8));
403    '''
404    vmovRegCoreSBIop = InstObjParams("vmov", "VmovRegCoreSB", "FpRegRegImmOp",
405                                     { "code": vmovRegCoreSBCode,
406                                       "predicate_test": predicateTest,
407                                       "op_class": "SimdFloatMiscOp" }, [])
408    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreSBIop);
409    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreSBIop);
410    exec_output += PredOpExecute.subst(vmovRegCoreSBIop);
411
412    vmovRegCoreSHCode = vfpEnabledCheckCode + '''
413        assert(imm < 2);
414        Dest = sext<16>(bits(FpOp1_uw, imm * 16 + 15, imm * 16));
415    '''
416    vmovRegCoreSHIop = InstObjParams("vmov", "VmovRegCoreSH", "FpRegRegImmOp",
417                                     { "code": vmovRegCoreSHCode,
418                                       "predicate_test": predicateTest,
419                                       "op_class": "SimdFloatMiscOp" }, [])
420    header_output  += FpRegRegImmOpDeclare.subst(vmovRegCoreSHIop);
421    decoder_output  += FpRegRegImmOpConstructor.subst(vmovRegCoreSHIop);
422    exec_output += PredOpExecute.subst(vmovRegCoreSHIop);
423
424    vmovRegCoreWCode = vfpEnabledCheckCode + '''
425        Dest = FpOp1_uw;
426    '''
427    vmovRegCoreWIop = InstObjParams("vmov", "VmovRegCoreW", "FpRegRegOp",
428                                     { "code": vmovRegCoreWCode,
429                                       "predicate_test": predicateTest,
430                                       "op_class": "SimdFloatMiscOp" }, [])
431    header_output  += FpRegRegOpDeclare.subst(vmovRegCoreWIop);
432    decoder_output  += FpRegRegOpConstructor.subst(vmovRegCoreWIop);
433    exec_output += PredOpExecute.subst(vmovRegCoreWIop);
434
435    vmov2Reg2CoreCode = vfpEnabledCheckCode + '''
436        FpDestP0_uw = Op1_uw;
437        FpDestP1_uw = Op2_uw;
438    '''
439    vmov2Reg2CoreIop = InstObjParams("vmov", "Vmov2Reg2Core", "FpRegRegRegOp",
440                                     { "code": vmov2Reg2CoreCode,
441                                       "predicate_test": predicateTest,
442                                       "op_class": "SimdFloatMiscOp" }, [])
443    header_output  += FpRegRegRegOpDeclare.subst(vmov2Reg2CoreIop);
444    decoder_output  += FpRegRegRegOpConstructor.subst(vmov2Reg2CoreIop);
445    exec_output += PredOpExecute.subst(vmov2Reg2CoreIop);
446
447    vmov2Core2RegCode = vfpEnabledCheckCode + '''
448        Dest_uw = FpOp2P0_uw;
449        Op1_uw = FpOp2P1_uw;
450    '''
451    vmov2Core2RegIop = InstObjParams("vmov", "Vmov2Core2Reg", "FpRegRegRegOp",
452                                     { "code": vmov2Core2RegCode,
453                                       "predicate_test": predicateTest,
454                                       "op_class": "SimdFloatMiscOp" }, [])
455    header_output  += FpRegRegRegOpDeclare.subst(vmov2Core2RegIop);
456    decoder_output  += FpRegRegRegOpConstructor.subst(vmov2Core2RegIop);
457    exec_output += PredOpExecute.subst(vmov2Core2RegIop);
458}};
459
460let {{
461
462    header_output = ""
463    decoder_output = ""
464    exec_output = ""
465
466    singleSimpleCode = vfpEnabledCheckCode + '''
467        FPSCR fpscr M5_VAR_USED = (FPSCR) FpscrExc;
468        FpDest = %(op)s;
469    '''
470    singleCode = singleSimpleCode + '''
471        FpscrExc = fpscr;
472    '''
473    singleTernOp = vfpEnabledCheckCode + '''
474        FPSCR fpscr = (FPSCR) FpscrExc;
475        VfpSavedState state = prepFpState(fpscr.rMode);
476        float cOp1 = FpOp1;
477        float cOp2 = FpOp2;
478        float cOp3 = FpDestP0;
479        FpDestP0   = ternaryOp(fpscr, %(palam)s, %(op)s,
480                               fpscr.fz, fpscr.dn, fpscr.rMode);
481        finishVfp(fpscr, state, fpscr.fz);
482        FpscrExc = fpscr;
483    '''
484    singleBinOp = "binaryOp(fpscr, FpOp1, FpOp2," + \
485                "%(func)s, fpscr.fz, fpscr.dn, fpscr.rMode)"
486    singleUnaryOp = "unaryOp(fpscr, FpOp1, %(func)s, fpscr.fz, fpscr.rMode)"
487    doubleCode = vfpEnabledCheckCode + '''
488        FPSCR fpscr M5_VAR_USED = (FPSCR) FpscrExc;
489        double dest = %(op)s;
490        FpDestP0_uw = dblLow(dest);
491        FpDestP1_uw = dblHi(dest);
492        FpscrExc = fpscr;
493    '''
494    doubleTernOp = vfpEnabledCheckCode + '''
495        FPSCR fpscr = (FPSCR) FpscrExc;
496        VfpSavedState state = prepFpState(fpscr.rMode);
497        double cOp1  = dbl(FpOp1P0_uw, FpOp1P1_uw);
498        double cOp2  = dbl(FpOp2P0_uw, FpOp2P1_uw);
499        double cOp3  = dbl(FpDestP0_uw, FpDestP1_uw);
500        double cDest = ternaryOp(fpscr, %(palam)s, %(op)s,
501                                 fpscr.fz, fpscr.dn, fpscr.rMode);
502        FpDestP0_uw  = dblLow(cDest);
503        FpDestP1_uw  = dblHi(cDest);
504        finishVfp(fpscr, state, fpscr.fz);
505        FpscrExc = fpscr;
506    '''
507    doubleBinOp = '''
508        binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
509                        dbl(FpOp2P0_uw, FpOp2P1_uw),
510                        %(func)s, fpscr.fz, fpscr.dn, fpscr.rMode);
511    '''
512    doubleUnaryOp = '''
513        unaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw), %(func)s,
514                fpscr.fz, fpscr.rMode)
515    '''
516
517    def buildTernaryFpOp(Name, base, opClass, singleOp, doubleOp, paramStr):
518        global header_output, decoder_output, exec_output
519
520        code = singleTernOp % { "op": singleOp, "palam": paramStr }
521        sIop = InstObjParams(Name.lower() + "s", Name + "S", base,
522                { "code": code,
523                  "predicate_test": predicateTest,
524                  "op_class": opClass }, [])
525        code = doubleTernOp % { "op": doubleOp, "palam": paramStr }
526        dIop = InstObjParams(Name.lower() + "d", Name + "D", base,
527                { "code": code,
528                  "predicate_test": predicateTest,
529                  "op_class": opClass }, [])
530
531        declareTempl     = eval(base + "Declare");
532        constructorTempl = eval(base + "Constructor");
533
534        for iop in sIop, dIop:
535            header_output  += declareTempl.subst(iop)
536            decoder_output += constructorTempl.subst(iop)
537            exec_output    += PredOpExecute.subst(iop)
538
539    buildTernaryFpOp("Vfma",  "FpRegRegRegOp", "SimdFloatMultAccOp",
540                     "fpMulAdd<float>", "fpMulAdd<double>", " cOp1, cOp2,  cOp3" )
541    buildTernaryFpOp("Vfms",  "FpRegRegRegOp", "SimdFloatMultAccOp",
542                     "fpMulAdd<float>", "fpMulAdd<double>", "-cOp1, cOp2,  cOp3" )
543    buildTernaryFpOp("Vfnma", "FpRegRegRegOp", "SimdFloatMultAccOp",
544                     "fpMulAdd<float>", "fpMulAdd<double>", "-cOp1, cOp2, -cOp3" )
545    buildTernaryFpOp("Vfnms", "FpRegRegRegOp", "SimdFloatMultAccOp",
546                     "fpMulAdd<float>", "fpMulAdd<double>", " cOp1, cOp2, -cOp3" )
547
548    def buildBinFpOp(name, Name, base, opClass, singleOp, doubleOp):
549        global header_output, decoder_output, exec_output
550
551        code = singleCode % { "op": singleBinOp }
552        code = code % { "func": singleOp }
553        sIop = InstObjParams(name + "s", Name + "S", base,
554                { "code": code,
555                  "predicate_test": predicateTest,
556                  "op_class": opClass }, [])
557        code = doubleCode % { "op": doubleBinOp }
558        code = code % { "func": doubleOp }
559        dIop = InstObjParams(name + "d", Name + "D", base,
560                { "code": code,
561                  "predicate_test": predicateTest,
562                  "op_class": opClass }, [])
563
564        declareTempl = eval(base + "Declare");
565        constructorTempl = eval(base + "Constructor");
566
567        for iop in sIop, dIop:
568            header_output += declareTempl.subst(iop)
569            decoder_output += constructorTempl.subst(iop)
570            exec_output += PredOpExecute.subst(iop)
571
572    buildBinFpOp("vadd", "Vadd", "FpRegRegRegOp", "SimdFloatAddOp", "fpAddS",
573                 "fpAddD")
574    buildBinFpOp("vsub", "Vsub", "FpRegRegRegOp", "SimdFloatAddOp", "fpSubS",
575                 "fpSubD")
576    buildBinFpOp("vdiv", "Vdiv", "FpRegRegRegOp", "SimdFloatDivOp", "fpDivS",
577                 "fpDivD")
578    buildBinFpOp("vmul", "Vmul", "FpRegRegRegOp", "SimdFloatMultOp", "fpMulS",
579                 "fpMulD")
580
581    def buildBinOp(name, base, opClass, op):
582        '''
583        Create backported aarch64 instructions that use fplib.
584
585        Because they are backported, these instructions are unconditional.
586        '''
587        global header_output, decoder_output, exec_output
588        inst_datas = [
589            (
590                "s",
591                '''
592                FpDest_uw = fplib%(op)s<>(FpOp1_uw, FpOp2_uw, fpscr);
593                '''
594            ),
595            (
596                "d",
597                '''
598                uint64_t op1 = ((uint64_t)FpOp1P0_uw |
599                               ((uint64_t)FpOp1P1_uw << 32));
600                uint64_t op2 = ((uint64_t)FpOp2P0_uw |
601                               ((uint64_t)FpOp2P1_uw << 32));
602                uint64_t dest = fplib%(op)s<>(op1, op2, fpscr);
603                FpDestP0_uw = dest;
604                FpDestP1_uw = dest >> 32;
605                '''
606            )
607        ]
608        Name = name[0].upper() + name[1:]
609        declareTempl = eval(base + "Declare");
610        constructorTempl = eval(base + "Constructor");
611        for size_suffix, code in inst_datas:
612            code = (
613                '''
614                FPSCR fpscr = (FPSCR)FpscrExc;
615                ''' +
616                code +
617                '''
618                FpscrExc = fpscr;
619                '''
620            )
621            iop = InstObjParams(
622                name + size_suffix,
623                Name + size_suffix.upper(),
624                base,
625                {
626                    "code": code % {"op": op},
627                    "op_class": opClass
628                },
629                []
630            )
631            header_output += declareTempl.subst(iop)
632            decoder_output += constructorTempl.subst(iop)
633            exec_output += BasicExecute.subst(iop)
634    ops = [
635        ("vminnm", "FpRegRegRegOp", "SimdFloatCmpOp", "MinNum"),
636        ("vmaxnm", "FpRegRegRegOp", "SimdFloatCmpOp", "MaxNum"),
637    ]
638    for op in ops:
639        buildBinOp(*op)
640
641    def buildUnaryFpOp(name, Name, base, opClass, singleOp, doubleOp = None):
642        if doubleOp is None:
643            doubleOp = singleOp
644        global header_output, decoder_output, exec_output
645
646        code = singleCode % { "op": singleUnaryOp }
647        code = code % { "func": singleOp }
648        sIop = InstObjParams(name + "s", Name + "S", base,
649                { "code": code,
650                  "predicate_test": predicateTest,
651                  "op_class": opClass }, [])
652        code = doubleCode % { "op": doubleUnaryOp }
653        code = code % { "func": doubleOp }
654        dIop = InstObjParams(name + "d", Name + "D", base,
655                { "code": code,
656                  "predicate_test": predicateTest,
657                  "op_class": opClass }, [])
658
659        declareTempl = eval(base + "Declare");
660        constructorTempl = eval(base + "Constructor");
661
662        for iop in sIop, dIop:
663            header_output += declareTempl.subst(iop)
664            decoder_output += constructorTempl.subst(iop)
665            exec_output += PredOpExecute.subst(iop)
666
667    buildUnaryFpOp("vsqrt", "Vsqrt", "FpRegRegOp", "SimdFloatSqrtOp", "sqrtf",
668                   "sqrt")
669
670    def buildSimpleUnaryFpOp(name, Name, base, opClass, singleOp,
671                             doubleOp = None):
672        if doubleOp is None:
673            doubleOp = singleOp
674        global header_output, decoder_output, exec_output
675
676        sIop = InstObjParams(name + "s", Name + "S", base,
677                { "code": singleSimpleCode % { "op": singleOp },
678                  "predicate_test": predicateTest,
679                  "op_class": opClass }, [])
680        dIop = InstObjParams(name + "d", Name + "D", base,
681                { "code": doubleCode % { "op": doubleOp },
682                  "predicate_test": predicateTest,
683                  "op_class": opClass }, [])
684
685        declareTempl = eval(base + "Declare");
686        constructorTempl = eval(base + "Constructor");
687
688        for iop in sIop, dIop:
689            header_output += declareTempl.subst(iop)
690            decoder_output += constructorTempl.subst(iop)
691            exec_output += PredOpExecute.subst(iop)
692
693    buildSimpleUnaryFpOp("vneg", "Vneg", "FpRegRegOp", "SimdFloatMiscOp",
694                         "-FpOp1", "-dbl(FpOp1P0_uw, FpOp1P1_uw)")
695    buildSimpleUnaryFpOp("vabs", "Vabs", "FpRegRegOp", "SimdFloatMiscOp",
696                         "fabsf(FpOp1)", "fabs(dbl(FpOp1P0_uw, FpOp1P1_uw))")
697    buildSimpleUnaryFpOp("vrintp", "VRIntP", "FpRegRegOp", "SimdFloatMiscOp",
698        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_POSINF, false, fpscr)",
699        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
700        "FPRounding_POSINF, false, fpscr)"
701        )
702    buildSimpleUnaryFpOp("vrintm", "VRIntM", "FpRegRegOp", "SimdFloatMiscOp",
703        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_NEGINF, false, fpscr)",
704        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
705        "FPRounding_NEGINF, false, fpscr)"
706        )
707    buildSimpleUnaryFpOp("vrinta", "VRIntA", "FpRegRegOp", "SimdFloatMiscOp",
708        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_TIEAWAY, false, fpscr)",
709        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
710        "FPRounding_TIEAWAY, false, fpscr)"
711        )
712    buildSimpleUnaryFpOp("vrintn", "VRIntN", "FpRegRegOp", "SimdFloatMiscOp",
713        "fplibRoundInt<uint32_t>(FpOp1, FPRounding_TIEEVEN, false, fpscr)",
714        "fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
715        "FPRounding_TIEEVEN, false, fpscr)"
716        )
717}};
718
719let {{
720
721    header_output = ""
722    decoder_output = ""
723    exec_output = ""
724
725    vmlaSCode = vfpEnabledCheckCode + '''
726        FPSCR fpscr = (FPSCR) FpscrExc;
727        float mid = binaryOp(fpscr, FpOp1, FpOp2,
728                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
729        FpDest = binaryOp(fpscr, FpDest, mid, fpAddS,
730                fpscr.fz, fpscr.dn, fpscr.rMode);
731        FpscrExc = fpscr;
732    '''
733    vmlaSIop = InstObjParams("vmlas", "VmlaS", "FpRegRegRegOp",
734                                     { "code": vmlaSCode,
735                                       "predicate_test": predicateTest,
736                                       "op_class": "SimdFloatMultAccOp" }, [])
737    header_output  += FpRegRegRegOpDeclare.subst(vmlaSIop);
738    decoder_output  += FpRegRegRegOpConstructor.subst(vmlaSIop);
739    exec_output += PredOpExecute.subst(vmlaSIop);
740
741    vmlaDCode = vfpEnabledCheckCode + '''
742        FPSCR fpscr = (FPSCR) FpscrExc;
743        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
744                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
745                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
746        double dest = binaryOp(fpscr, dbl(FpDestP0_uw, FpDestP1_uw),
747                                      mid, fpAddD, fpscr.fz,
748                                      fpscr.dn, fpscr.rMode);
749        FpDestP0_uw = dblLow(dest);
750        FpDestP1_uw = dblHi(dest);
751        FpscrExc = fpscr;
752    '''
753    vmlaDIop = InstObjParams("vmlad", "VmlaD", "FpRegRegRegOp",
754                                     { "code": vmlaDCode,
755                                       "predicate_test": predicateTest,
756                                       "op_class": "SimdFloatMultAccOp" }, [])
757    header_output  += FpRegRegRegOpDeclare.subst(vmlaDIop);
758    decoder_output  += FpRegRegRegOpConstructor.subst(vmlaDIop);
759    exec_output += PredOpExecute.subst(vmlaDIop);
760
761    vmlsSCode = vfpEnabledCheckCode + '''
762        FPSCR fpscr = (FPSCR) FpscrExc;
763        float mid = binaryOp(fpscr, FpOp1, FpOp2,
764                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
765        FpDest = binaryOp(fpscr, FpDest, -mid, fpAddS,
766                fpscr.fz, fpscr.dn, fpscr.rMode);
767        FpscrExc = fpscr;
768    '''
769    vmlsSIop = InstObjParams("vmlss", "VmlsS", "FpRegRegRegOp",
770                                     { "code": vmlsSCode,
771                                       "predicate_test": predicateTest,
772                                       "op_class": "SimdFloatMultAccOp" }, [])
773    header_output  += FpRegRegRegOpDeclare.subst(vmlsSIop);
774    decoder_output  += FpRegRegRegOpConstructor.subst(vmlsSIop);
775    exec_output += PredOpExecute.subst(vmlsSIop);
776
777    vmlsDCode = vfpEnabledCheckCode + '''
778        FPSCR fpscr = (FPSCR) FpscrExc;
779        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
780                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
781                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
782        double dest = binaryOp(fpscr, dbl(FpDestP0_uw, FpDestP1_uw),
783                                      -mid, fpAddD, fpscr.fz,
784                                      fpscr.dn, fpscr.rMode);
785        FpDestP0_uw = dblLow(dest);
786        FpDestP1_uw = dblHi(dest);
787        FpscrExc = fpscr;
788    '''
789    vmlsDIop = InstObjParams("vmlsd", "VmlsD", "FpRegRegRegOp",
790                                     { "code": vmlsDCode,
791                                       "predicate_test": predicateTest,
792                                       "op_class": "SimdFloatMultAccOp" }, [])
793    header_output  += FpRegRegRegOpDeclare.subst(vmlsDIop);
794    decoder_output  += FpRegRegRegOpConstructor.subst(vmlsDIop);
795    exec_output += PredOpExecute.subst(vmlsDIop);
796
797    vnmlaSCode = vfpEnabledCheckCode + '''
798        FPSCR fpscr = (FPSCR) FpscrExc;
799        float mid = binaryOp(fpscr, FpOp1, FpOp2,
800                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
801        FpDest = binaryOp(fpscr, -FpDest, -mid, fpAddS,
802                fpscr.fz, fpscr.dn, fpscr.rMode);
803        FpscrExc = fpscr;
804    '''
805    vnmlaSIop = InstObjParams("vnmlas", "VnmlaS", "FpRegRegRegOp",
806                                     { "code": vnmlaSCode,
807                                       "predicate_test": predicateTest,
808                                       "op_class": "SimdFloatMultAccOp" }, [])
809    header_output  += FpRegRegRegOpDeclare.subst(vnmlaSIop);
810    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlaSIop);
811    exec_output += PredOpExecute.subst(vnmlaSIop);
812
813    vnmlaDCode = vfpEnabledCheckCode + '''
814        FPSCR fpscr = (FPSCR) FpscrExc;
815        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
816                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
817                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
818        double dest = binaryOp(fpscr, -dbl(FpDestP0_uw, FpDestP1_uw),
819                                      -mid, fpAddD, fpscr.fz,
820                                      fpscr.dn, fpscr.rMode);
821        FpDestP0_uw = dblLow(dest);
822        FpDestP1_uw = dblHi(dest);
823        FpscrExc = fpscr;
824    '''
825    vnmlaDIop = InstObjParams("vnmlad", "VnmlaD", "FpRegRegRegOp",
826                                     { "code": vnmlaDCode,
827                                       "predicate_test": predicateTest,
828                                       "op_class": "SimdFloatMultAccOp" }, [])
829    header_output  += FpRegRegRegOpDeclare.subst(vnmlaDIop);
830    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlaDIop);
831    exec_output += PredOpExecute.subst(vnmlaDIop);
832
833    vnmlsSCode = vfpEnabledCheckCode + '''
834        FPSCR fpscr = (FPSCR) FpscrExc;
835        float mid = binaryOp(fpscr, FpOp1, FpOp2,
836                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
837        FpDest = binaryOp(fpscr, -FpDest, mid, fpAddS,
838                fpscr.fz, fpscr.dn, fpscr.rMode);
839        FpscrExc = fpscr;
840    '''
841    vnmlsSIop = InstObjParams("vnmlss", "VnmlsS", "FpRegRegRegOp",
842                              { "code": vnmlsSCode,
843                                "predicate_test": predicateTest,
844                                "op_class": "SimdFloatMultAccOp" }, [])
845    header_output  += FpRegRegRegOpDeclare.subst(vnmlsSIop);
846    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlsSIop);
847    exec_output += PredOpExecute.subst(vnmlsSIop);
848
849    vnmlsDCode = vfpEnabledCheckCode + '''
850        FPSCR fpscr = (FPSCR) FpscrExc;
851        double mid = binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
852                                     dbl(FpOp2P0_uw, FpOp2P1_uw),
853                                     fpMulD, fpscr.fz, fpscr.dn, fpscr.rMode);
854        double dest = binaryOp(fpscr, -dbl(FpDestP0_uw, FpDestP1_uw),
855                                      mid, fpAddD, fpscr.fz,
856                                      fpscr.dn, fpscr.rMode);
857        FpDestP0_uw = dblLow(dest);
858        FpDestP1_uw = dblHi(dest);
859        FpscrExc = fpscr;
860    '''
861    vnmlsDIop = InstObjParams("vnmlsd", "VnmlsD", "FpRegRegRegOp",
862                              { "code": vnmlsDCode,
863                                "predicate_test": predicateTest,
864                                "op_class": "SimdFloatMultAccOp" }, [])
865    header_output  += FpRegRegRegOpDeclare.subst(vnmlsDIop);
866    decoder_output  += FpRegRegRegOpConstructor.subst(vnmlsDIop);
867    exec_output += PredOpExecute.subst(vnmlsDIop);
868
869    vnmulSCode = vfpEnabledCheckCode + '''
870        FPSCR fpscr = (FPSCR) FpscrExc;
871        FpDest = -binaryOp(fpscr, FpOp1, FpOp2, fpMulS,
872                fpscr.fz, fpscr.dn, fpscr.rMode);
873        FpscrExc = fpscr;
874    '''
875    vnmulSIop = InstObjParams("vnmuls", "VnmulS", "FpRegRegRegOp",
876                              { "code": vnmulSCode,
877                                "predicate_test": predicateTest,
878                                "op_class": "SimdFloatMultOp" }, [])
879    header_output  += FpRegRegRegOpDeclare.subst(vnmulSIop);
880    decoder_output  += FpRegRegRegOpConstructor.subst(vnmulSIop);
881    exec_output += PredOpExecute.subst(vnmulSIop);
882
883    vnmulDCode = vfpEnabledCheckCode + '''
884        FPSCR fpscr = (FPSCR) FpscrExc;
885        double dest = -binaryOp(fpscr, dbl(FpOp1P0_uw, FpOp1P1_uw),
886                                       dbl(FpOp2P0_uw, FpOp2P1_uw),
887                                       fpMulD, fpscr.fz, fpscr.dn,
888                                       fpscr.rMode);
889        FpDestP0_uw = dblLow(dest);
890        FpDestP1_uw = dblHi(dest);
891        FpscrExc = fpscr;
892    '''
893    vnmulDIop = InstObjParams("vnmuld", "VnmulD", "FpRegRegRegOp",
894                                     { "code": vnmulDCode,
895                                       "predicate_test": predicateTest,
896                                       "op_class": "SimdFloatMultOp" }, [])
897    header_output += FpRegRegRegOpDeclare.subst(vnmulDIop);
898    decoder_output += FpRegRegRegOpConstructor.subst(vnmulDIop);
899    exec_output += PredOpExecute.subst(vnmulDIop);
900}};
901
902let {{
903
904    header_output = ""
905    decoder_output = ""
906    exec_output = ""
907
908    vcvtUIntFpSCode = vfpEnabledCheckCode + '''
909        FPSCR fpscr = (FPSCR) FpscrExc;
910        VfpSavedState state = prepFpState(fpscr.rMode);
911        __asm__ __volatile__("" : "=m" (FpOp1_uw) : "m" (FpOp1_uw));
912        FpDest = FpOp1_uw;
913        __asm__ __volatile__("" :: "m" (FpDest));
914        finishVfp(fpscr, state, fpscr.fz);
915        FpscrExc = fpscr;
916    '''
917    vcvtUIntFpSIop = InstObjParams("vcvt", "VcvtUIntFpS", "FpRegRegOp",
918                                     { "code": vcvtUIntFpSCode,
919                                       "predicate_test": predicateTest,
920                                       "op_class": "SimdFloatCvtOp" }, [])
921    header_output += FpRegRegOpDeclare.subst(vcvtUIntFpSIop);
922    decoder_output += FpRegRegOpConstructor.subst(vcvtUIntFpSIop);
923    exec_output += PredOpExecute.subst(vcvtUIntFpSIop);
924
925    vcvtUIntFpDCode = vfpEnabledCheckCode + '''
926        FPSCR fpscr = (FPSCR) FpscrExc;
927        VfpSavedState state = prepFpState(fpscr.rMode);
928        __asm__ __volatile__("" : "=m" (FpOp1P0_uw) : "m" (FpOp1P0_uw));
929        double cDest = (uint64_t)FpOp1P0_uw;
930        __asm__ __volatile__("" :: "m" (cDest));
931        finishVfp(fpscr, state, fpscr.fz);
932        FpDestP0_uw = dblLow(cDest);
933        FpDestP1_uw = dblHi(cDest);
934        FpscrExc = fpscr;
935    '''
936    vcvtUIntFpDIop = InstObjParams("vcvt", "VcvtUIntFpD", "FpRegRegOp",
937                                     { "code": vcvtUIntFpDCode,
938                                       "predicate_test": predicateTest,
939                                       "op_class": "SimdFloatCvtOp" }, [])
940    header_output += FpRegRegOpDeclare.subst(vcvtUIntFpDIop);
941    decoder_output += FpRegRegOpConstructor.subst(vcvtUIntFpDIop);
942    exec_output += PredOpExecute.subst(vcvtUIntFpDIop);
943
944    vcvtSIntFpSCode = vfpEnabledCheckCode + '''
945        FPSCR fpscr = (FPSCR) FpscrExc;
946        VfpSavedState state = prepFpState(fpscr.rMode);
947        __asm__ __volatile__("" : "=m" (FpOp1_sw) : "m" (FpOp1_sw));
948        FpDest = FpOp1_sw;
949        __asm__ __volatile__("" :: "m" (FpDest));
950        finishVfp(fpscr, state, fpscr.fz);
951        FpscrExc = fpscr;
952    '''
953    vcvtSIntFpSIop = InstObjParams("vcvt", "VcvtSIntFpS", "FpRegRegOp",
954                                     { "code": vcvtSIntFpSCode,
955                                       "predicate_test": predicateTest,
956                                       "op_class": "SimdFloatCvtOp" }, [])
957    header_output += FpRegRegOpDeclare.subst(vcvtSIntFpSIop);
958    decoder_output += FpRegRegOpConstructor.subst(vcvtSIntFpSIop);
959    exec_output += PredOpExecute.subst(vcvtSIntFpSIop);
960
961    vcvtSIntFpDCode = vfpEnabledCheckCode + '''
962        FPSCR fpscr = (FPSCR) FpscrExc;
963        VfpSavedState state = prepFpState(fpscr.rMode);
964        __asm__ __volatile__("" : "=m" (FpOp1P0_sw) : "m" (FpOp1P0_sw));
965        double cDest = FpOp1P0_sw;
966        __asm__ __volatile__("" :: "m" (cDest));
967        finishVfp(fpscr, state, fpscr.fz);
968        FpDestP0_uw = dblLow(cDest);
969        FpDestP1_uw = dblHi(cDest);
970        FpscrExc = fpscr;
971    '''
972    vcvtSIntFpDIop = InstObjParams("vcvt", "VcvtSIntFpD", "FpRegRegOp",
973                                     { "code": vcvtSIntFpDCode,
974                                       "predicate_test": predicateTest,
975                                       "op_class": "SimdFloatCvtOp" }, [])
976    header_output += FpRegRegOpDeclare.subst(vcvtSIntFpDIop);
977    decoder_output += FpRegRegOpConstructor.subst(vcvtSIntFpDIop);
978    exec_output += PredOpExecute.subst(vcvtSIntFpDIop);
979
980    vcvtFpUIntSRCode = vfpEnabledCheckCode + '''
981        FPSCR fpscr = (FPSCR) FpscrExc;
982        VfpSavedState state = prepFpState(fpscr.rMode);
983        vfpFlushToZero(fpscr, FpOp1);
984        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
985        FpDest_uw = vfpFpToFixed<float>(FpOp1, false, 32, 0, false);
986        __asm__ __volatile__("" :: "m" (FpDest_uw));
987        finishVfp(fpscr, state, fpscr.fz);
988        FpscrExc = fpscr;
989    '''
990    vcvtFpUIntSRIop = InstObjParams("vcvt", "VcvtFpUIntSR", "FpRegRegOp",
991                                     { "code": vcvtFpUIntSRCode,
992                                       "predicate_test": predicateTest,
993                                       "op_class": "SimdFloatCvtOp" }, [])
994    header_output += FpRegRegOpDeclare.subst(vcvtFpUIntSRIop);
995    decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntSRIop);
996    exec_output += PredOpExecute.subst(vcvtFpUIntSRIop);
997
998    vcvtFpUIntDRCode = vfpEnabledCheckCode + '''
999        FPSCR fpscr = (FPSCR) FpscrExc;
1000        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1001        vfpFlushToZero(fpscr, cOp1);
1002        VfpSavedState state = prepFpState(fpscr.rMode);
1003        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1004        uint64_t result = vfpFpToFixed<double>(cOp1, false, 32, 0, false);
1005        __asm__ __volatile__("" :: "m" (result));
1006        finishVfp(fpscr, state, fpscr.fz);
1007        FpDestP0_uw = result;
1008        FpscrExc = fpscr;
1009    '''
1010    vcvtFpUIntDRIop = InstObjParams("vcvtr", "VcvtFpUIntDR", "FpRegRegOp",
1011                                     { "code": vcvtFpUIntDRCode,
1012                                       "predicate_test": predicateTest,
1013                                       "op_class": "SimdFloatCvtOp" }, [])
1014    header_output += FpRegRegOpDeclare.subst(vcvtFpUIntDRIop);
1015    decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntDRIop);
1016    exec_output += PredOpExecute.subst(vcvtFpUIntDRIop);
1017
1018    vcvtFpSIntSRCode = vfpEnabledCheckCode + '''
1019        FPSCR fpscr = (FPSCR) FpscrExc;
1020        VfpSavedState state = prepFpState(fpscr.rMode);
1021        vfpFlushToZero(fpscr, FpOp1);
1022        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1023        FpDest_sw = vfpFpToFixed<float>(FpOp1, true, 32, 0, false);
1024        __asm__ __volatile__("" :: "m" (FpDest_sw));
1025        finishVfp(fpscr, state, fpscr.fz);
1026        FpscrExc = fpscr;
1027    '''
1028    vcvtFpSIntSRIop = InstObjParams("vcvtr", "VcvtFpSIntSR", "FpRegRegOp",
1029                                     { "code": vcvtFpSIntSRCode,
1030                                        "predicate_test": predicateTest,
1031                                        "op_class": "SimdFloatCvtOp" }, [])
1032    header_output += FpRegRegOpDeclare.subst(vcvtFpSIntSRIop);
1033    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntSRIop);
1034    exec_output += PredOpExecute.subst(vcvtFpSIntSRIop);
1035
1036    vcvtFpSIntDRCode = vfpEnabledCheckCode + '''
1037        FPSCR fpscr = (FPSCR) FpscrExc;
1038        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1039        vfpFlushToZero(fpscr, cOp1);
1040        VfpSavedState state = prepFpState(fpscr.rMode);
1041        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1042        int64_t result = vfpFpToFixed<double>(cOp1, true, 32, 0, false);
1043        __asm__ __volatile__("" :: "m" (result));
1044        finishVfp(fpscr, state, fpscr.fz);
1045        FpDestP0_uw = result;
1046        FpscrExc = fpscr;
1047    '''
1048    vcvtFpSIntDRIop = InstObjParams("vcvtr", "VcvtFpSIntDR", "FpRegRegOp",
1049                                     { "code": vcvtFpSIntDRCode,
1050                                       "predicate_test": predicateTest,
1051                                       "op_class": "SimdFloatCvtOp" }, [])
1052    header_output += FpRegRegOpDeclare.subst(vcvtFpSIntDRIop);
1053    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntDRIop);
1054    exec_output += PredOpExecute.subst(vcvtFpSIntDRIop);
1055
1056    round_mode_suffix_to_mode = {
1057        '': 'VfpRoundZero',
1058        'a': 'VfpRoundAway',
1059        'm': 'VfpRoundDown',
1060        'n': 'VfpRoundNearest',
1061        'p': 'VfpRoundUpward',
1062    }
1063
1064    def buildVcvt(code, className, roundModeSuffix):
1065        global header_output, decoder_output, exec_output, \
1066            vfpEnabledCheckCode, round_mode_suffix_to_mode
1067        full_code = vfpEnabledCheckCode + code.format(
1068            round_mode=round_mode_suffix_to_mode[roundModeSuffix],
1069        )
1070        iop = InstObjParams(
1071            "vcvt{}".format(roundModeSuffix),
1072            className.format(roundModeSuffix),
1073            "FpRegRegOp",
1074            { "code": full_code,
1075              "predicate_test": predicateTest,
1076              "op_class": "SimdFloatCvtOp" },
1077            []
1078        )
1079        header_output += FpRegRegOpDeclare.subst(iop);
1080        decoder_output += FpRegRegOpConstructor.subst(iop);
1081        exec_output += PredOpExecute.subst(iop);
1082
1083    code = '''
1084        FPSCR fpscr = (FPSCR) FpscrExc;
1085        vfpFlushToZero(fpscr, FpOp1);
1086        VfpSavedState state = prepFpState(fpscr.rMode);
1087        fesetround(FeRoundZero);
1088        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1089        FpDest_uw = vfpFpToFixed<float>(
1090            FpOp1, false, 32, 0, true, {round_mode});
1091        __asm__ __volatile__("" :: "m" (FpDest_uw));
1092        finishVfp(fpscr, state, fpscr.fz);
1093        FpscrExc = fpscr;
1094    '''
1095    for round_mode_suffix in round_mode_suffix_to_mode:
1096        buildVcvt(code, "Vcvt{}FpUIntS", round_mode_suffix)
1097
1098    code = '''
1099        FPSCR fpscr = (FPSCR) FpscrExc;
1100        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1101        vfpFlushToZero(fpscr, cOp1);
1102        VfpSavedState state = prepFpState(fpscr.rMode);
1103        fesetround(FeRoundZero);
1104        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1105        uint64_t result = vfpFpToFixed<double>(
1106            cOp1, false, 32, 0, true, {round_mode});
1107        __asm__ __volatile__("" :: "m" (result));
1108        finishVfp(fpscr, state, fpscr.fz);
1109        FpDestP0_uw = result;
1110        FpscrExc = fpscr;
1111    '''
1112    for round_mode_suffix in round_mode_suffix_to_mode:
1113        buildVcvt(code, "Vcvt{}FpUIntD", round_mode_suffix)
1114
1115    code = '''
1116        FPSCR fpscr = (FPSCR) FpscrExc;
1117        vfpFlushToZero(fpscr, FpOp1);
1118        VfpSavedState state = prepFpState(fpscr.rMode);
1119        fesetround(FeRoundZero);
1120        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1121        FpDest_sw = vfpFpToFixed<float>(
1122            FpOp1, true, 32, 0, true, {round_mode});
1123        __asm__ __volatile__("" :: "m" (FpDest_sw));
1124        finishVfp(fpscr, state, fpscr.fz);
1125        FpscrExc = fpscr;
1126    '''
1127    for round_mode_suffix in round_mode_suffix_to_mode:
1128        buildVcvt(code, "Vcvt{}FpSIntS", round_mode_suffix)
1129
1130    code = '''
1131        FPSCR fpscr = (FPSCR) FpscrExc;
1132        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1133        vfpFlushToZero(fpscr, cOp1);
1134        VfpSavedState state = prepFpState(fpscr.rMode);
1135        fesetround(FeRoundZero);
1136        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1137        int64_t result = vfpFpToFixed<double>(
1138            cOp1, true, 32, 0, true, {round_mode});
1139        __asm__ __volatile__("" :: "m" (result));
1140        finishVfp(fpscr, state, fpscr.fz);
1141        FpDestP0_uw = result;
1142        FpscrExc = fpscr;
1143    '''
1144    for round_mode_suffix in round_mode_suffix_to_mode:
1145        buildVcvt(code, "Vcvt{}FpSIntD", round_mode_suffix)
1146
1147    vcvtFpSFpDCode = vfpEnabledCheckCode + '''
1148        FPSCR fpscr = (FPSCR) FpscrExc;
1149        vfpFlushToZero(fpscr, FpOp1);
1150        VfpSavedState state = prepFpState(fpscr.rMode);
1151        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1152        double cDest = fixFpSFpDDest(FpscrExc, FpOp1);
1153        __asm__ __volatile__("" :: "m" (cDest));
1154        finishVfp(fpscr, state, fpscr.fz);
1155        FpDestP0_uw = dblLow(cDest);
1156        FpDestP1_uw = dblHi(cDest);
1157        FpscrExc = fpscr;
1158    '''
1159    vcvtFpSFpDIop = InstObjParams("vcvt", "VcvtFpSFpD", "FpRegRegOp",
1160                                     { "code": vcvtFpSFpDCode,
1161                                       "predicate_test": predicateTest,
1162                                       "op_class": "SimdFloatCvtOp" }, [])
1163    header_output += FpRegRegOpDeclare.subst(vcvtFpSFpDIop);
1164    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpDIop);
1165    exec_output += PredOpExecute.subst(vcvtFpSFpDIop);
1166
1167    vcvtFpDFpSCode = vfpEnabledCheckCode + '''
1168        FPSCR fpscr = (FPSCR) FpscrExc;
1169        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1170        vfpFlushToZero(fpscr, cOp1);
1171        VfpSavedState state = prepFpState(fpscr.rMode);
1172        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1173        FpDest = fixFpDFpSDest(FpscrExc, cOp1);
1174        __asm__ __volatile__("" :: "m" (FpDest));
1175        finishVfp(fpscr, state, fpscr.fz);
1176        FpscrExc = fpscr;
1177    '''
1178    vcvtFpDFpSIop = InstObjParams("vcvt", "VcvtFpDFpS", "FpRegRegOp",
1179                                     { "code": vcvtFpDFpSCode,
1180                                       "predicate_test": predicateTest,
1181                                       "op_class": "SimdFloatCvtOp" }, [])
1182    header_output += FpRegRegOpDeclare.subst(vcvtFpDFpSIop);
1183    decoder_output += FpRegRegOpConstructor.subst(vcvtFpDFpSIop);
1184    exec_output += PredOpExecute.subst(vcvtFpDFpSIop);
1185
1186    vcvtFpHTFpSCode = vfpEnabledCheckCode + '''
1187        FPSCR fpscr = (FPSCR) FpscrExc;
1188        vfpFlushToZero(fpscr, FpOp1);
1189        VfpSavedState state = prepFpState(fpscr.rMode);
1190        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1191        FpDest = vcvtFpHFpS(fpscr, fpscr.dn, fpscr.ahp,
1192                            bits(fpToBits(FpOp1), 31, 16));
1193        __asm__ __volatile__("" :: "m" (FpDest));
1194        finishVfp(fpscr, state, fpscr.fz);
1195        FpscrExc = fpscr;
1196    '''
1197    vcvtFpHTFpSIop = InstObjParams("vcvtt", "VcvtFpHTFpS", "FpRegRegOp",
1198                                   { "code": vcvtFpHTFpSCode,
1199                                     "predicate_test": predicateTest,
1200                                     "op_class": "SimdFloatCvtOp" }, [])
1201    header_output += FpRegRegOpDeclare.subst(vcvtFpHTFpSIop);
1202    decoder_output += FpRegRegOpConstructor.subst(vcvtFpHTFpSIop);
1203    exec_output += PredOpExecute.subst(vcvtFpHTFpSIop);
1204
1205    vcvtFpHBFpSCode = vfpEnabledCheckCode + '''
1206        FPSCR fpscr = (FPSCR) FpscrExc;
1207        VfpSavedState state = prepFpState(fpscr.rMode);
1208        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1209        FpDest = vcvtFpHFpS(fpscr, fpscr.dn, fpscr.ahp,
1210                            bits(fpToBits(FpOp1), 15, 0));
1211        __asm__ __volatile__("" :: "m" (FpDest));
1212        finishVfp(fpscr, state, fpscr.fz);
1213        FpscrExc = fpscr;
1214    '''
1215    vcvtFpHBFpSIop = InstObjParams("vcvtb", "VcvtFpHBFpS", "FpRegRegOp",
1216                                   { "code": vcvtFpHBFpSCode,
1217                                     "predicate_test": predicateTest,
1218                                     "op_class": "SimdFloatCvtOp" }, [])
1219    header_output += FpRegRegOpDeclare.subst(vcvtFpHBFpSIop);
1220    decoder_output += FpRegRegOpConstructor.subst(vcvtFpHBFpSIop);
1221    exec_output += PredOpExecute.subst(vcvtFpHBFpSIop);
1222
1223    vcvtFpSFpHTCode = vfpEnabledCheckCode + '''
1224        FPSCR fpscr = (FPSCR) FpscrExc;
1225        vfpFlushToZero(fpscr, FpOp1);
1226        VfpSavedState state = prepFpState(fpscr.rMode);
1227        __asm__ __volatile__("" : "=m" (FpOp1), "=m" (FpDest_uw)
1228                                : "m" (FpOp1), "m" (FpDest_uw));
1229        FpDest_uw = insertBits(FpDest_uw, 31, 16,,
1230                               vcvtFpSFpH(fpscr, fpscr.fz, fpscr.dn,
1231                               fpscr.rMode, fpscr.ahp, FpOp1));
1232        __asm__ __volatile__("" :: "m" (FpDest_uw));
1233        finishVfp(fpscr, state, fpscr.fz);
1234        FpscrExc = fpscr;
1235    '''
1236    vcvtFpSFpHTIop = InstObjParams("vcvtt", "VcvtFpSFpHT", "FpRegRegOp",
1237                                    { "code": vcvtFpHTFpSCode,
1238                                      "predicate_test": predicateTest,
1239                                      "op_class": "SimdFloatCvtOp" }, [])
1240    header_output += FpRegRegOpDeclare.subst(vcvtFpSFpHTIop);
1241    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpHTIop);
1242    exec_output += PredOpExecute.subst(vcvtFpSFpHTIop);
1243
1244    vcvtFpSFpHBCode = vfpEnabledCheckCode + '''
1245        FPSCR fpscr = (FPSCR) FpscrExc;
1246        vfpFlushToZero(fpscr, FpOp1);
1247        VfpSavedState state = prepFpState(fpscr.rMode);
1248        __asm__ __volatile__("" : "=m" (FpOp1), "=m" (FpDest_uw)
1249                                : "m" (FpOp1), "m" (FpDest_uw));
1250        FpDest_uw = insertBits(FpDest_uw, 15, 0,
1251                               vcvtFpSFpH(fpscr, fpscr.fz, fpscr.dn,
1252                               fpscr.rMode, fpscr.ahp, FpOp1));
1253        __asm__ __volatile__("" :: "m" (FpDest_uw));
1254        finishVfp(fpscr, state, fpscr.fz);
1255        FpscrExc = fpscr;
1256    '''
1257    vcvtFpSFpHBIop = InstObjParams("vcvtb", "VcvtFpSFpHB", "FpRegRegOp",
1258                                   { "code": vcvtFpSFpHBCode,
1259                                     "predicate_test": predicateTest,
1260                                     "op_class": "SimdFloatCvtOp" }, [])
1261    header_output += FpRegRegOpDeclare.subst(vcvtFpSFpHBIop);
1262    decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpHBIop);
1263    exec_output += PredOpExecute.subst(vcvtFpSFpHBIop);
1264
1265    vcmpSCode = vfpEnabledCheckCode + '''
1266        FPSCR fpscr = (FPSCR) FpscrExc;
1267        vfpFlushToZero(fpscr, FpDest, FpOp1);
1268        if (FpDest == FpOp1) {
1269            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1270        } else if (FpDest < FpOp1) {
1271            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1272        } else if (FpDest > FpOp1) {
1273            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1274        } else {
1275            const uint32_t qnan = 0x7fc00000;
1276            const bool nan1 = std::isnan(FpDest);
1277            const bool signal1 = nan1 && ((fpToBits(FpDest) & qnan) != qnan);
1278            const bool nan2 = std::isnan(FpOp1);
1279            const bool signal2 = nan2 && ((fpToBits(FpOp1) & qnan) != qnan);
1280            if (signal1 || signal2)
1281                fpscr.ioc = 1;
1282            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1283        }
1284        FpCondCodes = fpscr & FpCondCodesMask;
1285        FpscrExc = fpscr;
1286    '''
1287    vcmpSIop = InstObjParams("vcmps", "VcmpS", "FpRegRegOp",
1288                                     { "code": vcmpSCode,
1289                                       "predicate_test": predicateTest,
1290                                       "op_class": "SimdFloatCmpOp" }, [])
1291    header_output += FpRegRegOpDeclare.subst(vcmpSIop);
1292    decoder_output += FpRegRegOpConstructor.subst(vcmpSIop);
1293    exec_output += PredOpExecute.subst(vcmpSIop);
1294
1295    vcmpDCode = vfpEnabledCheckCode + '''
1296        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1297        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
1298        FPSCR fpscr = (FPSCR) FpscrExc;
1299        vfpFlushToZero(fpscr, cDest, cOp1);
1300        if (cDest == cOp1) {
1301            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1302        } else if (cDest < cOp1) {
1303            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1304        } else if (cDest > cOp1) {
1305            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1306        } else {
1307            const uint64_t qnan = ULL(0x7ff8000000000000);
1308            const bool nan1 = std::isnan(cDest);
1309            const bool signal1 = nan1 && ((fpToBits(cDest) & qnan) != qnan);
1310            const bool nan2 = std::isnan(cOp1);
1311            const bool signal2 = nan2 && ((fpToBits(cOp1) & qnan) != qnan);
1312            if (signal1 || signal2)
1313                fpscr.ioc = 1;
1314            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1315        }
1316        FpCondCodes = fpscr & FpCondCodesMask;
1317        FpscrExc = fpscr;
1318    '''
1319    vcmpDIop = InstObjParams("vcmpd", "VcmpD", "FpRegRegOp",
1320                                     { "code": vcmpDCode,
1321                                       "predicate_test": predicateTest,
1322                                       "op_class": "SimdFloatCmpOp" }, [])
1323    header_output += FpRegRegOpDeclare.subst(vcmpDIop);
1324    decoder_output += FpRegRegOpConstructor.subst(vcmpDIop);
1325    exec_output += PredOpExecute.subst(vcmpDIop);
1326
1327    vcmpZeroSCode = vfpEnabledCheckCode + '''
1328        FPSCR fpscr = (FPSCR) FpscrExc;
1329        vfpFlushToZero(fpscr, FpDest);
1330        // This only handles imm == 0 for now.
1331        assert(imm == 0);
1332        if (FpDest == imm) {
1333            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1334        } else if (FpDest < imm) {
1335            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1336        } else if (FpDest > imm) {
1337            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1338        } else {
1339            const uint32_t qnan = 0x7fc00000;
1340            const bool nan = std::isnan(FpDest);
1341            const bool signal = nan && ((fpToBits(FpDest) & qnan) != qnan);
1342            if (signal)
1343                fpscr.ioc = 1;
1344            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1345        }
1346        FpCondCodes = fpscr & FpCondCodesMask;
1347        FpscrExc = fpscr;
1348    '''
1349    vcmpZeroSIop = InstObjParams("vcmpZeros", "VcmpZeroS", "FpRegImmOp",
1350                                     { "code": vcmpZeroSCode,
1351                                       "predicate_test": predicateTest,
1352                                       "op_class": "SimdFloatCmpOp" }, [])
1353    header_output += FpRegImmOpDeclare.subst(vcmpZeroSIop);
1354    decoder_output += FpRegImmOpConstructor.subst(vcmpZeroSIop);
1355    exec_output += PredOpExecute.subst(vcmpZeroSIop);
1356
1357    vcmpZeroDCode = vfpEnabledCheckCode + '''
1358        // This only handles imm == 0 for now.
1359        assert(imm == 0);
1360        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
1361        FPSCR fpscr = (FPSCR) FpscrExc;
1362        vfpFlushToZero(fpscr, cDest);
1363        if (cDest == imm) {
1364            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1365        } else if (cDest < imm) {
1366            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1367        } else if (cDest > imm) {
1368            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1369        } else {
1370            const uint64_t qnan = ULL(0x7ff8000000000000);
1371            const bool nan = std::isnan(cDest);
1372            const bool signal = nan && ((fpToBits(cDest) & qnan) != qnan);
1373            if (signal)
1374                fpscr.ioc = 1;
1375            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1376        }
1377        FpCondCodes = fpscr & FpCondCodesMask;
1378        FpscrExc = fpscr;
1379    '''
1380    vcmpZeroDIop = InstObjParams("vcmpZerod", "VcmpZeroD", "FpRegImmOp",
1381                                     { "code": vcmpZeroDCode,
1382                                       "predicate_test": predicateTest,
1383                                       "op_class": "SimdFloatCmpOp" }, [])
1384    header_output += FpRegImmOpDeclare.subst(vcmpZeroDIop);
1385    decoder_output += FpRegImmOpConstructor.subst(vcmpZeroDIop);
1386    exec_output += PredOpExecute.subst(vcmpZeroDIop);
1387
1388    vcmpeSCode = vfpEnabledCheckCode + '''
1389        FPSCR fpscr = (FPSCR) FpscrExc;
1390        vfpFlushToZero(fpscr, FpDest, FpOp1);
1391        if (FpDest == FpOp1) {
1392            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1393        } else if (FpDest < FpOp1) {
1394            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1395        } else if (FpDest > FpOp1) {
1396            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1397        } else {
1398            fpscr.ioc = 1;
1399            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1400        }
1401        FpCondCodes = fpscr & FpCondCodesMask;
1402        FpscrExc = fpscr;
1403    '''
1404    vcmpeSIop = InstObjParams("vcmpes", "VcmpeS", "FpRegRegOp",
1405                                     { "code": vcmpeSCode,
1406                                       "predicate_test": predicateTest,
1407                                       "op_class": "SimdFloatCmpOp" }, [])
1408    header_output += FpRegRegOpDeclare.subst(vcmpeSIop);
1409    decoder_output += FpRegRegOpConstructor.subst(vcmpeSIop);
1410    exec_output += PredOpExecute.subst(vcmpeSIop);
1411
1412    vcmpeDCode = vfpEnabledCheckCode + '''
1413        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1414        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
1415        FPSCR fpscr = (FPSCR) FpscrExc;
1416        vfpFlushToZero(fpscr, cDest, cOp1);
1417        if (cDest == cOp1) {
1418            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1419        } else if (cDest < cOp1) {
1420            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1421        } else if (cDest > cOp1) {
1422            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1423        } else {
1424            fpscr.ioc = 1;
1425            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1426        }
1427        FpCondCodes = fpscr & FpCondCodesMask;
1428        FpscrExc = fpscr;
1429    '''
1430    vcmpeDIop = InstObjParams("vcmped", "VcmpeD", "FpRegRegOp",
1431                                     { "code": vcmpeDCode,
1432                                       "predicate_test": predicateTest,
1433                                       "op_class": "SimdFloatCmpOp" }, [])
1434    header_output += FpRegRegOpDeclare.subst(vcmpeDIop);
1435    decoder_output += FpRegRegOpConstructor.subst(vcmpeDIop);
1436    exec_output += PredOpExecute.subst(vcmpeDIop);
1437
1438    vcmpeZeroSCode = vfpEnabledCheckCode + '''
1439        FPSCR fpscr = (FPSCR) FpscrExc;
1440        vfpFlushToZero(fpscr, FpDest);
1441        if (FpDest == imm) {
1442            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1443        } else if (FpDest < imm) {
1444            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1445        } else if (FpDest > imm) {
1446            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1447        } else {
1448            fpscr.ioc = 1;
1449            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1450        }
1451        FpCondCodes = fpscr & FpCondCodesMask;
1452        FpscrExc = fpscr;
1453    '''
1454    vcmpeZeroSIop = InstObjParams("vcmpeZeros", "VcmpeZeroS", "FpRegImmOp",
1455                                     { "code": vcmpeZeroSCode,
1456                                       "predicate_test": predicateTest,
1457                                       "op_class": "SimdFloatCmpOp" }, [])
1458    header_output += FpRegImmOpDeclare.subst(vcmpeZeroSIop);
1459    decoder_output += FpRegImmOpConstructor.subst(vcmpeZeroSIop);
1460    exec_output += PredOpExecute.subst(vcmpeZeroSIop);
1461
1462    vcmpeZeroDCode = vfpEnabledCheckCode + '''
1463        double cDest = dbl(FpDestP0_uw, FpDestP1_uw);
1464        FPSCR fpscr = (FPSCR) FpscrExc;
1465        vfpFlushToZero(fpscr, cDest);
1466        if (cDest == imm) {
1467            fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0;
1468        } else if (cDest < imm) {
1469            fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0;
1470        } else if (cDest > imm) {
1471            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0;
1472        } else {
1473            fpscr.ioc = 1;
1474            fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1;
1475        }
1476        FpCondCodes = fpscr & FpCondCodesMask;
1477        FpscrExc = fpscr;
1478    '''
1479    vcmpeZeroDIop = InstObjParams("vcmpeZerod", "VcmpeZeroD", "FpRegImmOp",
1480                                     { "code": vcmpeZeroDCode,
1481                                       "predicate_test": predicateTest,
1482                                       "op_class": "SimdFloatCmpOp" }, [])
1483    header_output += FpRegImmOpDeclare.subst(vcmpeZeroDIop);
1484    decoder_output += FpRegImmOpConstructor.subst(vcmpeZeroDIop);
1485    exec_output += PredOpExecute.subst(vcmpeZeroDIop);
1486}};
1487
1488let {{
1489
1490    header_output = ""
1491    decoder_output = ""
1492    exec_output = ""
1493
1494    vselSCode = vfpEnabledCheckCode + '''
1495        if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, cond)) {
1496            FpDest = FpOp1;
1497        } else {
1498            FpDest = FpOp2;
1499        } '''
1500
1501    vselSIop = InstObjParams("vsels", "VselS", "FpRegRegRegCondOp",
1502                             { "code" : vselSCode,
1503                               "predicate_test" : predicateTest,
1504                               "op_class" : "SimdFloatCmpOp" }, [] )
1505    header_output += FpRegRegRegCondOpDeclare.subst(vselSIop);
1506    decoder_output += FpRegRegRegCondOpConstructor.subst(vselSIop);
1507    exec_output +=  PredOpExecute.subst(vselSIop);
1508
1509    vselDCode = vfpEnabledCheckCode + '''
1510        if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, cond)) {
1511            FpDestP0_uw = FpOp1P0_uw;
1512            FpDestP1_uw = FpOp1P1_uw;
1513        } else {
1514            FpDestP0_uw = FpOp2P0_uw;
1515            FpDestP1_uw = FpOp2P1_uw;
1516        } '''
1517
1518    vselDIop = InstObjParams("vseld", "VselD", "FpRegRegRegCondOp",
1519                             { "code" : vselDCode,
1520                               "predicate_test" : predicateTest,
1521                               "op_class" : "SimdFloatCmpOp" }, [] )
1522    header_output += FpRegRegRegCondOpDeclare.subst(vselDIop);
1523    decoder_output += FpRegRegRegCondOpConstructor.subst(vselDIop);
1524    exec_output +=  PredOpExecute.subst(vselDIop);
1525}};
1526
1527
1528let {{
1529
1530    header_output = ""
1531    decoder_output = ""
1532    exec_output = ""
1533
1534    vcvtFpSFixedSCode = vfpEnabledCheckCode + '''
1535        FPSCR fpscr = (FPSCR) FpscrExc;
1536        vfpFlushToZero(fpscr, FpOp1);
1537        VfpSavedState state = prepFpState(fpscr.rMode);
1538        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1539        FpDest_sw = vfpFpToFixed<float>(FpOp1, true, 32, imm);
1540        __asm__ __volatile__("" :: "m" (FpDest_sw));
1541        finishVfp(fpscr, state, fpscr.fz);
1542        FpscrExc = fpscr;
1543    '''
1544    vcvtFpSFixedSIop = InstObjParams("vcvt", "VcvtFpSFixedS", "FpRegRegImmOp",
1545                                     { "code": vcvtFpSFixedSCode,
1546                                       "predicate_test": predicateTest,
1547                                       "op_class": "SimdFloatCvtOp" }, [])
1548    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSFixedSIop);
1549    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSFixedSIop);
1550    exec_output += PredOpExecute.subst(vcvtFpSFixedSIop);
1551
1552    vcvtFpSFixedDCode = vfpEnabledCheckCode + '''
1553        FPSCR fpscr = (FPSCR) FpscrExc;
1554        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1555        vfpFlushToZero(fpscr, cOp1);
1556        VfpSavedState state = prepFpState(fpscr.rMode);
1557        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1558        uint64_t mid = vfpFpToFixed<double>(cOp1, true, 32, imm);
1559        __asm__ __volatile__("" :: "m" (mid));
1560        finishVfp(fpscr, state, fpscr.fz);
1561        FpDestP0_uw = mid;
1562        FpDestP1_uw = mid >> 32;
1563        FpscrExc = fpscr;
1564    '''
1565    vcvtFpSFixedDIop = InstObjParams("vcvt", "VcvtFpSFixedD", "FpRegRegImmOp",
1566                                     { "code": vcvtFpSFixedDCode,
1567                                       "predicate_test": predicateTest,
1568                                       "op_class": "SimdFloatCvtOp" }, [])
1569    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSFixedDIop);
1570    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSFixedDIop);
1571    exec_output += PredOpExecute.subst(vcvtFpSFixedDIop);
1572
1573    vcvtFpUFixedSCode = vfpEnabledCheckCode + '''
1574        FPSCR fpscr = (FPSCR) FpscrExc;
1575        vfpFlushToZero(fpscr, FpOp1);
1576        VfpSavedState state = prepFpState(fpscr.rMode);
1577        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1578        FpDest_uw = vfpFpToFixed<float>(FpOp1, false, 32, imm);
1579        __asm__ __volatile__("" :: "m" (FpDest_uw));
1580        finishVfp(fpscr, state, fpscr.fz);
1581        FpscrExc = fpscr;
1582    '''
1583    vcvtFpUFixedSIop = InstObjParams("vcvt", "VcvtFpUFixedS", "FpRegRegImmOp",
1584                                     { "code": vcvtFpUFixedSCode,
1585                                       "predicate_test": predicateTest,
1586                                       "op_class": "SimdFloatCvtOp" }, [])
1587    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUFixedSIop);
1588    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUFixedSIop);
1589    exec_output += PredOpExecute.subst(vcvtFpUFixedSIop);
1590
1591    vcvtFpUFixedDCode = vfpEnabledCheckCode + '''
1592        FPSCR fpscr = (FPSCR) FpscrExc;
1593        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1594        vfpFlushToZero(fpscr, cOp1);
1595        VfpSavedState state = prepFpState(fpscr.rMode);
1596        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1597        uint64_t mid = vfpFpToFixed<double>(cOp1, false, 32, imm);
1598        __asm__ __volatile__("" :: "m" (mid));
1599        finishVfp(fpscr, state, fpscr.fz);
1600        FpDestP0_uw = mid;
1601        FpDestP1_uw = mid >> 32;
1602        FpscrExc = fpscr;
1603    '''
1604    vcvtFpUFixedDIop = InstObjParams("vcvt", "VcvtFpUFixedD", "FpRegRegImmOp",
1605                                     { "code": vcvtFpUFixedDCode,
1606                                       "predicate_test": predicateTest,
1607                                       "op_class": "SimdFloatCvtOp" }, [])
1608    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUFixedDIop);
1609    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUFixedDIop);
1610    exec_output += PredOpExecute.subst(vcvtFpUFixedDIop);
1611
1612    vcvtSFixedFpSCode = vfpEnabledCheckCode + '''
1613        FPSCR fpscr = (FPSCR) FpscrExc;
1614        VfpSavedState state = prepFpState(fpscr.rMode);
1615        __asm__ __volatile__("" : "=m" (FpOp1_sw) : "m" (FpOp1_sw));
1616        FpDest = vfpSFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_sw, 32, imm);
1617        __asm__ __volatile__("" :: "m" (FpDest));
1618        finishVfp(fpscr, state, fpscr.fz);
1619        FpscrExc = fpscr;
1620    '''
1621    vcvtSFixedFpSIop = InstObjParams("vcvt", "VcvtSFixedFpS", "FpRegRegImmOp",
1622                                     { "code": vcvtSFixedFpSCode,
1623                                       "predicate_test": predicateTest,
1624                                       "op_class": "SimdFloatCvtOp" }, [])
1625    header_output += FpRegRegImmOpDeclare.subst(vcvtSFixedFpSIop);
1626    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSFixedFpSIop);
1627    exec_output += PredOpExecute.subst(vcvtSFixedFpSIop);
1628
1629    vcvtSFixedFpDCode = vfpEnabledCheckCode + '''
1630        FPSCR fpscr = (FPSCR) FpscrExc;
1631        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
1632        VfpSavedState state = prepFpState(fpscr.rMode);
1633        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
1634        double cDest = vfpSFixedToFpD(fpscr.fz, fpscr.dn, mid, 32, imm);
1635        __asm__ __volatile__("" :: "m" (cDest));
1636        finishVfp(fpscr, state, fpscr.fz);
1637        FpDestP0_uw = dblLow(cDest);
1638        FpDestP1_uw = dblHi(cDest);
1639        FpscrExc = fpscr;
1640    '''
1641    vcvtSFixedFpDIop = InstObjParams("vcvt", "VcvtSFixedFpD", "FpRegRegImmOp",
1642                                     { "code": vcvtSFixedFpDCode,
1643                                       "predicate_test": predicateTest,
1644                                       "op_class": "SimdFloatCvtOp" }, [])
1645    header_output += FpRegRegImmOpDeclare.subst(vcvtSFixedFpDIop);
1646    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSFixedFpDIop);
1647    exec_output += PredOpExecute.subst(vcvtSFixedFpDIop);
1648
1649    vcvtUFixedFpSCode = vfpEnabledCheckCode + '''
1650        FPSCR fpscr = (FPSCR) FpscrExc;
1651        VfpSavedState state = prepFpState(fpscr.rMode);
1652        __asm__ __volatile__("" : "=m" (FpOp1_uw) : "m" (FpOp1_uw));
1653        FpDest = vfpUFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_uw, 32, imm);
1654        __asm__ __volatile__("" :: "m" (FpDest));
1655        finishVfp(fpscr, state, fpscr.fz);
1656        FpscrExc = fpscr;
1657    '''
1658    vcvtUFixedFpSIop = InstObjParams("vcvt", "VcvtUFixedFpS", "FpRegRegImmOp",
1659                                     { "code": vcvtUFixedFpSCode,
1660                                       "predicate_test": predicateTest,
1661                                       "op_class": "SimdFloatCvtOp" }, [])
1662    header_output += FpRegRegImmOpDeclare.subst(vcvtUFixedFpSIop);
1663    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUFixedFpSIop);
1664    exec_output += PredOpExecute.subst(vcvtUFixedFpSIop);
1665
1666    vcvtUFixedFpDCode = vfpEnabledCheckCode + '''
1667        FPSCR fpscr = (FPSCR) FpscrExc;
1668        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
1669        VfpSavedState state = prepFpState(fpscr.rMode);
1670        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
1671        double cDest = vfpUFixedToFpD(fpscr.fz, fpscr.dn, mid, 32, imm);
1672        __asm__ __volatile__("" :: "m" (cDest));
1673        finishVfp(fpscr, state, fpscr.fz);
1674        FpDestP0_uw = dblLow(cDest);
1675        FpDestP1_uw = dblHi(cDest);
1676        FpscrExc = fpscr;
1677    '''
1678    vcvtUFixedFpDIop = InstObjParams("vcvt", "VcvtUFixedFpD", "FpRegRegImmOp",
1679                                     { "code": vcvtUFixedFpDCode,
1680                                       "predicate_test": predicateTest,
1681                                       "op_class": "SimdFloatCvtOp" }, [])
1682    header_output += FpRegRegImmOpDeclare.subst(vcvtUFixedFpDIop);
1683    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUFixedFpDIop);
1684    exec_output += PredOpExecute.subst(vcvtUFixedFpDIop);
1685
1686    vcvtFpSHFixedSCode = vfpEnabledCheckCode + '''
1687        FPSCR fpscr = (FPSCR) FpscrExc;
1688        vfpFlushToZero(fpscr, FpOp1);
1689        VfpSavedState state = prepFpState(fpscr.rMode);
1690        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1691        FpDest_sh = vfpFpToFixed<float>(FpOp1, true, 16, imm);
1692        __asm__ __volatile__("" :: "m" (FpDest_sh));
1693        finishVfp(fpscr, state, fpscr.fz);
1694        FpscrExc = fpscr;
1695    '''
1696    vcvtFpSHFixedSIop = InstObjParams("vcvt", "VcvtFpSHFixedS",
1697                                      "FpRegRegImmOp",
1698                                     { "code": vcvtFpSHFixedSCode,
1699                                       "predicate_test": predicateTest,
1700                                       "op_class": "SimdFloatCvtOp" }, [])
1701    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSHFixedSIop);
1702    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSHFixedSIop);
1703    exec_output += PredOpExecute.subst(vcvtFpSHFixedSIop);
1704
1705    vcvtFpSHFixedDCode = vfpEnabledCheckCode + '''
1706        FPSCR fpscr = (FPSCR) FpscrExc;
1707        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1708        vfpFlushToZero(fpscr, cOp1);
1709        VfpSavedState state = prepFpState(fpscr.rMode);
1710        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1711        uint64_t result = vfpFpToFixed<double>(cOp1, true, 16, imm);
1712        __asm__ __volatile__("" :: "m" (result));
1713        finishVfp(fpscr, state, fpscr.fz);
1714        FpDestP0_uw = result;
1715        FpDestP1_uw = result >> 32;
1716        FpscrExc = fpscr;
1717    '''
1718    vcvtFpSHFixedDIop = InstObjParams("vcvt", "VcvtFpSHFixedD",
1719                                      "FpRegRegImmOp",
1720                                     { "code": vcvtFpSHFixedDCode,
1721                                       "predicate_test": predicateTest,
1722                                       "op_class": "SimdFloatCvtOp" }, [])
1723    header_output += FpRegRegImmOpDeclare.subst(vcvtFpSHFixedDIop);
1724    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSHFixedDIop);
1725    exec_output += PredOpExecute.subst(vcvtFpSHFixedDIop);
1726
1727    vcvtFpUHFixedSCode = vfpEnabledCheckCode + '''
1728        FPSCR fpscr = (FPSCR) FpscrExc;
1729        vfpFlushToZero(fpscr, FpOp1);
1730        VfpSavedState state = prepFpState(fpscr.rMode);
1731        __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1));
1732        FpDest_uh = vfpFpToFixed<float>(FpOp1, false, 16, imm);
1733        __asm__ __volatile__("" :: "m" (FpDest_uh));
1734        finishVfp(fpscr, state, fpscr.fz);
1735        FpscrExc = fpscr;
1736    '''
1737    vcvtFpUHFixedSIop = InstObjParams("vcvt", "VcvtFpUHFixedS",
1738                                      "FpRegRegImmOp",
1739                                     { "code": vcvtFpUHFixedSCode,
1740                                       "predicate_test": predicateTest,
1741                                       "op_class": "SimdFloatCvtOp" }, [])
1742    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUHFixedSIop);
1743    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUHFixedSIop);
1744    exec_output += PredOpExecute.subst(vcvtFpUHFixedSIop);
1745
1746    vcvtFpUHFixedDCode = vfpEnabledCheckCode + '''
1747        FPSCR fpscr = (FPSCR) FpscrExc;
1748        double cOp1 = dbl(FpOp1P0_uw, FpOp1P1_uw);
1749        vfpFlushToZero(fpscr, cOp1);
1750        VfpSavedState state = prepFpState(fpscr.rMode);
1751        __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1));
1752        uint64_t mid = vfpFpToFixed<double>(cOp1, false, 16, imm);
1753        __asm__ __volatile__("" :: "m" (mid));
1754        finishVfp(fpscr, state, fpscr.fz);
1755        FpDestP0_uw = mid;
1756        FpDestP1_uw = mid >> 32;
1757        FpscrExc = fpscr;
1758    '''
1759    vcvtFpUHFixedDIop = InstObjParams("vcvt", "VcvtFpUHFixedD",
1760                                      "FpRegRegImmOp",
1761                                     { "code": vcvtFpUHFixedDCode,
1762                                       "predicate_test": predicateTest,
1763                                       "op_class": "SimdFloatCvtOp" }, [])
1764    header_output += FpRegRegImmOpDeclare.subst(vcvtFpUHFixedDIop);
1765    decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUHFixedDIop);
1766    exec_output += PredOpExecute.subst(vcvtFpUHFixedDIop);
1767
1768    vcvtSHFixedFpSCode = vfpEnabledCheckCode + '''
1769        FPSCR fpscr = (FPSCR) FpscrExc;
1770        VfpSavedState state = prepFpState(fpscr.rMode);
1771        __asm__ __volatile__("" : "=m" (FpOp1_sh) : "m" (FpOp1_sh));
1772        FpDest = vfpSFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_sh, 16, imm);
1773        __asm__ __volatile__("" :: "m" (FpDest));
1774        finishVfp(fpscr, state, fpscr.fz);
1775        FpscrExc = fpscr;
1776    '''
1777    vcvtSHFixedFpSIop = InstObjParams("vcvt", "VcvtSHFixedFpS",
1778                                      "FpRegRegImmOp",
1779                                     { "code": vcvtSHFixedFpSCode,
1780                                       "predicate_test": predicateTest,
1781                                       "op_class": "SimdFloatCvtOp" }, [])
1782    header_output += FpRegRegImmOpDeclare.subst(vcvtSHFixedFpSIop);
1783    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSHFixedFpSIop);
1784    exec_output += PredOpExecute.subst(vcvtSHFixedFpSIop);
1785
1786    vcvtSHFixedFpDCode = vfpEnabledCheckCode + '''
1787        FPSCR fpscr = (FPSCR) FpscrExc;
1788        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
1789        VfpSavedState state = prepFpState(fpscr.rMode);
1790        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
1791        double cDest = vfpSFixedToFpD(fpscr.fz, fpscr.dn, mid, 16, imm);
1792        __asm__ __volatile__("" :: "m" (cDest));
1793        finishVfp(fpscr, state, fpscr.fz);
1794        FpDestP0_uw = dblLow(cDest);
1795        FpDestP1_uw = dblHi(cDest);
1796        FpscrExc = fpscr;
1797    '''
1798    vcvtSHFixedFpDIop = InstObjParams("vcvt", "VcvtSHFixedFpD",
1799                                      "FpRegRegImmOp",
1800                                     { "code": vcvtSHFixedFpDCode,
1801                                       "predicate_test": predicateTest,
1802                                       "op_class": "SimdFloatCvtOp" }, [])
1803    header_output += FpRegRegImmOpDeclare.subst(vcvtSHFixedFpDIop);
1804    decoder_output += FpRegRegImmOpConstructor.subst(vcvtSHFixedFpDIop);
1805    exec_output += PredOpExecute.subst(vcvtSHFixedFpDIop);
1806
1807    vcvtUHFixedFpSCode = vfpEnabledCheckCode + '''
1808        FPSCR fpscr = (FPSCR) FpscrExc;
1809        VfpSavedState state = prepFpState(fpscr.rMode);
1810        __asm__ __volatile__("" : "=m" (FpOp1_uh) : "m" (FpOp1_uh));
1811        FpDest = vfpUFixedToFpS(fpscr.fz, fpscr.dn, FpOp1_uh, 16, imm);
1812        __asm__ __volatile__("" :: "m" (FpDest));
1813        finishVfp(fpscr, state, fpscr.fz);
1814        FpscrExc = fpscr;
1815    '''
1816    vcvtUHFixedFpSIop = InstObjParams("vcvt", "VcvtUHFixedFpS",
1817                                      "FpRegRegImmOp",
1818                                     { "code": vcvtUHFixedFpSCode,
1819                                       "predicate_test": predicateTest,
1820                                       "op_class": "SimdFloatCvtOp" }, [])
1821    header_output += FpRegRegImmOpDeclare.subst(vcvtUHFixedFpSIop);
1822    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUHFixedFpSIop);
1823    exec_output += PredOpExecute.subst(vcvtUHFixedFpSIop);
1824
1825    vcvtUHFixedFpDCode = vfpEnabledCheckCode + '''
1826        FPSCR fpscr = (FPSCR) FpscrExc;
1827        uint64_t mid = ((uint64_t)FpOp1P0_uw | ((uint64_t)FpOp1P1_uw << 32));
1828        VfpSavedState state = prepFpState(fpscr.rMode);
1829        __asm__ __volatile__("" : "=m" (mid) : "m" (mid));
1830        double cDest = vfpUFixedToFpD(fpscr.fz, fpscr.dn, mid, 16, imm);
1831        __asm__ __volatile__("" :: "m" (cDest));
1832        finishVfp(fpscr, state, fpscr.fz);
1833        FpDestP0_uw = dblLow(cDest);
1834        FpDestP1_uw = dblHi(cDest);
1835        FpscrExc = fpscr;
1836    '''
1837    vcvtUHFixedFpDIop = InstObjParams("vcvt", "VcvtUHFixedFpD",
1838                                      "FpRegRegImmOp",
1839                                     { "code": vcvtUHFixedFpDCode,
1840                                       "predicate_test": predicateTest,
1841                                       "op_class": "SimdFloatCvtOp" }, [])
1842    header_output += FpRegRegImmOpDeclare.subst(vcvtUHFixedFpDIop);
1843    decoder_output += FpRegRegImmOpConstructor.subst(vcvtUHFixedFpDIop);
1844    exec_output += PredOpExecute.subst(vcvtUHFixedFpDIop);
1845}};
1846