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