fp.isa revision 7371
17202Sgblack@eecs.umich.edu// -*- mode:c++ -*-
27202Sgblack@eecs.umich.edu
37202Sgblack@eecs.umich.edu// Copyright (c) 2010 ARM Limited
47202Sgblack@eecs.umich.edu// All rights reserved
57202Sgblack@eecs.umich.edu//
67202Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall
77202Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual
87202Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating
97202Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software
107202Sgblack@eecs.umich.edu// licensed hereunder.  You may use the software subject to the license
117202Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated
127202Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software,
137202Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form.
147202Sgblack@eecs.umich.edu//
157202Sgblack@eecs.umich.edu// Copyright (c) 2007-2008 The Florida State University
167202Sgblack@eecs.umich.edu// All rights reserved.
177202Sgblack@eecs.umich.edu//
187202Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
197202Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
207202Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
217202Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
227202Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
237202Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
247202Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
257202Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
267202Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
277202Sgblack@eecs.umich.edu// this software without specific prior written permission.
287202Sgblack@eecs.umich.edu//
297202Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
307202Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
317202Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
327202Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
337202Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
347202Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
357202Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
367202Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
377202Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
387202Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
397202Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
407202Sgblack@eecs.umich.edu//
417202Sgblack@eecs.umich.edu// Authors: Stephen Hines
427202Sgblack@eecs.umich.edu
437202Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////
447202Sgblack@eecs.umich.edu//
457202Sgblack@eecs.umich.edu// Floating Point operate instructions
467202Sgblack@eecs.umich.edu//
477202Sgblack@eecs.umich.edu
487202Sgblack@eecs.umich.edudef template FPAExecute {{
497202Sgblack@eecs.umich.edu        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
507202Sgblack@eecs.umich.edu        {
517202Sgblack@eecs.umich.edu                Fault fault = NoFault;
527202Sgblack@eecs.umich.edu
537202Sgblack@eecs.umich.edu                %(fp_enable_check)s;
547202Sgblack@eecs.umich.edu
557202Sgblack@eecs.umich.edu                %(op_decl)s;
567202Sgblack@eecs.umich.edu                %(op_rd)s;
577202Sgblack@eecs.umich.edu
587202Sgblack@eecs.umich.edu                if (%(predicate_test)s) {
597202Sgblack@eecs.umich.edu                    %(code)s;
607202Sgblack@eecs.umich.edu                    if (fault == NoFault) {
617202Sgblack@eecs.umich.edu                        %(op_wb)s;
627202Sgblack@eecs.umich.edu                    }
637202Sgblack@eecs.umich.edu                }
647202Sgblack@eecs.umich.edu
657202Sgblack@eecs.umich.edu                return fault;
667202Sgblack@eecs.umich.edu        }
677202Sgblack@eecs.umich.edu}};
687202Sgblack@eecs.umich.edu
697202Sgblack@eecs.umich.edudef template FloatDoubleDecode {{
707202Sgblack@eecs.umich.edu    {
717202Sgblack@eecs.umich.edu        ArmStaticInst *i = NULL;
727202Sgblack@eecs.umich.edu        switch (OPCODE_19 << 1 | OPCODE_7)
737202Sgblack@eecs.umich.edu        {
747202Sgblack@eecs.umich.edu            case 0:
757202Sgblack@eecs.umich.edu                i = (ArmStaticInst *)new %(class_name)sS(machInst);
767202Sgblack@eecs.umich.edu                break;
777202Sgblack@eecs.umich.edu            case 1:
787202Sgblack@eecs.umich.edu                i = (ArmStaticInst *)new %(class_name)sD(machInst);
797202Sgblack@eecs.umich.edu                break;
807202Sgblack@eecs.umich.edu            case 2:
817202Sgblack@eecs.umich.edu            case 3:
827202Sgblack@eecs.umich.edu            default:
837202Sgblack@eecs.umich.edu                panic("Cannot decode float/double nature of the instruction");
847202Sgblack@eecs.umich.edu        }
857202Sgblack@eecs.umich.edu        return i;
867202Sgblack@eecs.umich.edu    }
877202Sgblack@eecs.umich.edu}};
887202Sgblack@eecs.umich.edu
897202Sgblack@eecs.umich.edu// Primary format for float point operate instructions:
907202Sgblack@eecs.umich.edudef format FloatOp(code, *flags) {{
917202Sgblack@eecs.umich.edu        orig_code = code
927202Sgblack@eecs.umich.edu
937202Sgblack@eecs.umich.edu        cblk = code
947202Sgblack@eecs.umich.edu        iop = InstObjParams(name, Name, 'PredOp',
957202Sgblack@eecs.umich.edu                            {"code": cblk,
967202Sgblack@eecs.umich.edu                             "predicate_test": predicateTest},
977202Sgblack@eecs.umich.edu                            flags)
987202Sgblack@eecs.umich.edu        header_output = BasicDeclare.subst(iop)
997202Sgblack@eecs.umich.edu        decoder_output = BasicConstructor.subst(iop)
1007202Sgblack@eecs.umich.edu        exec_output = FPAExecute.subst(iop)
1017208Sgblack@eecs.umich.edu
1027208Sgblack@eecs.umich.edu        sng_cblk = code
1037208Sgblack@eecs.umich.edu        sng_iop = InstObjParams(name, Name+'S', 'PredOp',
1047208Sgblack@eecs.umich.edu                                {"code": sng_cblk,
1057208Sgblack@eecs.umich.edu                                 "predicate_test": predicateTest},
1067208Sgblack@eecs.umich.edu                                flags)
1077208Sgblack@eecs.umich.edu        header_output += BasicDeclare.subst(sng_iop)
1087208Sgblack@eecs.umich.edu        decoder_output += BasicConstructor.subst(sng_iop)
1097208Sgblack@eecs.umich.edu        exec_output += FPAExecute.subst(sng_iop)
1107208Sgblack@eecs.umich.edu
1117208Sgblack@eecs.umich.edu        dbl_code = re.sub(r'\.sf', '.df', orig_code)
1127208Sgblack@eecs.umich.edu
1137208Sgblack@eecs.umich.edu        dbl_cblk = dbl_code
1147208Sgblack@eecs.umich.edu        dbl_iop = InstObjParams(name, Name+'D', 'PredOp',
1157208Sgblack@eecs.umich.edu                                {"code": dbl_cblk,
1167208Sgblack@eecs.umich.edu                                 "predicate_test": predicateTest},
1177208Sgblack@eecs.umich.edu                                flags)
1187208Sgblack@eecs.umich.edu        header_output += BasicDeclare.subst(dbl_iop)
1197208Sgblack@eecs.umich.edu        decoder_output += BasicConstructor.subst(dbl_iop)
1207208Sgblack@eecs.umich.edu        exec_output += FPAExecute.subst(dbl_iop)
1217208Sgblack@eecs.umich.edu
1227225Sgblack@eecs.umich.edu        decode_block = FloatDoubleDecode.subst(iop)
1237233Sgblack@eecs.umich.edu}};
1247233Sgblack@eecs.umich.edu
1257233Sgblack@eecs.umich.edulet {{
1267233Sgblack@eecs.umich.edu        calcFPCcCode = '''
1277233Sgblack@eecs.umich.edu        uint16_t _in, _iz, _ic, _iv;
1287233Sgblack@eecs.umich.edu
1297233Sgblack@eecs.umich.edu        _in = %(fReg1)s < %(fReg2)s;
1307233Sgblack@eecs.umich.edu        _iz = %(fReg1)s == %(fReg2)s;
1317233Sgblack@eecs.umich.edu        _ic = %(fReg1)s >= %(fReg2)s;
1327233Sgblack@eecs.umich.edu        _iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1;
1337233Sgblack@eecs.umich.edu
1347233Sgblack@eecs.umich.edu        CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
1357233Sgblack@eecs.umich.edu            (CondCodes & 0x0FFFFFFF);
1367233Sgblack@eecs.umich.edu        '''
1377233Sgblack@eecs.umich.edu}};
1387233Sgblack@eecs.umich.edu
1397233Sgblack@eecs.umich.edudef format FloatCmp(fReg1, fReg2, *flags) {{
1407233Sgblack@eecs.umich.edu        code = calcFPCcCode % vars()
1417233Sgblack@eecs.umich.edu        iop = InstObjParams(name, Name, 'PredOp',
1427233Sgblack@eecs.umich.edu                            {"code": code,
1437233Sgblack@eecs.umich.edu                             "predicate_test": predicateTest},
1447233Sgblack@eecs.umich.edu                             flags)
1457233Sgblack@eecs.umich.edu        header_output = BasicDeclare.subst(iop)
1467233Sgblack@eecs.umich.edu        decoder_output = BasicConstructor.subst(iop)
1477233Sgblack@eecs.umich.edu        decode_block = BasicDecode.subst(iop)
1487233Sgblack@eecs.umich.edu        exec_output = FPAExecute.subst(iop)
1497241Sgblack@eecs.umich.edu}};
1507241Sgblack@eecs.umich.edu
1517241Sgblack@eecs.umich.edulet {{
1527241Sgblack@eecs.umich.edu    header_output = '''
1537241Sgblack@eecs.umich.edu    StaticInstPtr
1547241Sgblack@eecs.umich.edu    decodeExtensionRegLoadStore(ExtMachInst machInst);
1557241Sgblack@eecs.umich.edu    '''
1567241Sgblack@eecs.umich.edu    decoder_output = '''
1577241Sgblack@eecs.umich.edu    StaticInstPtr
1587241Sgblack@eecs.umich.edu    decodeExtensionRegLoadStore(ExtMachInst machInst)
1597241Sgblack@eecs.umich.edu    {
1607241Sgblack@eecs.umich.edu        const uint32_t opcode = bits(machInst, 24, 20);
1617241Sgblack@eecs.umich.edu        const uint32_t offset = bits(machInst, 7, 0);
1627241Sgblack@eecs.umich.edu        const bool single = (bits(machInst, 8) == 0);
1637241Sgblack@eecs.umich.edu        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1647241Sgblack@eecs.umich.edu        RegIndex vd;
1657241Sgblack@eecs.umich.edu        if (single) {
1667241Sgblack@eecs.umich.edu            vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
1677241Sgblack@eecs.umich.edu                                      bits(machInst, 22));
1687241Sgblack@eecs.umich.edu        } else {
1697241Sgblack@eecs.umich.edu            vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
1707241Sgblack@eecs.umich.edu                                      (bits(machInst, 22) << 5));
1717241Sgblack@eecs.umich.edu        }
1727241Sgblack@eecs.umich.edu        switch (bits(opcode, 4, 3)) {
1737241Sgblack@eecs.umich.edu          case 0x0:
1747241Sgblack@eecs.umich.edu            if (bits(opcode, 4, 1) == 0x2 &&
1757238Sgblack@eecs.umich.edu                    !(machInst.thumb == 1 && bits(machInst, 28) == 1) &&
1767238Sgblack@eecs.umich.edu                    !(machInst.thumb == 0 && machInst.condCode == 0xf)) {
1777238Sgblack@eecs.umich.edu                if ((bits(machInst, 7, 4) & 0xd) != 1) {
1787238Sgblack@eecs.umich.edu                    break;
1797238Sgblack@eecs.umich.edu                }
1807238Sgblack@eecs.umich.edu                const IntRegIndex rt =
1817238Sgblack@eecs.umich.edu                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
1827238Sgblack@eecs.umich.edu                const IntRegIndex rt2 =
1837238Sgblack@eecs.umich.edu                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1847238Sgblack@eecs.umich.edu                const bool op = bits(machInst, 20);
1857238Sgblack@eecs.umich.edu                uint32_t vm;
1867238Sgblack@eecs.umich.edu                if (single) {
1877238Sgblack@eecs.umich.edu                    vm = (bits(machInst, 3, 0) << 1) | bits(machInst, 5);
1887238Sgblack@eecs.umich.edu                } else {
1897238Sgblack@eecs.umich.edu                    vm = (bits(machInst, 3, 0) << 1) |
1907238Sgblack@eecs.umich.edu                         (bits(machInst, 5) << 5);
1917238Sgblack@eecs.umich.edu                }
1927238Sgblack@eecs.umich.edu                if (op) {
1937238Sgblack@eecs.umich.edu                    return new Vmov2Core2Reg(machInst, rt, rt2,
1947238Sgblack@eecs.umich.edu                                             (IntRegIndex)vm);
1957238Sgblack@eecs.umich.edu                } else {
1967238Sgblack@eecs.umich.edu                    return new Vmov2Reg2Core(machInst, (IntRegIndex)vm,
1977238Sgblack@eecs.umich.edu                                             rt, rt2);
1987238Sgblack@eecs.umich.edu                }
1997253Sgblack@eecs.umich.edu            }
2007253Sgblack@eecs.umich.edu            break;
2017253Sgblack@eecs.umich.edu          case 0x1:
2027253Sgblack@eecs.umich.edu            switch (bits(opcode, 1, 0)) {
2037253Sgblack@eecs.umich.edu              case 0x0:
2047253Sgblack@eecs.umich.edu                return new VLdmStm(machInst, rn, vd, single,
2057253Sgblack@eecs.umich.edu                                   true, false, false, offset);
2067253Sgblack@eecs.umich.edu              case 0x1:
2077253Sgblack@eecs.umich.edu                return new VLdmStm(machInst, rn, vd, single,
2087253Sgblack@eecs.umich.edu                                   true, false, true, offset);
2097253Sgblack@eecs.umich.edu              case 0x2:
2107253Sgblack@eecs.umich.edu                return new VLdmStm(machInst, rn, vd, single,
2117253Sgblack@eecs.umich.edu                                   true, true, false, offset);
2127253Sgblack@eecs.umich.edu              case 0x3:
2137253Sgblack@eecs.umich.edu                // If rn == sp, then this is called vpop.
2147253Sgblack@eecs.umich.edu                return new VLdmStm(machInst, rn, vd, single,
2157253Sgblack@eecs.umich.edu                                   true, true, true, offset);
2167253Sgblack@eecs.umich.edu            }
2177253Sgblack@eecs.umich.edu          case 0x2:
2187253Sgblack@eecs.umich.edu            if (bits(opcode, 1, 0) == 0x2) {
2197253Sgblack@eecs.umich.edu                // If rn == sp, then this is called vpush.
2207253Sgblack@eecs.umich.edu                return new VLdmStm(machInst, rn, vd, single,
2217253Sgblack@eecs.umich.edu                                   false, true, false, offset);
2227253Sgblack@eecs.umich.edu            } else if (bits(opcode, 1, 0) == 0x3) {
2237253Sgblack@eecs.umich.edu                return new VLdmStm(machInst, rn, vd, single,
2247253Sgblack@eecs.umich.edu                                   false, true, true, offset);
2257232Sgblack@eecs.umich.edu            }
2267225Sgblack@eecs.umich.edu            // Fall through on purpose
2277225Sgblack@eecs.umich.edu          case 0x3:
2287225Sgblack@eecs.umich.edu            const bool up = (bits(machInst, 23) == 1);
2297225Sgblack@eecs.umich.edu            const uint32_t imm = bits(machInst, 7, 0) << 2;
2307225Sgblack@eecs.umich.edu            RegIndex vd;
2317225Sgblack@eecs.umich.edu            if (single) {
2327232Sgblack@eecs.umich.edu                vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
2337225Sgblack@eecs.umich.edu                                          (bits(machInst, 22)));
2347225Sgblack@eecs.umich.edu            } else {
2357225Sgblack@eecs.umich.edu                vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
2367225Sgblack@eecs.umich.edu                                          (bits(machInst, 22) << 5));
2377232Sgblack@eecs.umich.edu            }
2387225Sgblack@eecs.umich.edu            if (bits(opcode, 1, 0) == 0x0) {
2397225Sgblack@eecs.umich.edu                if (single) {
2407232Sgblack@eecs.umich.edu                    if (up) {
2417225Sgblack@eecs.umich.edu                        return new %(vstr_us)s(machInst, vd, rn, up, imm);
2427225Sgblack@eecs.umich.edu                    } else {
2437232Sgblack@eecs.umich.edu                        return new %(vstr_s)s(machInst, vd, rn, up, imm);
2447225Sgblack@eecs.umich.edu                    }
2457225Sgblack@eecs.umich.edu                } else {
2467225Sgblack@eecs.umich.edu                    if (up) {
2477225Sgblack@eecs.umich.edu                        return new %(vstr_ud)s(machInst, vd, vd + 1,
2487225Sgblack@eecs.umich.edu                                               rn, up, imm);
2497232Sgblack@eecs.umich.edu                    } else {
2507225Sgblack@eecs.umich.edu                        return new %(vstr_d)s(machInst, vd, vd + 1,
2517225Sgblack@eecs.umich.edu                                              rn, up, imm);
2527225Sgblack@eecs.umich.edu                    }
2537225Sgblack@eecs.umich.edu                }
2547225Sgblack@eecs.umich.edu            } else if (bits(opcode, 1, 0) == 0x1) {
2557225Sgblack@eecs.umich.edu                if (single) {
2567232Sgblack@eecs.umich.edu                    if (up) {
2577225Sgblack@eecs.umich.edu                        return new %(vldr_us)s(machInst, vd, rn, up, imm);
2587225Sgblack@eecs.umich.edu                    } else {
2597225Sgblack@eecs.umich.edu                        return new %(vldr_s)s(machInst, vd, rn, up, imm);
2607225Sgblack@eecs.umich.edu                    }
2617225Sgblack@eecs.umich.edu                } else {
2627232Sgblack@eecs.umich.edu                    if (up) {
2637225Sgblack@eecs.umich.edu                        return new %(vldr_ud)s(machInst, vd, vd + 1,
2647225Sgblack@eecs.umich.edu                                               rn, up, imm);
2657232Sgblack@eecs.umich.edu                    } else {
2667225Sgblack@eecs.umich.edu                        return new %(vldr_d)s(machInst, vd, vd + 1,
2677225Sgblack@eecs.umich.edu                                              rn, up, imm);
2687225Sgblack@eecs.umich.edu                    }
2697225Sgblack@eecs.umich.edu                }
2707232Sgblack@eecs.umich.edu            }
2717225Sgblack@eecs.umich.edu        }
2727225Sgblack@eecs.umich.edu        return new Unknown(machInst);
2737225Sgblack@eecs.umich.edu    }
2747225Sgblack@eecs.umich.edu    ''' % {
275        "vldr_us" : "VLDR_" + loadImmClassName(False, True, False),
276        "vldr_s" : "VLDR_" + loadImmClassName(False, False, False),
277        "vldr_ud" : "VLDR_" + loadDoubleImmClassName(False, True, False),
278        "vldr_d" : "VLDR_" + loadDoubleImmClassName(False, False, False),
279        "vstr_us" : "VSTR_" + storeImmClassName(False, True, False),
280        "vstr_s" : "VSTR_" + storeImmClassName(False, False, False),
281        "vstr_ud" : "VSTR_" + storeDoubleImmClassName(False, True, False),
282        "vstr_d" : "VSTR_" + storeDoubleImmClassName(False, False, False)
283    }
284}};
285
286def format ExtensionRegLoadStore() {{
287    decode_block = '''
288    return decodeExtensionRegLoadStore(machInst);
289    '''
290}};
291
292let {{
293    header_output = '''
294    StaticInstPtr
295    decodeShortFpTransfer(ExtMachInst machInst);
296    '''
297    decoder_output = '''
298    StaticInstPtr
299    decodeShortFpTransfer(ExtMachInst machInst)
300    {
301        const uint32_t l = bits(machInst, 20);
302        const uint32_t c = bits(machInst, 8);
303        const uint32_t a = bits(machInst, 23, 21);
304        const uint32_t b = bits(machInst, 6, 5);
305        if ((machInst.thumb == 1 && bits(machInst, 28) == 1) ||
306            (machInst.thumb == 0 && machInst.condCode == 0xf)) {
307            return new Unknown(machInst);
308        }
309        if (l == 0 && c == 0) {
310            if (a == 0) {
311                const uint32_t vn = (bits(machInst, 19, 16) << 1) |
312                                    bits(machInst, 7);
313                const IntRegIndex rt =
314                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
315                if (bits(machInst, 20) == 1) {
316                    return new VmovRegCoreW(machInst, rt, (IntRegIndex)vn);
317                } else {
318                    return new VmovCoreRegW(machInst, (IntRegIndex)vn, rt);
319                }
320            } else if (a == 0x7) {
321                const IntRegIndex rt =
322                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
323                uint32_t specReg = bits(machInst, 19, 16);
324                switch (specReg) {
325                  case 0:
326                    specReg = MISCREG_FPSID;
327                    break;
328                  case 1:
329                    specReg = MISCREG_FPSCR;
330                    break;
331                  case 8:
332                    specReg = MISCREG_FPEXC;
333                    break;
334                  default:
335                    return new Unknown(machInst);
336                }
337                return new Vmsr(machInst, (IntRegIndex)specReg, rt);
338            }
339        } else if (l == 0 && c == 1) {
340            if (bits(a, 2) == 0) {
341                uint32_t vd = (bits(machInst, 7) << 5) |
342                              (bits(machInst, 19, 16) << 1);
343                uint32_t index, size;
344                const IntRegIndex rt =
345                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
346                if (bits(machInst, 22) == 1) {
347                    size = 8;
348                    index = (bits(machInst, 21) << 2) |
349                            bits(machInst, 6, 5);
350                } else if (bits(machInst, 5) == 1) {
351                    size = 16;
352                    index = (bits(machInst, 21) << 1) |
353                            bits(machInst, 6);
354                } else if (bits(machInst, 6) == 0) {
355                    size = 32;
356                    index = bits(machInst, 21);
357                } else {
358                    return new Unknown(machInst);
359                }
360                if (index >= (32 / size)) {
361                    index -= (32 / size);
362                    vd++;
363                }
364                switch (size) {
365                  case 8:
366                    return new VmovCoreRegB(machInst, (IntRegIndex)vd,
367                                            rt, index);
368                  case 16:
369                    return new VmovCoreRegH(machInst, (IntRegIndex)vd,
370                                            rt, index);
371                  case 32:
372                    return new VmovCoreRegW(machInst, (IntRegIndex)vd, rt);
373                }
374            } else if (bits(b, 1) == 0) {
375                // A8-594
376                return new WarnUnimplemented("vdup", machInst);
377            }
378        } else if (l == 1 && c == 0) {
379            if (a == 0) {
380                const uint32_t vn = (bits(machInst, 19, 16) << 1) |
381                                    bits(machInst, 7);
382                const IntRegIndex rt =
383                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
384                if (bits(machInst, 20) == 1) {
385                    return new VmovRegCoreW(machInst, rt, (IntRegIndex)vn);
386                } else {
387                    return new VmovCoreRegW(machInst, (IntRegIndex)vn, rt);
388                }
389            } else if (a == 7) {
390                const IntRegIndex rt =
391                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
392                uint32_t specReg = bits(machInst, 19, 16);
393                switch (specReg) {
394                  case 0:
395                    specReg = MISCREG_FPSID;
396                    break;
397                  case 1:
398                    specReg = MISCREG_FPSCR;
399                    break;
400                  case 6:
401                    specReg = MISCREG_MVFR1;
402                    break;
403                  case 7:
404                    specReg = MISCREG_MVFR0;
405                    break;
406                  case 8:
407                    specReg = MISCREG_FPEXC;
408                    break;
409                  default:
410                    return new Unknown(machInst);
411                }
412                return new Vmrs(machInst, rt, (IntRegIndex)specReg);
413            }
414        } else {
415            uint32_t vd = (bits(machInst, 7) << 5) |
416                          (bits(machInst, 19, 16) << 1);
417            uint32_t index, size;
418            const IntRegIndex rt =
419                (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
420            const bool u = (bits(machInst, 23) == 1);
421            if (bits(machInst, 22) == 1) {
422                size = 8;
423                index = (bits(machInst, 21) << 2) |
424                        bits(machInst, 6, 5);
425            } else if (bits(machInst, 5) == 1) {
426                size = 16;
427                index = (bits(machInst, 21) << 1) |
428                        bits(machInst, 6);
429            } else if (bits(machInst, 6) == 0 && !u) {
430                size = 32;
431                index = bits(machInst, 21);
432            } else {
433                return new Unknown(machInst);
434            }
435            if (index >= (32 / size)) {
436                index -= (32 / size);
437                vd++;
438            }
439            switch (size) {
440              case 8:
441                if (u) {
442                    return new VmovRegCoreUB(machInst, rt,
443                                             (IntRegIndex)vd, index);
444                } else {
445                    return new VmovRegCoreSB(machInst, rt,
446                                             (IntRegIndex)vd, index);
447                }
448              case 16:
449                if (u) {
450                    return new VmovRegCoreUH(machInst, rt,
451                                             (IntRegIndex)vd, index);
452                } else {
453                    return new VmovRegCoreSH(machInst, rt,
454                                             (IntRegIndex)vd, index);
455                }
456              case 32:
457                return new VmovRegCoreW(machInst, rt, (IntRegIndex)vd);
458            }
459        }
460        return new Unknown(machInst);
461    }
462    '''
463}};
464
465def format ShortFpTransfer() {{
466    decode_block = '''
467    return decodeShortFpTransfer(machInst);
468    '''
469}};
470
471let {{
472    header_output = '''
473    StaticInstPtr
474    decodeVfpData(ExtMachInst machInst);
475    '''
476    decoder_output = '''
477    StaticInstPtr
478    decodeVfpData(ExtMachInst machInst)
479    {
480        const uint32_t opc1 = bits(machInst, 23, 20);
481        const uint32_t opc2 = bits(machInst, 19, 16);
482        const uint32_t opc3 = bits(machInst, 7, 6);
483        //const uint32_t opc4 = bits(machInst, 3, 0);
484        switch (opc1 & 0xb /* 1011 */) {
485          case 0x0:
486            if (bits(machInst, 6) == 0) {
487                uint32_t vd;
488                uint32_t vm;
489                uint32_t vn;
490                if (bits(machInst, 8) == 0) {
491                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
492                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
493                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
494                    return new VmlaS(machInst, (IntRegIndex)vd,
495                            (IntRegIndex)vn, (IntRegIndex)vm);
496                } else {
497                    vd = (bits(machInst, 22) << 5) |
498                         (bits(machInst, 15, 12) << 1);
499                    vm = (bits(machInst, 5) << 5) |
500                         (bits(machInst, 3, 0) << 1);
501                    vn = (bits(machInst, 7) << 5) |
502                         (bits(machInst, 19, 16) << 1);
503                    return new VmlaD(machInst, (IntRegIndex)vd,
504                            (IntRegIndex)vn, (IntRegIndex)vm);
505                }
506            } else {
507                uint32_t vd;
508                uint32_t vm;
509                uint32_t vn;
510                if (bits(machInst, 8) == 0) {
511                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
512                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
513                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
514                    return new VmlsS(machInst, (IntRegIndex)vd,
515                            (IntRegIndex)vn, (IntRegIndex)vm);
516                } else {
517                    vd = (bits(machInst, 22) << 5) |
518                         (bits(machInst, 15, 12) << 1);
519                    vm = (bits(machInst, 5) << 5) |
520                         (bits(machInst, 3, 0) << 1);
521                    vn = (bits(machInst, 7) << 5) |
522                         (bits(machInst, 19, 16) << 1);
523                    return new VmlsD(machInst, (IntRegIndex)vd,
524                            (IntRegIndex)vn, (IntRegIndex)vm);
525                }
526            }
527          case 0x1:
528            if (bits(machInst, 6) == 1) {
529                uint32_t vd;
530                uint32_t vm;
531                uint32_t vn;
532                if (bits(machInst, 8) == 0) {
533                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
534                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
535                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
536                    return new VnmlaS(machInst, (IntRegIndex)vd,
537                            (IntRegIndex)vn, (IntRegIndex)vm);
538                } else {
539                    vd = (bits(machInst, 22) << 5) |
540                         (bits(machInst, 15, 12) << 1);
541                    vm = (bits(machInst, 5) << 5) |
542                         (bits(machInst, 3, 0) << 1);
543                    vn = (bits(machInst, 7) << 5) |
544                         (bits(machInst, 19, 16) << 1);
545                    return new VnmlaD(machInst, (IntRegIndex)vd,
546                            (IntRegIndex)vn, (IntRegIndex)vm);
547                }
548            } else {
549                uint32_t vd;
550                uint32_t vm;
551                uint32_t vn;
552                if (bits(machInst, 8) == 0) {
553                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
554                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
555                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
556                    return new VnmlsS(machInst, (IntRegIndex)vd,
557                            (IntRegIndex)vn, (IntRegIndex)vm);
558                } else {
559                    vd = (bits(machInst, 22) << 5) |
560                         (bits(machInst, 15, 12) << 1);
561                    vm = (bits(machInst, 5) << 5) |
562                         (bits(machInst, 3, 0) << 1);
563                    vn = (bits(machInst, 7) << 5) |
564                         (bits(machInst, 19, 16) << 1);
565                    return new VnmlsD(machInst, (IntRegIndex)vd,
566                            (IntRegIndex)vn, (IntRegIndex)vm);
567                }
568            }
569          case 0x2:
570            if ((opc3 & 0x1) == 0) {
571                uint32_t vd;
572                uint32_t vm;
573                uint32_t vn;
574                if (bits(machInst, 8) == 0) {
575                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
576                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
577                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
578                    return new VmulS(machInst, (IntRegIndex)vd,
579                            (IntRegIndex)vn, (IntRegIndex)vm);
580                } else {
581                    vd = (bits(machInst, 22) << 5) |
582                         (bits(machInst, 15, 12) << 1);
583                    vm = (bits(machInst, 5) << 5) |
584                         (bits(machInst, 3, 0) << 1);
585                    vn = (bits(machInst, 7) << 5) |
586                         (bits(machInst, 19, 16) << 1);
587                    return new VmulD(machInst, (IntRegIndex)vd,
588                            (IntRegIndex)vn, (IntRegIndex)vm);
589                }
590            } else {
591                uint32_t vd;
592                uint32_t vm;
593                uint32_t vn;
594                if (bits(machInst, 8) == 0) {
595                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
596                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
597                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
598                    return new VnmulS(machInst, (IntRegIndex)vd,
599                            (IntRegIndex)vn, (IntRegIndex)vm);
600                } else {
601                    vd = (bits(machInst, 22) << 5) |
602                         (bits(machInst, 15, 12) << 1);
603                    vm = (bits(machInst, 5) << 5) |
604                         (bits(machInst, 3, 0) << 1);
605                    vn = (bits(machInst, 7) << 5) |
606                         (bits(machInst, 19, 16) << 1);
607                    return new VnmulD(machInst, (IntRegIndex)vd,
608                            (IntRegIndex)vn, (IntRegIndex)vm);
609                }
610            }
611          case 0x3:
612            if ((opc3 & 0x1) == 0) {
613                uint32_t vd;
614                uint32_t vm;
615                uint32_t vn;
616                if (bits(machInst, 8) == 0) {
617                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
618                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
619                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
620                    return new VaddS(machInst, (IntRegIndex)vd,
621                            (IntRegIndex)vn, (IntRegIndex)vm);
622                } else {
623                    vd = (bits(machInst, 22) << 5) |
624                         (bits(machInst, 15, 12) << 1);
625                    vm = (bits(machInst, 5) << 5) |
626                         (bits(machInst, 3, 0) << 1);
627                    vn = (bits(machInst, 7) << 5) |
628                         (bits(machInst, 19, 16) << 1);
629                    return new VaddD(machInst, (IntRegIndex)vd,
630                            (IntRegIndex)vn, (IntRegIndex)vm);
631                }
632            } else {
633                uint32_t vd;
634                uint32_t vm;
635                uint32_t vn;
636                if (bits(machInst, 8) == 0) {
637                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
638                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
639                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
640                    return new VsubS(machInst, (IntRegIndex)vd,
641                            (IntRegIndex)vn, (IntRegIndex)vm);
642                } else {
643                    vd = (bits(machInst, 22) << 5) |
644                         (bits(machInst, 15, 12) << 1);
645                    vm = (bits(machInst, 5) << 5) |
646                         (bits(machInst, 3, 0) << 1);
647                    vn = (bits(machInst, 7) << 5) |
648                         (bits(machInst, 19, 16) << 1);
649                    return new VsubD(machInst, (IntRegIndex)vd,
650                            (IntRegIndex)vn, (IntRegIndex)vm);
651                }
652            }
653          case 0x8:
654            if ((opc3 & 0x1) == 0) {
655                uint32_t vd;
656                uint32_t vm;
657                uint32_t vn;
658                if (bits(machInst, 8) == 0) {
659                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
660                    vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
661                    vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1);
662                    return new VdivS(machInst, (IntRegIndex)vd,
663                            (IntRegIndex)vn, (IntRegIndex)vm);
664                } else {
665                    vd = (bits(machInst, 22) << 5) |
666                         (bits(machInst, 15, 12) << 1);
667                    vm = (bits(machInst, 5) << 5) |
668                         (bits(machInst, 3, 0) << 1);
669                    vn = (bits(machInst, 7) << 5) |
670                         (bits(machInst, 19, 16) << 1);
671                    return new VdivD(machInst, (IntRegIndex)vd,
672                            (IntRegIndex)vn, (IntRegIndex)vm);
673                }
674            }
675            break;
676          case 0xb:
677            if ((opc3 & 0x1) == 0) {
678                uint32_t vd;
679                const uint32_t baseImm =
680                    bits(machInst, 3, 0) | (bits(machInst, 19, 16) << 4);
681                if (bits(machInst, 8) == 0) {
682                    vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
683                    uint32_t imm = vfp_modified_imm(baseImm, false);
684                    return new VmovImmS(machInst, (IntRegIndex)vd, imm);
685                } else {
686                    vd = (bits(machInst, 22) << 5) |
687                         (bits(machInst, 15, 12) << 1);
688                    uint64_t imm = vfp_modified_imm(baseImm, true);
689                    return new VmovImmD(machInst, (IntRegIndex)vd, imm);
690                }
691            }
692            switch (opc2) {
693              case 0x0:
694                if (opc3 == 1) {
695                    uint32_t vd;
696                    uint32_t vm;
697                    if (bits(machInst, 8) == 0) {
698                        vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
699                        vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
700                        return new VmovRegS(machInst,
701                                (IntRegIndex)vd, (IntRegIndex)vm);
702                    } else {
703                        vd = (bits(machInst, 22) << 5) |
704                             (bits(machInst, 15, 12) << 1);
705                        vm = (bits(machInst, 5) << 5) |
706                             (bits(machInst, 3, 0) << 1);
707                        return new VmovRegD(machInst,
708                                (IntRegIndex)vd, (IntRegIndex)vm);
709                    }
710                } else {
711                    uint32_t vd;
712                    uint32_t vm;
713                    if (bits(machInst, 8) == 0) {
714                        vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
715                        vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
716                        return new VabsS(machInst,
717                                (IntRegIndex)vd, (IntRegIndex)vm);
718                    } else {
719                        vd = (bits(machInst, 22) << 5) |
720                             (bits(machInst, 15, 12) << 1);
721                        vm = (bits(machInst, 5) << 5) |
722                             (bits(machInst, 3, 0) << 1);
723                        return new VabsD(machInst,
724                                (IntRegIndex)vd, (IntRegIndex)vm);
725                    }
726                }
727              case 0x1:
728                if (opc3 == 1) {
729                    uint32_t vd;
730                    uint32_t vm;
731                    if (bits(machInst, 8) == 0) {
732                        vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
733                        vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
734                        return new VnegS(machInst,
735                                (IntRegIndex)vd, (IntRegIndex)vm);
736                    } else {
737                        vd = (bits(machInst, 22) << 5) |
738                             (bits(machInst, 15, 12) << 1);
739                        vm = (bits(machInst, 5) << 5) |
740                             (bits(machInst, 3, 0) << 1);
741                        return new VnegD(machInst,
742                                (IntRegIndex)vd, (IntRegIndex)vm);
743                    }
744                } else {
745                    uint32_t vd;
746                    uint32_t vm;
747                    if (bits(machInst, 8) == 0) {
748                        vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1);
749                        vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1);
750                        return new VsqrtS(machInst,
751                                (IntRegIndex)vd, (IntRegIndex)vm);
752                    } else {
753                        vd = (bits(machInst, 22) << 5) |
754                             (bits(machInst, 15, 12) << 1);
755                        vm = (bits(machInst, 5) << 5) |
756                             (bits(machInst, 3, 0) << 1);
757                        return new VsqrtD(machInst,
758                                (IntRegIndex)vd, (IntRegIndex)vm);
759                    }
760                }
761              case 0x2:
762              case 0x3:
763                // Between half and single precision.
764                return new WarnUnimplemented("vcvtb, vcvtt", machInst);
765              case 0x4:
766              case 0x5:
767                return new WarnUnimplemented("vcmp, vcmpe", machInst);
768              case 0x7:
769                if (opc3 == 0x3) {
770                    // Between double and single precision.
771                    return new WarnUnimplemented("vcvt", machInst);
772                }
773                break;
774              case 0x8:
775                // Between FP and int.
776                return new WarnUnimplemented("vcvt, vcvtr", machInst);
777              case 0xa:
778              case 0xb:
779                // Between FP and fixed point.
780                return new WarnUnimplemented("vcvt", machInst);
781              case 0xc:
782              case 0xd:
783                // Between FP and int.
784                return new WarnUnimplemented("vcvt, vcvtr", machInst);
785              case 0xe:
786              case 0xf:
787                // Between FP and fixed point.
788                return new WarnUnimplemented("vcvt", machInst);
789            }
790            break;
791        }
792        return new Unknown(machInst);
793    }
794    '''
795}};
796
797def format VfpData() {{
798    decode_block = '''
799    return decodeVfpData(machInst);
800    '''
801}};
802