// -*- mode:c++ -*- // Copyright (c) 2010-2013,2016-2017 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall // not be construed as granting a license to any other intellectual // property including but not limited to intellectual property relating // to a hardware implementation of the functionality of the software // licensed hereunder. You may use the software subject to the license // terms below provided that you ensure that this notice is replicated // unmodified and in its entirety in all distributions of the software, // modified or unmodified, in source code or in binary form. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Gabe Black // Giacomo Gabrielli def format Crc32() {{ decode_block = ''' { const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); uint8_t c_poly = bits(machInst, 9); uint8_t sz = bits(machInst, 22, 21); uint8_t crc_select = (c_poly << 2) | sz; switch(crc_select) { case 0x0: return new Crc32b(machInst, rd, rn, rm); case 0x1: return new Crc32h(machInst, rd, rn, rm); case 0x2: return new Crc32w(machInst, rd, rn, rm); case 0x4: return new Crc32cb(machInst, rd, rn, rm); case 0x5: return new Crc32ch(machInst, rd, rn, rm); case 0x6: return new Crc32cw(machInst, rd, rn, rm); default: return new Unknown(machInst); } } ''' }}; def format ArmERet() {{ decode_block = "return new Eret(machInst);" }}; def format Svc() {{ decode_block = "return new Svc(machInst, bits(machInst, 23, 0));" }}; def format ArmSmcHyp() {{ decode_block = ''' { if (bits(machInst, 21)) { return new Smc(machInst); } else { uint32_t imm16 = (bits(machInst, 19, 8) << 4) | (bits(machInst, 3, 0) << 0); return new Hvc(machInst, imm16); } } ''' }}; def format ArmMsrMrs() {{ decode_block = ''' { const uint8_t byteMask = bits(machInst, 19, 16); const uint8_t sysM = byteMask | (bits(machInst, 8) << 4); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const uint32_t opcode = bits(machInst, 24, 21); const bool useImm = bits(machInst, 25); const bool r = bits(machInst, 22); const bool isBanked = bits(machInst, 9); const uint32_t unrotated = bits(machInst, 7, 0); const uint32_t rotation = (bits(machInst, 11, 8) << 1); const uint32_t imm = rotate_imm(unrotated, rotation); switch (opcode) { case 0x8: if (isBanked) { return new MrsBankedReg(machInst, rd, sysM, r!=0); } else { return new MrsCpsr(machInst, rd); } case 0x9: if (useImm) { return new MsrCpsrImm(machInst, imm, byteMask); } else { if (isBanked) { return new MsrBankedReg(machInst, rn, sysM, r!=0); } else { return new MsrCpsrReg(machInst, rn, byteMask); } } case 0xa: if (isBanked) { return new MrsBankedReg(machInst, rd, sysM, r!=0); } else { return new MrsSpsr(machInst, rd); } case 0xb: if (useImm) { return new MsrSpsrImm(machInst, imm, byteMask); } else { if (isBanked) { return new MsrBankedReg(machInst, rn, sysM, r!=0); } else { return new MsrSpsrReg(machInst, rn, byteMask); } } default: return new Unknown(machInst); } } ''' }}; let {{ header_output = ''' StaticInstPtr decodeMcrMrc14(ExtMachInst machInst); ''' decoder_output = ''' StaticInstPtr decodeMcrMrc14(ExtMachInst machInst) { const uint32_t opc1 = bits(machInst, 23, 21); const uint32_t crn = bits(machInst, 19, 16); const uint32_t opc2 = bits(machInst, 7, 5); const uint32_t crm = bits(machInst, 3, 0); const MiscRegIndex miscReg = decodeCP14Reg(crn, opc1, crm, opc2); const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const bool isRead = bits(machInst, 20); switch (miscReg) { case MISCREG_NOP: return new NopInst(machInst); case MISCREG_CP14_UNIMPL: return new FailUnimplemented(isRead ? "mrc unknown" : "mcr unknown", machInst, csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown", crn, opc1, crm, opc2, isRead ? "read" : "write")); default: uint32_t iss = mcrMrcIssBuild(isRead, crm, rt, crn, opc1, opc2); if (isRead) { return new Mrc14(machInst, rt, (IntRegIndex)miscReg, iss); } else { return new Mcr14(machInst, (IntRegIndex)miscReg, rt, iss); } } } ''' }}; def format McrMrc14() {{ decode_block = ''' return decodeMcrMrc14(machInst); ''' }}; let {{ header_output = ''' StaticInstPtr decodeMcrMrc14(ExtMachInst machInst); StaticInstPtr decodeMcrMrc15(ExtMachInst machInst); ''' decoder_output = ''' StaticInstPtr decodeMcrMrc15(ExtMachInst machInst) { const uint32_t opc1 = bits(machInst, 23, 21); const uint32_t crn = bits(machInst, 19, 16); const uint32_t opc2 = bits(machInst, 7, 5); const uint32_t crm = bits(machInst, 3, 0); const MiscRegIndex miscReg = decodeCP15Reg(crn, opc1, crm, opc2); const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const bool isRead = bits(machInst, 20); uint32_t iss = mcrMrcIssBuild(isRead, crm, rt, crn, opc1, opc2); switch (miscReg) { case MISCREG_NOP: return new McrMrcMiscInst(isRead ? "mrc nop" : "mcr nop", machInst, iss, MISCREG_NOP); case MISCREG_CP15_UNIMPL: return new FailUnimplemented(isRead ? "mrc unkown" : "mcr unkown", machInst, csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown", crn, opc1, crm, opc2, isRead ? "read" : "write")); case MISCREG_CP15ISB: return new Isb(machInst, iss); case MISCREG_CP15DSB: return new Dsb(machInst, iss); case MISCREG_CP15DMB: return new Dmb(machInst, iss); case MISCREG_DCIMVAC: return new McrDcimvac(machInst, miscReg, rt, iss); case MISCREG_DCCMVAC: return new McrDccmvac(machInst, miscReg, rt, iss); case MISCREG_DCCMVAU: return new McrDccmvau(machInst, miscReg, rt, iss); case MISCREG_DCCIMVAC: return new McrDccimvac(machInst, miscReg, rt, iss); default: if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) { std::string full_mnem = csprintf("%s %s", isRead ? "mrc" : "mcr", miscRegName[miscReg]); warn("\\tinstruction '%s' unimplemented\\n", full_mnem); // Remove the warn flag and set the implemented flag. This // prevents the instruction warning a second time, it also // means the instruction is actually generated. Actually // creating the instruction to access an register that isn't // implemented sounds a bit silly, but its required to get // the correct behaviour for hyp traps and undef exceptions. miscRegInfo[miscReg][MISCREG_IMPLEMENTED] = true; miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL] = false; } if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) { if (isRead) return new Mrc15(machInst, rt, miscReg, iss); return new Mcr15(machInst, miscReg, rt, iss); } else { return new FailUnimplemented(isRead ? "mrc" : "mcr", machInst, csprintf("%s %s", isRead ? "mrc" : "mcr", miscRegName[miscReg])); } } } ''' }}; def format McrMrc15() {{ decode_block = ''' return decodeMcrMrc15(machInst); ''' }}; let {{ header_output = ''' StaticInstPtr decodeMcrrMrrc15(ExtMachInst machInst); ''' decoder_output = ''' StaticInstPtr decodeMcrrMrrc15(ExtMachInst machInst) { const uint32_t crm = bits(machInst, 3, 0); const uint32_t opc1 = bits(machInst, 7, 4); const MiscRegIndex miscReg = decodeCP15Reg64(crm, opc1); const IntRegIndex rt = (IntRegIndex) (uint32_t) bits(machInst, 15, 12); const IntRegIndex rt2 = (IntRegIndex) (uint32_t) bits(machInst, 19, 16); const bool isRead = bits(machInst, 20); switch (miscReg) { case MISCREG_CP15_UNIMPL: return new FailUnimplemented(isRead ? "mrc" : "mcr", machInst, csprintf("miscreg crm:%d opc1:%d 64-bit %s unknown", crm, opc1, isRead ? "read" : "write")); default: if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) { std::string full_mnem = csprintf("%s %s", isRead ? "mrrc" : "mcrr", miscRegName[miscReg]); warn("\\tinstruction '%s' unimplemented\\n", full_mnem); // Remove the warn flag and set the implemented flag. This // prevents the instruction warning a second time, it also // means the instruction is actually generated. Actually // creating the instruction to access an register that isn't // implemented sounds a bit silly, but its required to get // the correct behaviour for hyp traps and undef exceptions. miscRegInfo[miscReg][MISCREG_IMPLEMENTED] = true; miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL] = false; } if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) { uint32_t iss = mcrrMrrcIssBuild(isRead, crm, rt, rt2, opc1); if (isRead) { StaticInstPtr si = new Mrrc15(machInst, miscReg, rt2, rt, iss); if (miscRegInfo[miscReg][MISCREG_UNVERIFIABLE]) si->setFlag(StaticInst::IsUnverifiable); return si; } return new Mcrr15(machInst, rt2, rt, miscReg, iss); } else { return new FailUnimplemented(isRead ? "mrrc" : "mcrr", machInst, csprintf("%s %s", isRead ? "mrrc" : "mcrr", miscRegName[miscReg])); } } } ''' }}; def format Mcrr15() {{ decode_block = ''' return decodeMcrrMrrc15(machInst); ''' }}; def format Mrrc15() {{ decode_block = ''' return decodeMcrrMrrc15(machInst); ''' }};