1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Copyright (c) 2007-2008 The Florida State University 16// All rights reserved. 17// 18// Redistribution and use in source and binary forms, with or without 19// modification, are permitted provided that the following conditions are 20// met: redistributions of source code must retain the above copyright 21// notice, this list of conditions and the following disclaimer; 22// redistributions in binary form must reproduce the above copyright 23// notice, this list of conditions and the following disclaimer in the 24// documentation and/or other materials provided with the distribution; 25// neither the name of the copyright holders nor the names of its 26// contributors may be used to endorse or promote products derived from 27// this software without specific prior written permission. 28// 29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40// 41// Authors: Stephen Hines 42// Gabe Black 43 44//////////////////////////////////////////////////////////////////// 45// 46// Load/store microops 47// 48 49let {{ 50 microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 51 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 52 'MicroMemOp', 53 {'memacc_code': microLdrUopCode, 54 'ea_code': 'EA = Rb + (up ? imm : -imm);', 55 'predicate_test': predicateTest}, 56 ['IsMicroop']) 57 58 microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 59 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 60 'MicroMemOp', 61 {'memacc_code': microLdrFpUopCode,
| 1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Copyright (c) 2007-2008 The Florida State University 16// All rights reserved. 17// 18// Redistribution and use in source and binary forms, with or without 19// modification, are permitted provided that the following conditions are 20// met: redistributions of source code must retain the above copyright 21// notice, this list of conditions and the following disclaimer; 22// redistributions in binary form must reproduce the above copyright 23// notice, this list of conditions and the following disclaimer in the 24// documentation and/or other materials provided with the distribution; 25// neither the name of the copyright holders nor the names of its 26// contributors may be used to endorse or promote products derived from 27// this software without specific prior written permission. 28// 29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40// 41// Authors: Stephen Hines 42// Gabe Black 43 44//////////////////////////////////////////////////////////////////// 45// 46// Load/store microops 47// 48 49let {{ 50 microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 51 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 52 'MicroMemOp', 53 {'memacc_code': microLdrUopCode, 54 'ea_code': 'EA = Rb + (up ? imm : -imm);', 55 'predicate_test': predicateTest}, 56 ['IsMicroop']) 57 58 microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 59 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 60 'MicroMemOp', 61 {'memacc_code': microLdrFpUopCode,
|
62 'ea_code':
| 62 'ea_code': vfpEnabledCheckCode +
|
63 'EA = Rb + (up ? imm : -imm);', 64 'predicate_test': predicateTest}, 65 ['IsMicroop']) 66 67 microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 68 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 69 'MicroMemOp', 70 {'memacc_code': microLdrFpUopCode,
| 63 'EA = Rb + (up ? imm : -imm);', 64 'predicate_test': predicateTest}, 65 ['IsMicroop']) 66 67 microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 68 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 69 'MicroMemOp', 70 {'memacc_code': microLdrFpUopCode,
|
71 'ea_code': '''
| 71 'ea_code': vfpEnabledCheckCode + '''
|
72 EA = Rb + (up ? imm : -imm) + 73 (((CPSR)Cpsr).e ? 4 : 0); 74 ''', 75 'predicate_test': predicateTest}, 76 ['IsMicroop']) 77 78 microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 79 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 80 'MicroMemOp', 81 {'memacc_code': microLdrFpUopCode,
| 72 EA = Rb + (up ? imm : -imm) + 73 (((CPSR)Cpsr).e ? 4 : 0); 74 ''', 75 'predicate_test': predicateTest}, 76 ['IsMicroop']) 77 78 microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 79 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 80 'MicroMemOp', 81 {'memacc_code': microLdrFpUopCode,
|
82 'ea_code': '''
| 82 'ea_code': vfpEnabledCheckCode + '''
|
83 EA = Rb + (up ? imm : -imm) - 84 (((CPSR)Cpsr).e ? 4 : 0); 85 ''', 86 'predicate_test': predicateTest}, 87 ['IsMicroop']) 88 89 microLdrRetUopCode = ''' 90 CPSR cpsr = Cpsr; 91 SCTLR sctlr = Sctlr; 92 uint32_t newCpsr = 93 cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); 94 Cpsr = ~CondCodesMask & newCpsr; 95 CondCodes = CondCodesMask & newCpsr; 96 IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 97 ''' 98 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 99 'MicroMemOp', 100 {'memacc_code': microLdrRetUopCode, 101 'ea_code': 102 'EA = Rb + (up ? imm : -imm);', 103 'predicate_test': condPredicateTest}, 104 ['IsMicroop']) 105 106 microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);" 107 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 108 'MicroMemOp', 109 {'memacc_code': microStrUopCode, 110 'postacc_code': "", 111 'ea_code': 'EA = Rb + (up ? imm : -imm);', 112 'predicate_test': predicateTest}, 113 ['IsMicroop']) 114 115 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 116 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 117 'MicroMemOp', 118 {'memacc_code': microStrFpUopCode, 119 'postacc_code': "",
| 83 EA = Rb + (up ? imm : -imm) - 84 (((CPSR)Cpsr).e ? 4 : 0); 85 ''', 86 'predicate_test': predicateTest}, 87 ['IsMicroop']) 88 89 microLdrRetUopCode = ''' 90 CPSR cpsr = Cpsr; 91 SCTLR sctlr = Sctlr; 92 uint32_t newCpsr = 93 cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); 94 Cpsr = ~CondCodesMask & newCpsr; 95 CondCodes = CondCodesMask & newCpsr; 96 IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 97 ''' 98 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 99 'MicroMemOp', 100 {'memacc_code': microLdrRetUopCode, 101 'ea_code': 102 'EA = Rb + (up ? imm : -imm);', 103 'predicate_test': condPredicateTest}, 104 ['IsMicroop']) 105 106 microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);" 107 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 108 'MicroMemOp', 109 {'memacc_code': microStrUopCode, 110 'postacc_code': "", 111 'ea_code': 'EA = Rb + (up ? imm : -imm);', 112 'predicate_test': predicateTest}, 113 ['IsMicroop']) 114 115 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 116 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 117 'MicroMemOp', 118 {'memacc_code': microStrFpUopCode, 119 'postacc_code': "",
|
120 'ea_code': 'EA = Rb + (up ? imm : -imm);',
| 120 'ea_code': vfpEnabledCheckCode + 121 'EA = Rb + (up ? imm : -imm);',
|
121 'predicate_test': predicateTest}, 122 ['IsMicroop']) 123 124 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 125 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 126 'MicroMemOp', 127 {'memacc_code': microStrFpUopCode, 128 'postacc_code': "",
| 122 'predicate_test': predicateTest}, 123 ['IsMicroop']) 124 125 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 126 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 127 'MicroMemOp', 128 {'memacc_code': microStrFpUopCode, 129 'postacc_code': "",
|
129 'ea_code': '''
| 130 'ea_code': vfpEnabledCheckCode + '''
|
130 EA = Rb + (up ? imm : -imm) + 131 (((CPSR)Cpsr).e ? 4 : 0); 132 ''', 133 'predicate_test': predicateTest}, 134 ['IsMicroop']) 135 136 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 137 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 138 'MicroMemOp', 139 {'memacc_code': microStrFpUopCode, 140 'postacc_code': "",
| 131 EA = Rb + (up ? imm : -imm) + 132 (((CPSR)Cpsr).e ? 4 : 0); 133 ''', 134 'predicate_test': predicateTest}, 135 ['IsMicroop']) 136 137 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 138 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 139 'MicroMemOp', 140 {'memacc_code': microStrFpUopCode, 141 'postacc_code': "",
|
141 'ea_code': '''
| 142 'ea_code': vfpEnabledCheckCode + '''
|
142 EA = Rb + (up ? imm : -imm) - 143 (((CPSR)Cpsr).e ? 4 : 0); 144 ''', 145 'predicate_test': predicateTest}, 146 ['IsMicroop']) 147 148 header_output = decoder_output = exec_output = '' 149 150 loadIops = (microLdrUopIop, microLdrRetUopIop, 151 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 152 storeIops = (microStrUopIop, microStrFpUopIop, 153 microStrDBFpUopIop, microStrDTFpUopIop) 154 for iop in loadIops + storeIops: 155 header_output += MicroMemDeclare.subst(iop) 156 decoder_output += MicroMemConstructor.subst(iop) 157 for iop in loadIops: 158 exec_output += LoadExecute.subst(iop) + \ 159 LoadInitiateAcc.subst(iop) + \ 160 LoadCompleteAcc.subst(iop) 161 for iop in storeIops: 162 exec_output += StoreExecute.subst(iop) + \ 163 StoreInitiateAcc.subst(iop) + \ 164 StoreCompleteAcc.subst(iop) 165}}; 166 167let {{ 168 exec_output = header_output = '' 169 170 eaCode = 'EA = Ra + imm;' 171 172 for size in (1, 2, 3, 4, 6, 8, 12, 16): 173 # Set up the memory access. 174 regs = (size + 3) // 4 175 subst = { "size" : size, "regs" : regs } 176 memDecl = ''' 177 union MemUnion { 178 uint8_t bytes[%(size)d]; 179 Element elements[%(size)d / sizeof(Element)]; 180 uint32_t floatRegBits[%(regs)d]; 181 }; 182 ''' % subst 183 184 # Do endian conversion for all the elements. 185 convCode = ''' 186 const unsigned eCount = sizeof(memUnion.elements) / 187 sizeof(memUnion.elements[0]); 188 if (((CPSR)Cpsr).e) { 189 for (unsigned i = 0; i < eCount; i++) { 190 memUnion.elements[i] = gtobe(memUnion.elements[i]); 191 } 192 } else { 193 for (unsigned i = 0; i < eCount; i++) { 194 memUnion.elements[i] = gtole(memUnion.elements[i]); 195 } 196 } 197 ''' 198 199 # Offload everything into registers 200 regSetCode = '' 201 for reg in range(regs): 202 mask = '' 203 if reg == regs - 1: 204 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 205 regSetCode += ''' 206 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 207 ''' % { "reg" : reg, "mask" : mask } 208 209 # Pull everything in from registers 210 regGetCode = '' 211 for reg in range(regs): 212 regGetCode += ''' 213 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 214 ''' % { "reg" : reg } 215 216 loadMemAccCode = convCode + regSetCode 217 storeMemAccCode = regGetCode + convCode 218 219 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 220 'MicroLdrNeon%(size)dUop' % subst, 221 'MicroNeonMemOp', 222 { 'mem_decl' : memDecl, 223 'size' : size, 224 'memacc_code' : loadMemAccCode,
| 143 EA = Rb + (up ? imm : -imm) - 144 (((CPSR)Cpsr).e ? 4 : 0); 145 ''', 146 'predicate_test': predicateTest}, 147 ['IsMicroop']) 148 149 header_output = decoder_output = exec_output = '' 150 151 loadIops = (microLdrUopIop, microLdrRetUopIop, 152 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 153 storeIops = (microStrUopIop, microStrFpUopIop, 154 microStrDBFpUopIop, microStrDTFpUopIop) 155 for iop in loadIops + storeIops: 156 header_output += MicroMemDeclare.subst(iop) 157 decoder_output += MicroMemConstructor.subst(iop) 158 for iop in loadIops: 159 exec_output += LoadExecute.subst(iop) + \ 160 LoadInitiateAcc.subst(iop) + \ 161 LoadCompleteAcc.subst(iop) 162 for iop in storeIops: 163 exec_output += StoreExecute.subst(iop) + \ 164 StoreInitiateAcc.subst(iop) + \ 165 StoreCompleteAcc.subst(iop) 166}}; 167 168let {{ 169 exec_output = header_output = '' 170 171 eaCode = 'EA = Ra + imm;' 172 173 for size in (1, 2, 3, 4, 6, 8, 12, 16): 174 # Set up the memory access. 175 regs = (size + 3) // 4 176 subst = { "size" : size, "regs" : regs } 177 memDecl = ''' 178 union MemUnion { 179 uint8_t bytes[%(size)d]; 180 Element elements[%(size)d / sizeof(Element)]; 181 uint32_t floatRegBits[%(regs)d]; 182 }; 183 ''' % subst 184 185 # Do endian conversion for all the elements. 186 convCode = ''' 187 const unsigned eCount = sizeof(memUnion.elements) / 188 sizeof(memUnion.elements[0]); 189 if (((CPSR)Cpsr).e) { 190 for (unsigned i = 0; i < eCount; i++) { 191 memUnion.elements[i] = gtobe(memUnion.elements[i]); 192 } 193 } else { 194 for (unsigned i = 0; i < eCount; i++) { 195 memUnion.elements[i] = gtole(memUnion.elements[i]); 196 } 197 } 198 ''' 199 200 # Offload everything into registers 201 regSetCode = '' 202 for reg in range(regs): 203 mask = '' 204 if reg == regs - 1: 205 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 206 regSetCode += ''' 207 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 208 ''' % { "reg" : reg, "mask" : mask } 209 210 # Pull everything in from registers 211 regGetCode = '' 212 for reg in range(regs): 213 regGetCode += ''' 214 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 215 ''' % { "reg" : reg } 216 217 loadMemAccCode = convCode + regSetCode 218 storeMemAccCode = regGetCode + convCode 219 220 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 221 'MicroLdrNeon%(size)dUop' % subst, 222 'MicroNeonMemOp', 223 { 'mem_decl' : memDecl, 224 'size' : size, 225 'memacc_code' : loadMemAccCode,
|
225 'ea_code' : eaCode,
| 226 'ea_code' : simdEnabledCheckCode + eaCode,
|
226 'predicate_test' : predicateTest }, 227 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 228 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 229 'MicroStrNeon%(size)dUop' % subst, 230 'MicroNeonMemOp', 231 { 'mem_decl' : memDecl, 232 'size' : size, 233 'memacc_code' : storeMemAccCode,
| 227 'predicate_test' : predicateTest }, 228 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 229 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 230 'MicroStrNeon%(size)dUop' % subst, 231 'MicroNeonMemOp', 232 { 'mem_decl' : memDecl, 233 'size' : size, 234 'memacc_code' : storeMemAccCode,
|
234 'ea_code' : eaCode,
| 235 'ea_code' : simdEnabledCheckCode + eaCode,
|
235 'predicate_test' : predicateTest }, 236 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 237 238 exec_output += NeonLoadExecute.subst(loadIop) + \ 239 NeonLoadInitiateAcc.subst(loadIop) + \ 240 NeonLoadCompleteAcc.subst(loadIop) + \ 241 NeonStoreExecute.subst(storeIop) + \ 242 NeonStoreInitiateAcc.subst(storeIop) + \ 243 NeonStoreCompleteAcc.subst(storeIop) 244 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 245 MicroNeonMemDeclare.subst(storeIop) 246}}; 247 248let {{ 249 exec_output = '' 250 for eSize, type in (1, 'uint8_t'), \ 251 (2, 'uint16_t'), \ 252 (4, 'uint32_t'), \ 253 (8, 'uint64_t'): 254 size = eSize 255 # An instruction handles no more than 16 bytes and no more than 256 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 257 sizes = set((16, 8)) 258 for count in 1, 2, 3, 4: 259 size = count * eSize 260 if size <= 16: 261 sizes.add(size) 262 for size in sizes: 263 substDict = { 264 "class_name" : "MicroLdrNeon%dUop" % size, 265 "targs" : type 266 } 267 exec_output += MicroNeonMemExecDeclare.subst(substDict) 268 substDict["class_name"] = "MicroStrNeon%dUop" % size 269 exec_output += MicroNeonMemExecDeclare.subst(substDict) 270 size += eSize 271}}; 272 273//////////////////////////////////////////////////////////////////// 274// 275// Neon (de)interlacing microops 276// 277 278let {{ 279 header_output = exec_output = '' 280 for dRegs in (2, 3, 4): 281 loadConv = '' 282 unloadConv = '' 283 for dReg in range(dRegs): 284 loadConv += ''' 285 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 286 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 287 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 288 unloadConv += ''' 289 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 290 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 291 ''' % { "dReg" : dReg } 292 microDeintNeonCode = ''' 293 const unsigned dRegs = %(dRegs)d; 294 const unsigned regs = 2 * dRegs; 295 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 296 sizeof(Element); 297 union convStruct { 298 FloatRegBits cRegs[regs]; 299 Element elements[dRegs * perDReg]; 300 } conv1, conv2; 301 302 %(loadConv)s 303 304 unsigned srcElem = 0; 305 for (unsigned destOffset = 0; 306 destOffset < perDReg; destOffset++) { 307 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 308 conv2.elements[dReg * perDReg + destOffset] = 309 conv1.elements[srcElem++]; 310 } 311 } 312 313 %(unloadConv)s 314 ''' % { "dRegs" : dRegs, 315 "loadConv" : loadConv, 316 "unloadConv" : unloadConv } 317 microDeintNeonIop = \ 318 InstObjParams('deintneon%duop' % (dRegs * 2), 319 'MicroDeintNeon%dUop' % (dRegs * 2), 320 'MicroNeonMixOp', 321 { 'predicate_test': predicateTest, 322 'code' : microDeintNeonCode }, 323 ['IsMicroop']) 324 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 325 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 326 327 loadConv = '' 328 unloadConv = '' 329 for dReg in range(dRegs): 330 loadConv += ''' 331 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 332 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 333 ''' % { "dReg" : dReg } 334 unloadConv += ''' 335 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 336 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 337 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 338 microInterNeonCode = ''' 339 const unsigned dRegs = %(dRegs)d; 340 const unsigned regs = 2 * dRegs; 341 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 342 sizeof(Element); 343 union convStruct { 344 FloatRegBits cRegs[regs]; 345 Element elements[dRegs * perDReg]; 346 } conv1, conv2; 347 348 %(loadConv)s 349 350 unsigned destElem = 0; 351 for (unsigned srcOffset = 0; 352 srcOffset < perDReg; srcOffset++) { 353 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 354 conv2.elements[destElem++] = 355 conv1.elements[dReg * perDReg + srcOffset]; 356 } 357 } 358 359 %(unloadConv)s 360 ''' % { "dRegs" : dRegs, 361 "loadConv" : loadConv, 362 "unloadConv" : unloadConv } 363 microInterNeonIop = \ 364 InstObjParams('interneon%duop' % (dRegs * 2), 365 'MicroInterNeon%dUop' % (dRegs * 2), 366 'MicroNeonMixOp', 367 { 'predicate_test': predicateTest, 368 'code' : microInterNeonCode }, 369 ['IsMicroop']) 370 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 371 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 372}}; 373 374let {{ 375 exec_output = '' 376 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 377 for dRegs in (2, 3, 4): 378 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 379 substDict = { "class_name" : Name, "targs" : type } 380 exec_output += MicroNeonExecDeclare.subst(substDict) 381 Name = "MicroInterNeon%dUop" % (dRegs * 2) 382 substDict = { "class_name" : Name, "targs" : type } 383 exec_output += MicroNeonExecDeclare.subst(substDict) 384}}; 385 386//////////////////////////////////////////////////////////////////// 387// 388// Neon microops to pack/unpack a single lane 389// 390 391let {{ 392 header_output = exec_output = '' 393 for sRegs in 1, 2: 394 baseLoadRegs = '' 395 for reg in range(sRegs): 396 baseLoadRegs += ''' 397 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 398 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 399 ''' % { "reg0" : (2 * reg + 0), 400 "reg1" : (2 * reg + 1) } 401 for dRegs in range(sRegs, 5): 402 unloadRegs = '' 403 loadRegs = baseLoadRegs 404 for reg in range(dRegs): 405 loadRegs += ''' 406 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 407 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 408 ''' % { "reg" : reg } 409 unloadRegs += ''' 410 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 411 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 412 ''' % { "reg" : reg } 413 microUnpackNeonCode = ''' 414 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 415 sizeof(Element); 416 417 union SourceRegs { 418 FloatRegBits fRegs[2 * %(sRegs)d]; 419 Element elements[%(sRegs)d * perDReg]; 420 } sourceRegs; 421 422 union DestReg { 423 FloatRegBits fRegs[2]; 424 Element elements[perDReg]; 425 } destRegs[%(dRegs)d]; 426 427 %(loadRegs)s 428 429 for (unsigned i = 0; i < %(dRegs)d; i++) { 430 destRegs[i].elements[lane] = sourceRegs.elements[i]; 431 } 432 433 %(unloadRegs)s 434 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 435 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 436 437 microUnpackNeonIop = \ 438 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 439 'MicroUnpackNeon%dto%dUop' % 440 (sRegs * 2, dRegs * 2), 441 'MicroNeonMixLaneOp', 442 { 'predicate_test': predicateTest, 443 'code' : microUnpackNeonCode }, 444 ['IsMicroop']) 445 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 446 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 447 448 for sRegs in 1, 2: 449 loadRegs = '' 450 for reg in range(sRegs): 451 loadRegs += ''' 452 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 453 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 454 ''' % { "reg0" : (2 * reg + 0), 455 "reg1" : (2 * reg + 1) } 456 for dRegs in range(sRegs, 5): 457 unloadRegs = '' 458 for reg in range(dRegs): 459 unloadRegs += ''' 460 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 461 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 462 ''' % { "reg" : reg } 463 microUnpackAllNeonCode = ''' 464 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 465 sizeof(Element); 466 467 union SourceRegs { 468 FloatRegBits fRegs[2 * %(sRegs)d]; 469 Element elements[%(sRegs)d * perDReg]; 470 } sourceRegs; 471 472 union DestReg { 473 FloatRegBits fRegs[2]; 474 Element elements[perDReg]; 475 } destRegs[%(dRegs)d]; 476 477 %(loadRegs)s 478 479 for (unsigned i = 0; i < %(dRegs)d; i++) { 480 for (unsigned j = 0; j < perDReg; j++) 481 destRegs[i].elements[j] = sourceRegs.elements[i]; 482 } 483 484 %(unloadRegs)s 485 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 486 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 487 488 microUnpackAllNeonIop = \ 489 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 490 'MicroUnpackAllNeon%dto%dUop' % 491 (sRegs * 2, dRegs * 2), 492 'MicroNeonMixOp', 493 { 'predicate_test': predicateTest, 494 'code' : microUnpackAllNeonCode }, 495 ['IsMicroop']) 496 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 497 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 498 499 for dRegs in 1, 2: 500 unloadRegs = '' 501 for reg in range(dRegs): 502 unloadRegs += ''' 503 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 504 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 505 ''' % { "reg0" : (2 * reg + 0), 506 "reg1" : (2 * reg + 1) } 507 for sRegs in range(dRegs, 5): 508 loadRegs = '' 509 for reg in range(sRegs): 510 loadRegs += ''' 511 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 512 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 513 ''' % { "reg" : reg } 514 microPackNeonCode = ''' 515 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 516 sizeof(Element); 517 518 union SourceReg { 519 FloatRegBits fRegs[2]; 520 Element elements[perDReg]; 521 } sourceRegs[%(sRegs)d]; 522 523 union DestRegs { 524 FloatRegBits fRegs[2 * %(dRegs)d]; 525 Element elements[%(dRegs)d * perDReg]; 526 } destRegs; 527 528 %(loadRegs)s 529 530 for (unsigned i = 0; i < %(sRegs)d; i++) { 531 destRegs.elements[i] = sourceRegs[i].elements[lane]; 532 } 533 534 %(unloadRegs)s 535 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 536 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 537 538 microPackNeonIop = \ 539 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 540 'MicroPackNeon%dto%dUop' % 541 (sRegs * 2, dRegs * 2), 542 'MicroNeonMixLaneOp', 543 { 'predicate_test': predicateTest, 544 'code' : microPackNeonCode }, 545 ['IsMicroop']) 546 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 547 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 548}}; 549 550let {{ 551 exec_output = '' 552 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 553 for sRegs in 1, 2: 554 for dRegs in range(sRegs, 5): 555 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 556 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 557 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 558 Name = format % { "sRegs" : sRegs * 2, 559 "dRegs" : dRegs * 2 } 560 substDict = { "class_name" : Name, "targs" : type } 561 exec_output += MicroNeonExecDeclare.subst(substDict) 562}}; 563 564//////////////////////////////////////////////////////////////////// 565// 566// Integer = Integer op Immediate microops 567// 568 569let {{ 570 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 571 'MicroIntImmOp', 572 {'code': 'Ra = Rb + imm;', 573 'predicate_test': predicateTest}, 574 ['IsMicroop']) 575 576 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 577 'MicroIntOp', 578 {'code': 'Ra = Rb + Rc;', 579 'predicate_test': predicateTest}, 580 ['IsMicroop']) 581 582 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 583 'MicroIntImmOp', 584 {'code': 'Ra = Rb - imm;', 585 'predicate_test': predicateTest}, 586 ['IsMicroop']) 587 588 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 589 MicroIntImmDeclare.subst(microSubiUopIop) + \ 590 MicroIntDeclare.subst(microAddUopIop) 591 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 592 MicroIntImmConstructor.subst(microSubiUopIop) + \ 593 MicroIntConstructor.subst(microAddUopIop) 594 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 595 PredOpExecute.subst(microSubiUopIop) + \ 596 PredOpExecute.subst(microAddUopIop) 597}}; 598 599let {{ 600 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 601 header_output = MacroMemDeclare.subst(iop) 602 decoder_output = MacroMemConstructor.subst(iop) 603 604 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 605 header_output += VMemMultDeclare.subst(iop) 606 decoder_output += VMemMultConstructor.subst(iop) 607 608 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 609 header_output += VMemSingleDeclare.subst(iop) 610 decoder_output += VMemSingleConstructor.subst(iop) 611 612 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 613 header_output += VMemMultDeclare.subst(iop) 614 decoder_output += VMemMultConstructor.subst(iop) 615 616 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 617 header_output += VMemSingleDeclare.subst(iop) 618 decoder_output += VMemSingleConstructor.subst(iop) 619 620 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 621 header_output += MacroVFPMemDeclare.subst(vfpIop) 622 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 623}};
| 236 'predicate_test' : predicateTest }, 237 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 238 239 exec_output += NeonLoadExecute.subst(loadIop) + \ 240 NeonLoadInitiateAcc.subst(loadIop) + \ 241 NeonLoadCompleteAcc.subst(loadIop) + \ 242 NeonStoreExecute.subst(storeIop) + \ 243 NeonStoreInitiateAcc.subst(storeIop) + \ 244 NeonStoreCompleteAcc.subst(storeIop) 245 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 246 MicroNeonMemDeclare.subst(storeIop) 247}}; 248 249let {{ 250 exec_output = '' 251 for eSize, type in (1, 'uint8_t'), \ 252 (2, 'uint16_t'), \ 253 (4, 'uint32_t'), \ 254 (8, 'uint64_t'): 255 size = eSize 256 # An instruction handles no more than 16 bytes and no more than 257 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 258 sizes = set((16, 8)) 259 for count in 1, 2, 3, 4: 260 size = count * eSize 261 if size <= 16: 262 sizes.add(size) 263 for size in sizes: 264 substDict = { 265 "class_name" : "MicroLdrNeon%dUop" % size, 266 "targs" : type 267 } 268 exec_output += MicroNeonMemExecDeclare.subst(substDict) 269 substDict["class_name"] = "MicroStrNeon%dUop" % size 270 exec_output += MicroNeonMemExecDeclare.subst(substDict) 271 size += eSize 272}}; 273 274//////////////////////////////////////////////////////////////////// 275// 276// Neon (de)interlacing microops 277// 278 279let {{ 280 header_output = exec_output = '' 281 for dRegs in (2, 3, 4): 282 loadConv = '' 283 unloadConv = '' 284 for dReg in range(dRegs): 285 loadConv += ''' 286 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 287 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 288 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 289 unloadConv += ''' 290 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 291 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 292 ''' % { "dReg" : dReg } 293 microDeintNeonCode = ''' 294 const unsigned dRegs = %(dRegs)d; 295 const unsigned regs = 2 * dRegs; 296 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 297 sizeof(Element); 298 union convStruct { 299 FloatRegBits cRegs[regs]; 300 Element elements[dRegs * perDReg]; 301 } conv1, conv2; 302 303 %(loadConv)s 304 305 unsigned srcElem = 0; 306 for (unsigned destOffset = 0; 307 destOffset < perDReg; destOffset++) { 308 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 309 conv2.elements[dReg * perDReg + destOffset] = 310 conv1.elements[srcElem++]; 311 } 312 } 313 314 %(unloadConv)s 315 ''' % { "dRegs" : dRegs, 316 "loadConv" : loadConv, 317 "unloadConv" : unloadConv } 318 microDeintNeonIop = \ 319 InstObjParams('deintneon%duop' % (dRegs * 2), 320 'MicroDeintNeon%dUop' % (dRegs * 2), 321 'MicroNeonMixOp', 322 { 'predicate_test': predicateTest, 323 'code' : microDeintNeonCode }, 324 ['IsMicroop']) 325 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 326 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 327 328 loadConv = '' 329 unloadConv = '' 330 for dReg in range(dRegs): 331 loadConv += ''' 332 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 333 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 334 ''' % { "dReg" : dReg } 335 unloadConv += ''' 336 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 337 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 338 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 339 microInterNeonCode = ''' 340 const unsigned dRegs = %(dRegs)d; 341 const unsigned regs = 2 * dRegs; 342 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 343 sizeof(Element); 344 union convStruct { 345 FloatRegBits cRegs[regs]; 346 Element elements[dRegs * perDReg]; 347 } conv1, conv2; 348 349 %(loadConv)s 350 351 unsigned destElem = 0; 352 for (unsigned srcOffset = 0; 353 srcOffset < perDReg; srcOffset++) { 354 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 355 conv2.elements[destElem++] = 356 conv1.elements[dReg * perDReg + srcOffset]; 357 } 358 } 359 360 %(unloadConv)s 361 ''' % { "dRegs" : dRegs, 362 "loadConv" : loadConv, 363 "unloadConv" : unloadConv } 364 microInterNeonIop = \ 365 InstObjParams('interneon%duop' % (dRegs * 2), 366 'MicroInterNeon%dUop' % (dRegs * 2), 367 'MicroNeonMixOp', 368 { 'predicate_test': predicateTest, 369 'code' : microInterNeonCode }, 370 ['IsMicroop']) 371 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 372 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 373}}; 374 375let {{ 376 exec_output = '' 377 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 378 for dRegs in (2, 3, 4): 379 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 380 substDict = { "class_name" : Name, "targs" : type } 381 exec_output += MicroNeonExecDeclare.subst(substDict) 382 Name = "MicroInterNeon%dUop" % (dRegs * 2) 383 substDict = { "class_name" : Name, "targs" : type } 384 exec_output += MicroNeonExecDeclare.subst(substDict) 385}}; 386 387//////////////////////////////////////////////////////////////////// 388// 389// Neon microops to pack/unpack a single lane 390// 391 392let {{ 393 header_output = exec_output = '' 394 for sRegs in 1, 2: 395 baseLoadRegs = '' 396 for reg in range(sRegs): 397 baseLoadRegs += ''' 398 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 399 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 400 ''' % { "reg0" : (2 * reg + 0), 401 "reg1" : (2 * reg + 1) } 402 for dRegs in range(sRegs, 5): 403 unloadRegs = '' 404 loadRegs = baseLoadRegs 405 for reg in range(dRegs): 406 loadRegs += ''' 407 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 408 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 409 ''' % { "reg" : reg } 410 unloadRegs += ''' 411 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 412 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 413 ''' % { "reg" : reg } 414 microUnpackNeonCode = ''' 415 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 416 sizeof(Element); 417 418 union SourceRegs { 419 FloatRegBits fRegs[2 * %(sRegs)d]; 420 Element elements[%(sRegs)d * perDReg]; 421 } sourceRegs; 422 423 union DestReg { 424 FloatRegBits fRegs[2]; 425 Element elements[perDReg]; 426 } destRegs[%(dRegs)d]; 427 428 %(loadRegs)s 429 430 for (unsigned i = 0; i < %(dRegs)d; i++) { 431 destRegs[i].elements[lane] = sourceRegs.elements[i]; 432 } 433 434 %(unloadRegs)s 435 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 436 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 437 438 microUnpackNeonIop = \ 439 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 440 'MicroUnpackNeon%dto%dUop' % 441 (sRegs * 2, dRegs * 2), 442 'MicroNeonMixLaneOp', 443 { 'predicate_test': predicateTest, 444 'code' : microUnpackNeonCode }, 445 ['IsMicroop']) 446 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 447 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 448 449 for sRegs in 1, 2: 450 loadRegs = '' 451 for reg in range(sRegs): 452 loadRegs += ''' 453 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 454 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 455 ''' % { "reg0" : (2 * reg + 0), 456 "reg1" : (2 * reg + 1) } 457 for dRegs in range(sRegs, 5): 458 unloadRegs = '' 459 for reg in range(dRegs): 460 unloadRegs += ''' 461 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 462 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 463 ''' % { "reg" : reg } 464 microUnpackAllNeonCode = ''' 465 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 466 sizeof(Element); 467 468 union SourceRegs { 469 FloatRegBits fRegs[2 * %(sRegs)d]; 470 Element elements[%(sRegs)d * perDReg]; 471 } sourceRegs; 472 473 union DestReg { 474 FloatRegBits fRegs[2]; 475 Element elements[perDReg]; 476 } destRegs[%(dRegs)d]; 477 478 %(loadRegs)s 479 480 for (unsigned i = 0; i < %(dRegs)d; i++) { 481 for (unsigned j = 0; j < perDReg; j++) 482 destRegs[i].elements[j] = sourceRegs.elements[i]; 483 } 484 485 %(unloadRegs)s 486 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 487 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 488 489 microUnpackAllNeonIop = \ 490 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 491 'MicroUnpackAllNeon%dto%dUop' % 492 (sRegs * 2, dRegs * 2), 493 'MicroNeonMixOp', 494 { 'predicate_test': predicateTest, 495 'code' : microUnpackAllNeonCode }, 496 ['IsMicroop']) 497 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 498 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 499 500 for dRegs in 1, 2: 501 unloadRegs = '' 502 for reg in range(dRegs): 503 unloadRegs += ''' 504 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 505 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 506 ''' % { "reg0" : (2 * reg + 0), 507 "reg1" : (2 * reg + 1) } 508 for sRegs in range(dRegs, 5): 509 loadRegs = '' 510 for reg in range(sRegs): 511 loadRegs += ''' 512 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 513 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 514 ''' % { "reg" : reg } 515 microPackNeonCode = ''' 516 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 517 sizeof(Element); 518 519 union SourceReg { 520 FloatRegBits fRegs[2]; 521 Element elements[perDReg]; 522 } sourceRegs[%(sRegs)d]; 523 524 union DestRegs { 525 FloatRegBits fRegs[2 * %(dRegs)d]; 526 Element elements[%(dRegs)d * perDReg]; 527 } destRegs; 528 529 %(loadRegs)s 530 531 for (unsigned i = 0; i < %(sRegs)d; i++) { 532 destRegs.elements[i] = sourceRegs[i].elements[lane]; 533 } 534 535 %(unloadRegs)s 536 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 537 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 538 539 microPackNeonIop = \ 540 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 541 'MicroPackNeon%dto%dUop' % 542 (sRegs * 2, dRegs * 2), 543 'MicroNeonMixLaneOp', 544 { 'predicate_test': predicateTest, 545 'code' : microPackNeonCode }, 546 ['IsMicroop']) 547 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 548 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 549}}; 550 551let {{ 552 exec_output = '' 553 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 554 for sRegs in 1, 2: 555 for dRegs in range(sRegs, 5): 556 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 557 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 558 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 559 Name = format % { "sRegs" : sRegs * 2, 560 "dRegs" : dRegs * 2 } 561 substDict = { "class_name" : Name, "targs" : type } 562 exec_output += MicroNeonExecDeclare.subst(substDict) 563}}; 564 565//////////////////////////////////////////////////////////////////// 566// 567// Integer = Integer op Immediate microops 568// 569 570let {{ 571 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 572 'MicroIntImmOp', 573 {'code': 'Ra = Rb + imm;', 574 'predicate_test': predicateTest}, 575 ['IsMicroop']) 576 577 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 578 'MicroIntOp', 579 {'code': 'Ra = Rb + Rc;', 580 'predicate_test': predicateTest}, 581 ['IsMicroop']) 582 583 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 584 'MicroIntImmOp', 585 {'code': 'Ra = Rb - imm;', 586 'predicate_test': predicateTest}, 587 ['IsMicroop']) 588 589 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 590 MicroIntImmDeclare.subst(microSubiUopIop) + \ 591 MicroIntDeclare.subst(microAddUopIop) 592 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 593 MicroIntImmConstructor.subst(microSubiUopIop) + \ 594 MicroIntConstructor.subst(microAddUopIop) 595 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 596 PredOpExecute.subst(microSubiUopIop) + \ 597 PredOpExecute.subst(microAddUopIop) 598}}; 599 600let {{ 601 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 602 header_output = MacroMemDeclare.subst(iop) 603 decoder_output = MacroMemConstructor.subst(iop) 604 605 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 606 header_output += VMemMultDeclare.subst(iop) 607 decoder_output += VMemMultConstructor.subst(iop) 608 609 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 610 header_output += VMemSingleDeclare.subst(iop) 611 decoder_output += VMemSingleConstructor.subst(iop) 612 613 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 614 header_output += VMemMultDeclare.subst(iop) 615 decoder_output += VMemMultConstructor.subst(iop) 616 617 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 618 header_output += VMemSingleDeclare.subst(iop) 619 decoder_output += VMemSingleConstructor.subst(iop) 620 621 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 622 header_output += MacroVFPMemDeclare.subst(vfpIop) 623 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 624}};
|