| // -*- mode:c++ -*- |
| |
| // Copyright (c) 2010 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 |
| |
| let {{ |
| |
| header_output = "" |
| decoder_output = "" |
| exec_output = "" |
| |
| calcQCode = ''' |
| CpsrQ = (resTemp & 1) << 27; |
| ''' |
| |
| calcCcCode = ''' |
| uint16_t _iz, _in; |
| _in = (resTemp >> %(negBit)d) & 1; |
| _iz = ((%(zType)s)resTemp == 0); |
| |
| CondCodesNZ = (_in << 1) | _iz; |
| |
| DPRINTF(Arm, "(in, iz) = (%%d, %%d)\\n", _in, _iz); |
| ''' |
| |
| def buildMultInst(mnem, doCc, unCc, regs, code, flagType): |
| global header_output, decoder_output, exec_output |
| cCode = carryCode[flagType] |
| vCode = overflowCode[flagType] |
| zType = "uint32_t" |
| negBit = 31 |
| if flagType == "llbit": |
| zType = "uint64_t" |
| negBit = 63 |
| if flagType == "overflow": |
| ccCode = calcQCode |
| else: |
| ccCode = calcCcCode % { |
| "negBit": negBit, |
| "zType": zType |
| } |
| |
| if not regs in (3, 4): |
| raise Exception, "Multiplication instructions with %d " + \ |
| "registers are not implemented" |
| |
| if regs == 3: |
| base = 'Mult3' |
| else: |
| base = 'Mult4' |
| |
| Name = mnem.capitalize() |
| |
| if unCc: |
| iop = InstObjParams(mnem, Name, base, |
| {"code" : code, |
| "predicate_test": pickPredicate(code), |
| "op_class": "IntMultOp" }) |
| if doCc: |
| iopCc = InstObjParams(mnem + "s", Name + "Cc", base, |
| {"code" : code + ccCode, |
| "predicate_test": pickPredicate(code + ccCode), |
| "op_class": "IntMultOp" }) |
| |
| if regs == 3: |
| declare = Mult3Declare |
| constructor = Mult3Constructor |
| else: |
| declare = Mult4Declare |
| constructor = Mult4Constructor |
| |
| if unCc: |
| header_output += declare.subst(iop) |
| decoder_output += constructor.subst(iop) |
| exec_output += PredOpExecute.subst(iop) |
| if doCc: |
| header_output += declare.subst(iopCc) |
| decoder_output += constructor.subst(iopCc) |
| exec_output += PredOpExecute.subst(iopCc) |
| |
| def buildMult3Inst(mnem, code, flagType = "logic"): |
| buildMultInst(mnem, True, True, 3, code, flagType) |
| |
| def buildMult3InstCc(mnem, code, flagType = "logic"): |
| buildMultInst(mnem, True, False, 3, code, flagType) |
| |
| def buildMult3InstUnCc(mnem, code, flagType = "logic"): |
| buildMultInst(mnem, False, True, 3, code, flagType) |
| |
| def buildMult4Inst(mnem, code, flagType = "logic"): |
| buildMultInst(mnem, True, True, 4, code, flagType) |
| |
| def buildMult4InstCc(mnem, code, flagType = "logic"): |
| buildMultInst(mnem, True, False, 4, code, flagType) |
| |
| def buildMult4InstUnCc(mnem, code, flagType = "logic"): |
| buildMultInst(mnem, False, True, 4, code, flagType) |
| |
| buildMult4Inst ("mla", "Reg0 = resTemp = Reg1 * Reg2 + Reg3;") |
| buildMult4InstUnCc("mls", "Reg0 = resTemp = Reg3 - Reg1 * Reg2;") |
| buildMult3Inst ("mul", "Reg0 = resTemp = Reg1 * Reg2;") |
| buildMult4InstCc ("smlabb", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2_sw, 15, 0)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlabt", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2_sw, 31, 16)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlatb", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2_sw, 15, 0)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlatt", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2_sw, 31, 16)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlad", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 31, 16)) + |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 15, 0)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smladx", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 15, 0)) + |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 31, 16)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4Inst ("smlal", '''resTemp = sext<32>(Reg2) * sext<32>(Reg3) + |
| (int64_t)((Reg1_ud << 32) | Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''', "llbit") |
| buildMult4InstUnCc("smlalbb", '''resTemp = sext<16>(bits(Reg2, 15, 0)) * |
| sext<16>(bits(Reg3, 15, 0)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smlalbt", '''resTemp = sext<16>(bits(Reg2, 15, 0)) * |
| sext<16>(bits(Reg3, 31, 16)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smlaltb", '''resTemp = sext<16>(bits(Reg2, 31, 16)) * |
| sext<16>(bits(Reg3, 15, 0)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smlaltt", '''resTemp = sext<16>(bits(Reg2, 31, 16)) * |
| sext<16>(bits(Reg3, 31, 16)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smlald", '''resTemp = |
| sext<16>(bits(Reg2, 31, 16)) * |
| sext<16>(bits(Reg3, 31, 16)) + |
| sext<16>(bits(Reg2, 15, 0)) * |
| sext<16>(bits(Reg3, 15, 0)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smlaldx", '''resTemp = |
| sext<16>(bits(Reg2, 31, 16)) * |
| sext<16>(bits(Reg3, 15, 0)) + |
| sext<16>(bits(Reg2, 15, 0)) * |
| sext<16>(bits(Reg3, 31, 16)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstCc ("smlawb", '''Reg0 = resTemp = |
| (Reg1_sw * |
| sext<16>(bits(Reg2, 15, 0)) + |
| ((int64_t)Reg3_sw << 16)) >> 16; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlawt", '''Reg0 = resTemp = |
| (Reg1_sw * |
| sext<16>(bits(Reg2, 31, 16)) + |
| ((int64_t)Reg3_sw << 16)) >> 16; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlsd", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 15, 0)) - |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 31, 16)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstCc ("smlsdx", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 31, 16)) - |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 15, 0)) + |
| Reg3_sw; |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult4InstUnCc("smlsld", '''resTemp = |
| sext<16>(bits(Reg2, 15, 0)) * |
| sext<16>(bits(Reg3, 15, 0)) - |
| sext<16>(bits(Reg2, 31, 16)) * |
| sext<16>(bits(Reg3, 31, 16)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smlsldx", '''resTemp = |
| sext<16>(bits(Reg2, 15, 0)) * |
| sext<16>(bits(Reg3, 31, 16)) - |
| sext<16>(bits(Reg2, 31, 16)) * |
| sext<16>(bits(Reg3, 15, 0)) + |
| (int64_t)((Reg1_ud << 32) | |
| Reg0_ud); |
| Reg0_ud = (uint32_t)resTemp; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| ''') |
| buildMult4InstUnCc("smmla", '''Reg0 = resTemp = |
| ((int64_t)(Reg3_ud << 32) + |
| (int64_t)Reg1_sw * |
| (int64_t)Reg2_sw) >> 32; |
| ''') |
| buildMult4InstUnCc("smmlar", '''Reg0 = resTemp = |
| ((int64_t)(Reg3_ud << 32) + |
| (int64_t)Reg1_sw * |
| (int64_t)Reg2_sw + |
| ULL(0x80000000)) >> 32; |
| ''') |
| buildMult4InstUnCc("smmls", '''Reg0 = resTemp = |
| ((int64_t)(Reg3_ud << 32) - |
| (int64_t)Reg1_sw * |
| (int64_t)Reg2_sw) >> 32; |
| ''') |
| buildMult4InstUnCc("smmlsr", '''Reg0 = resTemp = |
| ((int64_t)(Reg3_ud << 32) - |
| (int64_t)Reg1_sw * |
| (int64_t)Reg2_sw + |
| ULL(0x80000000)) >> 32; |
| ''') |
| buildMult3InstUnCc("smmul", '''Reg0 = resTemp = |
| ((int64_t)Reg1_sw * |
| (int64_t)Reg2_sw) >> 32; |
| ''') |
| buildMult3InstUnCc("smmulr", '''Reg0 = resTemp = |
| ((int64_t)Reg1_sw * |
| (int64_t)Reg2_sw + |
| ULL(0x80000000)) >> 32; |
| ''') |
| buildMult3InstCc ("smuad", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 15, 0)) + |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 31, 16)); |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult3InstCc ("smuadx", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 31, 16)) + |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 15, 0)); |
| resTemp = bits(resTemp, 32) != |
| bits(resTemp, 31); |
| ''', "overflow") |
| buildMult3InstUnCc("smulbb", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 15, 0)); |
| ''') |
| buildMult3InstUnCc("smulbt", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 31, 16)); |
| ''') |
| buildMult3InstUnCc("smultb", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 15, 0)); |
| ''') |
| buildMult3InstUnCc("smultt", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 31, 16)); |
| ''') |
| buildMult4Inst ("smull", '''resTemp = (int64_t)Reg2_sw * |
| (int64_t)Reg3_sw; |
| Reg1 = (int32_t)(resTemp >> 32); |
| Reg0 = (int32_t)resTemp; |
| ''', "llbit") |
| buildMult3InstUnCc("smulwb", '''Reg0 = resTemp = |
| (Reg1_sw * |
| sext<16>(bits(Reg2, 15, 0))) >> 16; |
| ''') |
| buildMult3InstUnCc("smulwt", '''Reg0 = resTemp = |
| (Reg1_sw * |
| sext<16>(bits(Reg2, 31, 16))) >> 16; |
| ''') |
| buildMult3InstUnCc("smusd", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 15, 0)) - |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 31, 16)); |
| ''') |
| buildMult3InstUnCc("smusdx", '''Reg0 = resTemp = |
| sext<16>(bits(Reg1, 15, 0)) * |
| sext<16>(bits(Reg2, 31, 16)) - |
| sext<16>(bits(Reg1, 31, 16)) * |
| sext<16>(bits(Reg2, 15, 0)); |
| ''') |
| buildMult4InstUnCc("umaal", '''resTemp = Reg2_ud * Reg3_ud + |
| Reg0_ud + Reg1_ud; |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| Reg0_ud = (uint32_t)resTemp; |
| ''') |
| buildMult4Inst ("umlal", '''resTemp = Reg2_ud * Reg3_ud + Reg0_ud + |
| (Reg1_ud << 32); |
| Reg1_ud = (uint32_t)(resTemp >> 32); |
| Reg0_ud = (uint32_t)resTemp; |
| ''', "llbit") |
| buildMult4Inst ("umull", '''resTemp = Reg2_ud * Reg3_ud; |
| Reg1 = (uint32_t)(resTemp >> 32); |
| Reg0 = (uint32_t)resTemp; |
| ''', "llbit") |
| }}; |